3654 lines
114 KiB
C#
3654 lines
114 KiB
C#
|
using LibrarySDR;
|
|||
|
using LibrarySDR.Enums;
|
|||
|
using LibrarySDR.Responses;
|
|||
|
using NAudio.Wave;
|
|||
|
using Nini.Config;
|
|||
|
using SafeMobileLib;
|
|||
|
using SafeMobileLib.Helpers;
|
|||
|
using SafeMobileLib.Registration;
|
|||
|
using SafeMobileLib.Tetra;
|
|||
|
using SharedUI;
|
|||
|
using System;
|
|||
|
using System.Collections;
|
|||
|
using System.Collections.Generic;
|
|||
|
using System.ComponentModel;
|
|||
|
using System.Diagnostics;
|
|||
|
using System.Drawing;
|
|||
|
using System.IO;
|
|||
|
using System.IO.Ports;
|
|||
|
using System.Net;
|
|||
|
using System.Net.Sockets;
|
|||
|
using System.Text;
|
|||
|
using System.Threading;
|
|||
|
using System.Threading.Tasks;
|
|||
|
using System.Windows.Forms;
|
|||
|
using Telerik.WinControls;
|
|||
|
using Telerik.WinControls.UI;
|
|||
|
using Tetra_GW.Helpers;
|
|||
|
using smutils = SafeMobileLib.Utils;
|
|||
|
|
|||
|
namespace Tetra_GW
|
|||
|
{
|
|||
|
//+MCTGDR – Command for reading DMO talkgroups +MCTGDR: 1,DMO TG1,600101,420000000,1,1,DMO Folder1
|
|||
|
// 2,DMO TG2,457,421000000,1,1,DMO Folder1
|
|||
|
|
|||
|
//+CTOM - TMO/DMO Operating mode
|
|||
|
// LIP - Location Information Protocol
|
|||
|
// DMO - Direct Mode Operations
|
|||
|
// TMO - Trunked Mode Operations(also known as V+D for Voice + Data)
|
|||
|
// TG - Talkgroup
|
|||
|
//ISSI - Individual Short Subscriber Identity
|
|||
|
// SDS - Short Data Service
|
|||
|
//SDS-TL - SDS Transport Layer(provides end-to-end delivery acknowledgement)
|
|||
|
//SSI - Short Subscriber Identity
|
|||
|
//DM-MS - MS operating in DMO
|
|||
|
// TSI - Tetra Subscriber Identit
|
|||
|
|
|||
|
public partial class MainForm : RadForm
|
|||
|
{
|
|||
|
private System.Threading.Timer _memoryCheckTimer;
|
|||
|
|
|||
|
private InterthreadMessageQueue<Tuple<string, string>> MessageQueue;
|
|||
|
private bool stopMessageConsume = false;
|
|||
|
|
|||
|
private enum CallState { Idle, InProgress, HangTime };
|
|||
|
private LIPDecoder lipDecoder = new LIPDecoder();
|
|||
|
private Int64 ISSI = 0;
|
|||
|
private Int32 BAUD_RATE = ConfigHelper.BaudRate; //9600 //38400 //115200
|
|||
|
private static Int32 AREA = ConfigHelper.Area;
|
|||
|
|
|||
|
#region variables
|
|||
|
private CallState callState = CallState.Idle;
|
|||
|
private BindingList<String> eventsList = new BindingList<String>();
|
|||
|
private Gateway currentGateway = null;
|
|||
|
private RadioGateway currentRadioGw;
|
|||
|
System.Timers.Timer rebootCheck;
|
|||
|
|
|||
|
private volatile String[] ports;
|
|||
|
private Hashtable htSU = new Hashtable();
|
|||
|
private UdpMulticast udpMulticast;
|
|||
|
private String lastLat = "", lastLng = "", SUID = "";
|
|||
|
private Hashtable portHT = new Hashtable();
|
|||
|
private volatile bool _shouldStop = false;
|
|||
|
private volatile bool _isConnected = false;
|
|||
|
private volatile int counter = 0;
|
|||
|
private volatile bool keepAlive = false;
|
|||
|
private volatile bool needToRegister = false;
|
|||
|
private volatile int intRegister = 0;
|
|||
|
System.Threading.Timer _gatewayStatusTimer = null;
|
|||
|
private string radioMesageError = "Fail to communicate with radio";
|
|||
|
private string GWID = "0";
|
|||
|
private string RadioGwId = "0";
|
|||
|
private string callerID = null;
|
|||
|
private string callStatus = "1"; //init call
|
|||
|
private string _callType = null;
|
|||
|
private string groupID = null;
|
|||
|
private string callInstance = "1";
|
|||
|
bool isDMO = true;
|
|||
|
bool hasPresenceCheck = true;
|
|||
|
int msgReceived = 0;
|
|||
|
|
|||
|
#endregion variables
|
|||
|
|
|||
|
#region voice variables
|
|||
|
public volatile WaveIn waveInClass = null;
|
|||
|
public volatile WaveOut waveOutClass = null;
|
|||
|
|
|||
|
private volatile BufferedWaveProvider buffWaveProvider = null;
|
|||
|
public int selectedOUTDevice;
|
|||
|
public string selectedOUTDeviceName = " ";
|
|||
|
|
|||
|
public int selectedINDevice;
|
|||
|
public string selectedINDeviceName = " ";
|
|||
|
|
|||
|
private string voiceMulticastIP4Send;
|
|||
|
private string voiceMulticastIP4Recv;
|
|||
|
|
|||
|
private UdpMulticast udp4VoiceSend;
|
|||
|
private UdpMulticast udp4VoiceRecv;
|
|||
|
|
|||
|
private bool PTTbusy = false;
|
|||
|
private bool isPortable = false;
|
|||
|
#endregion voice
|
|||
|
|
|||
|
#region constructor
|
|||
|
public MainForm()
|
|||
|
{
|
|||
|
InitializeComponent();
|
|||
|
|
|||
|
stopMessageConsume = false;
|
|||
|
Version v = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version;
|
|||
|
SafeMobileLib.Utils.WriteLine("Version: " + v.ToString());
|
|||
|
this.Text += " - v." + v.ToString();
|
|||
|
|
|||
|
SafeMobileLib.Utils.WriteLine("Tetra Gateway. SafeMobile 2012-2019", ConsoleColor.Magenta);
|
|||
|
SafeMobileLib.Utils.WriteLine("");
|
|||
|
|
|||
|
rcpSettings.Collapse();
|
|||
|
|
|||
|
// set datasource for events
|
|||
|
rlvEvents.DataSource = null;
|
|||
|
rlvEvents.DataSource = eventsList;
|
|||
|
|
|||
|
btConnect.Enabled = false;
|
|||
|
//lbUpdateVAL.Text = "Not available";
|
|||
|
//lbUpdateVAL.ForeColor = Color.Blue;
|
|||
|
}
|
|||
|
#endregion constructor
|
|||
|
|
|||
|
#region voice Methods
|
|||
|
private void SendALLcallACK2SD(string _seqID)
|
|||
|
{
|
|||
|
string test = "#121#" + GWID + "." + RadioGwId + "#1#";
|
|||
|
SendOnMsgBus(_seqID, test);
|
|||
|
|
|||
|
SafeMobileLib.Utils.WriteLine("\n\n########### **************** ALL CALL VOICE :" + voiceMulticastIP4Recv);
|
|||
|
SafeMobileLib.Utils.WriteLine("########### **************** " + GWID + " | " + RadioGwId + " | \n\n");
|
|||
|
|
|||
|
PTTbusy = true;
|
|||
|
//start voice buss for send
|
|||
|
udp4VoiceRecv = new UdpMulticast(voiceMulticastIP4Recv, ConfigHelper.voicePort);
|
|||
|
udp4VoiceRecv.OnNewDataRecv += new UdpMulticast.newData4Send(udp4VoiceRecv_OnNewDataRecv);
|
|||
|
udp4VoiceRecv.StartListen();
|
|||
|
}
|
|||
|
|
|||
|
private void SendPrivateCallACK2SD(string _seqID)
|
|||
|
{
|
|||
|
string test = "#122#" + GWID + "." + RadioGwId + "#1#";
|
|||
|
SendOnMsgBus(_seqID, test);
|
|||
|
|
|||
|
PTTbusy = true;
|
|||
|
//start voice buss for send
|
|||
|
|
|||
|
udp4VoiceRecv = new UdpMulticast(voiceMulticastIP4Recv, ConfigHelper.voicePort);
|
|||
|
udp4VoiceRecv.OnNewDataRecv += new UdpMulticast.newData4Send(udp4VoiceRecv_OnNewDataRecv);
|
|||
|
udp4VoiceRecv.StartListen();
|
|||
|
}
|
|||
|
|
|||
|
private void SendGroupCallACK2SD(string _seqID)
|
|||
|
{
|
|||
|
string test = "#123#" + GWID + "." + RadioGwId + "#1#";
|
|||
|
SendOnMsgBus(_seqID, test);
|
|||
|
|
|||
|
PTTbusy = true;
|
|||
|
//start voice buss for send
|
|||
|
|
|||
|
udp4VoiceRecv = new UdpMulticast(voiceMulticastIP4Recv, ConfigHelper.voicePort);
|
|||
|
udp4VoiceRecv.OnNewDataRecv += new UdpMulticast.newData4Send(udp4VoiceRecv_OnNewDataRecv);
|
|||
|
udp4VoiceRecv.StartListen();
|
|||
|
}
|
|||
|
|
|||
|
public void StartnVoice()
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
if (waveOutClass != null)
|
|||
|
{
|
|||
|
waveOutClass.Dispose();
|
|||
|
waveOutClass = null;
|
|||
|
}
|
|||
|
|
|||
|
if (waveInClass != null)
|
|||
|
{
|
|||
|
waveInClass.DataAvailable -= waveInClass_DataAvailable;
|
|||
|
waveInClass.Dispose();
|
|||
|
waveInClass = null;
|
|||
|
}
|
|||
|
|
|||
|
//selectedINDevice = selectedOUTDevice = 0;
|
|||
|
if ((selectedINDevice != -1) && (selectedOUTDevice != -1))
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
NAudio.Wave.WaveFormat waveFormat = new NAudio.Wave.WaveFormat(8000, 16, 1);
|
|||
|
// Instantiate waveOut
|
|||
|
WaveOut waveOutClass = new WaveOut();
|
|||
|
waveOutClass.DeviceNumber = selectedOUTDevice;
|
|||
|
buffWaveProvider = new BufferedWaveProvider(waveFormat);
|
|||
|
waveOutClass.Init(buffWaveProvider);
|
|||
|
waveOutClass.Play();
|
|||
|
|
|||
|
// Instatiate waveIn
|
|||
|
|
|||
|
try
|
|||
|
{
|
|||
|
waveInClass = new WaveIn();
|
|||
|
waveInClass.DeviceNumber = selectedINDevice;
|
|||
|
waveInClass.BufferMilliseconds = 32;
|
|||
|
waveInClass.DataAvailable += waveInClass_DataAvailable;
|
|||
|
waveInClass.WaveFormat = waveFormat;
|
|||
|
waveInClass?.StartRecording();
|
|||
|
}
|
|||
|
catch (NAudio.MmException ex)
|
|||
|
{
|
|||
|
Console.WriteLine(ex.ToString());
|
|||
|
}
|
|||
|
|
|||
|
SafeMobileLib.Utils.WriteLine("Init new WAVE module", ConsoleColor.Magenta);
|
|||
|
}
|
|||
|
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("Error to start voice for ALL call" + ex.ToString(), ConsoleColor.Red);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("StartnVoice Exception: " + ex.ToString(), ConsoleColor.Red);
|
|||
|
SM.Debug("StartnVoice: " + ex.ToString());
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
private void OnCallStartedHandler()
|
|||
|
{
|
|||
|
AddEvent($"Incomming {(_callType.Equals("102") ? "private" : "group")} call from radio id {callerID}" +
|
|||
|
$"{(_callType.Equals("103") ? " on group " + groupID : "")}");
|
|||
|
|
|||
|
string message = "#125#" + GWID + "." + RadioGwId + "." + callerID.ToString() + "#" + callStatus + "#" + _callType + "#" + groupID + "#";
|
|||
|
SendOnMsgBus("0.0", message);
|
|||
|
PTTbusy = true;
|
|||
|
isPortable = true;
|
|||
|
}
|
|||
|
|
|||
|
private void OnCallHangTimeHandler()
|
|||
|
{
|
|||
|
if (callerID == null || _callType == null || groupID == null)
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("Empty info when receiving CallEnd", ConsoleColor.Yellow);
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
string message = "#125#" + GWID + "." + RadioGwId + "." + callerID.ToString() + "#" + "2" + "#" + _callType + "#" + groupID + "#";
|
|||
|
SendOnMsgBus("0.0", message);
|
|||
|
|
|||
|
// TETRA is not available to init a call while in hangtime
|
|||
|
PTTbusy = false;
|
|||
|
isPortable = false;
|
|||
|
|
|||
|
AddEvent($"Call from radio id {callerID} {(_callType.Equals("103") ? " on group " + groupID : "")} is in hangtime");
|
|||
|
}
|
|||
|
|
|||
|
private void OnCallEndedHandler()
|
|||
|
{
|
|||
|
if (callerID == null || _callType == null || groupID == null)
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("Empty info when receiving CallEnd", ConsoleColor.Yellow);
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
string message = "#125#" + GWID + "." + RadioGwId + "." + callerID.ToString() + "#" + "3" + "#" + _callType + "#" + groupID + "#";
|
|||
|
SendOnMsgBus("0.0", message);
|
|||
|
|
|||
|
AddEvent($"Call from radio id {callerID} {(_callType.Equals("103") ? " on group " + groupID : "")} has ended");
|
|||
|
}
|
|||
|
#endregion
|
|||
|
|
|||
|
#region form methods
|
|||
|
|
|||
|
private void MainForm_Load(object sender, EventArgs e)
|
|||
|
{
|
|||
|
ContextMenu contextMenu = new ContextMenu();
|
|||
|
contextMenu.MenuItems.Add("Check for updates...", (s, e2) =>
|
|||
|
{
|
|||
|
UpdateForm uf = new UpdateForm(App.GW_TETRA, true) { IsDevelop = Utils.isDevelop };
|
|||
|
uf.Show();
|
|||
|
});
|
|||
|
|
|||
|
contextMenu.MenuItems.Add("Exit", (s, e2) => CloseApp());
|
|||
|
notifyIcon1.ContextMenu = contextMenu;
|
|||
|
|
|||
|
// check for a new version if available
|
|||
|
if (Utils.autoupdate)
|
|||
|
CheckForUpdate();
|
|||
|
|
|||
|
|
|||
|
// update ui for not connected state
|
|||
|
OnRegistrationStatusChanged(RegistrationStatus.NotConnected);
|
|||
|
|
|||
|
// register for registration changed event
|
|||
|
this.OnRegistrationCompleted += OnRegistrationResponseHandler;
|
|||
|
|
|||
|
Register();
|
|||
|
stopMessageConsume = false;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
private async void Register()
|
|||
|
{
|
|||
|
RegistrationResponse regResponse = await RegistrationHelper.RegisterGateway(ConfigHelper.APPLICATION_SERVER_IP, ConfigHelper.regPort);
|
|||
|
// raise event for registration completed
|
|||
|
OnRegistrationCompleted?.Invoke(regResponse);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
#region REGISTRATION HANDLER
|
|||
|
private void OnRegistrationResponseHandler(RegistrationResponse regResponse)
|
|||
|
{
|
|||
|
this.Invoke((MethodInvoker)delegate ()
|
|||
|
{
|
|||
|
switch (regResponse.RegistrationStatus)
|
|||
|
{
|
|||
|
case RegistrationCode.ServerUnreachable:
|
|||
|
onRegistrationServerUnreachable();
|
|||
|
break;
|
|||
|
case RegistrationCode.Unauthorized:
|
|||
|
onRegistraionUnauthorized();
|
|||
|
break;
|
|||
|
case RegistrationCode.Registered:
|
|||
|
onRegistrationCompleted(regResponse);
|
|||
|
break;
|
|||
|
|
|||
|
}
|
|||
|
});
|
|||
|
}
|
|||
|
|
|||
|
private void onRegistrationServerUnreachable()
|
|||
|
{
|
|||
|
DisplayMessageBox("Application Server is unreachable. Please check internet connection and the application server IP in the configuration file.",
|
|||
|
"App Server Unreachable", RadMessageIcon.Error);
|
|||
|
|
|||
|
Application.Exit();
|
|||
|
}
|
|||
|
|
|||
|
private void onRegistraionUnauthorized()
|
|||
|
{
|
|||
|
DisplayMessageBox("Please register this gateway in the admin module.", "Unauthorized gateway", RadMessageIcon.Exclamation);
|
|||
|
|
|||
|
Application.Exit();
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
private void DisplayMessageBox(String message, String title, RadMessageIcon boxType)
|
|||
|
{
|
|||
|
RadMessageBox.Instance.Dispose();
|
|||
|
RadMessageBox.SetThemeName("TelerikMetroBlue");
|
|||
|
RadMessageBox.Instance.TopMost = true;
|
|||
|
RadMessageBox.Instance.TopLevel = true;
|
|||
|
RadMessageBox.Show(this, "Application Server is unreachable. Please check internet connection and the application server IP in the configuration file.",
|
|||
|
"App Server Unreachable", MessageBoxButtons.OK, RadMessageIcon.Error);
|
|||
|
RadMessageBox.Instance.TopMost = false;
|
|||
|
RadMessageBox.Instance.TopLevel = false;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
private void onRegistrationCompleted(RegistrationResponse response)
|
|||
|
{
|
|||
|
String currentIP = "127.0.0.1";
|
|||
|
|
|||
|
// this gateway is on other computer than the application server is
|
|||
|
if (!ConfigHelper.APPLICATION_SERVER_IP.Equals("127.0.0.1"))
|
|||
|
currentIP = RegistrationHelper.GatewayIP;
|
|||
|
|
|||
|
// update values for Message bus, database received from AppServer
|
|||
|
ConfigHelper.DB_IP = response.DataBaseServerIP;
|
|||
|
ConfigHelper.DB_passwd = response.DataBasePassword;
|
|||
|
ConfigHelper.DB_port = response.DataBasePort + "";
|
|||
|
ConfigHelper.DB_schema = response.DataBaseName;
|
|||
|
ConfigHelper.DB_user = response.DataBaseUser;
|
|||
|
ConfigHelper.messageBusIP = response.MessageBusIP;
|
|||
|
ConfigHelper.messageBusPort = response.MessageBusPort;
|
|||
|
ConfigHelper.voicePort = response.VoicePort;
|
|||
|
|
|||
|
|
|||
|
DBvehiclesManager vehManager = new DBvehiclesManager(ConfigHelper.DB_IP, ConfigHelper.DB_schema,
|
|||
|
ConfigHelper.DB_user, ConfigHelper.DB_passwd, ConfigHelper.DB_port);
|
|||
|
|
|||
|
DBgatewaysManager gatewayManager = new DBgatewaysManager(ConfigHelper.DB_IP, ConfigHelper.DB_schema,
|
|||
|
ConfigHelper.DB_user, ConfigHelper.DB_passwd, ConfigHelper.DB_port);
|
|||
|
|
|||
|
// get current gateway
|
|||
|
currentGateway = getGateway(currentIP, gatewayManager);
|
|||
|
|
|||
|
List<RadioGateway> radioGws = getRadioGWsFromDB(currentGateway.Id, gatewayManager);
|
|||
|
|
|||
|
// check if any sdr gateway is defined
|
|||
|
if (radioGws.Count == 0)
|
|||
|
{
|
|||
|
onNoRadioGatewayDefined();
|
|||
|
return;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
currentRadioGw = radioGws[0];
|
|||
|
GWID = currentRadioGw.Gw_id + "";
|
|||
|
RadioGwId = currentRadioGw.Id + "";
|
|||
|
|
|||
|
// search for radioGws with same identifier as this gateway
|
|||
|
foreach (RadioGateway rg in radioGws)
|
|||
|
{
|
|||
|
if (rg.Name.ToLower().Equals(ConfigHelper.GatewayName.ToLower()))
|
|||
|
{
|
|||
|
currentRadioGw = rg;
|
|||
|
GWID = rg.Gw_id + "";
|
|||
|
RadioGwId = rg.Id + "";
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
// remove all others gateways from the list
|
|||
|
// update values for current gateway
|
|||
|
radioGws.Clear();
|
|||
|
radioGws.Add(currentRadioGw);
|
|||
|
|
|||
|
MessageQueue = new InterthreadMessageQueue<Tuple<string,string>>();
|
|||
|
Task.Factory.StartNew(ConsumeMessage);
|
|||
|
}
|
|||
|
|
|||
|
FindPortsWorker.RunWorkerAsync();
|
|||
|
|
|||
|
if (!File.Exists(Utils.configFile))
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("Config file didn't exist. Creating it...", ConsoleColor.Yellow);
|
|||
|
|
|||
|
try
|
|||
|
{
|
|||
|
using (FileStream fs = File.Create(Utils.configFile)) { }
|
|||
|
}
|
|||
|
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("Application ended!!!! " + Utils.configFile + " could not be created. Exception: " + ex.ToString(), ConsoleColor.Red);
|
|||
|
Console.WriteLine("Press any key to exit...");
|
|||
|
Console.ReadKey();
|
|||
|
Environment.Exit(0);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
int configOutDeviceIdx = 0;
|
|||
|
int nrOfWaveOutDevices = WaveOut.DeviceCount;
|
|||
|
if (nrOfWaveOutDevices > 0)
|
|||
|
{
|
|||
|
OutputSoundList.Enabled = true;
|
|||
|
rbApplyAudioConfiguration.Enabled = true;
|
|||
|
|
|||
|
for (int i = 0; i < nrOfWaveOutDevices; i++)
|
|||
|
{
|
|||
|
WaveOutCapabilities deviceInfo = WaveOut.GetCapabilities(i);
|
|||
|
OutputSoundList.Items.Add(deviceInfo.ProductName);
|
|||
|
|
|||
|
if (deviceInfo.ProductName.Trim().StartsWith(ConfigHelper.SpeakerDeviceName))
|
|||
|
configOutDeviceIdx = i;
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
OutputSoundList.Items.Add("Please add a device");
|
|||
|
OutputSoundList.Enabled = false;
|
|||
|
rbApplyAudioConfiguration.Enabled = false;
|
|||
|
}
|
|||
|
|
|||
|
int configInDeviceIdx = 0;
|
|||
|
int nrOfWaveInDevices = WaveIn.DeviceCount;
|
|||
|
if (nrOfWaveInDevices > 0)
|
|||
|
{
|
|||
|
InputSoundList.Enabled = true;
|
|||
|
rbApplyAudioConfiguration.Enabled = true;
|
|||
|
|
|||
|
for (int i = 0; i < nrOfWaveInDevices; i++)
|
|||
|
{
|
|||
|
WaveInCapabilities deviceInfo = WaveIn.GetCapabilities(i);
|
|||
|
InputSoundList.Items.Add(deviceInfo.ProductName);
|
|||
|
|
|||
|
if (deviceInfo.ProductName.Trim().StartsWith(ConfigHelper.MicDeviceName))
|
|||
|
configInDeviceIdx = i;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
else
|
|||
|
{
|
|||
|
InputSoundList.Items.Add("Please add a device");
|
|||
|
InputSoundList.Enabled = false;
|
|||
|
rbApplyAudioConfiguration.Enabled = false;
|
|||
|
}
|
|||
|
|
|||
|
// restore previous values for sound
|
|||
|
|
|||
|
selectedINDevice = configInDeviceIdx;
|
|||
|
selectedOUTDevice = configOutDeviceIdx;
|
|||
|
InputSoundList.SelectedIndex = configInDeviceIdx;
|
|||
|
OutputSoundList.SelectedIndex = configOutDeviceIdx;
|
|||
|
|
|||
|
StartnVoice();
|
|||
|
_gatewayStatusTimer = new System.Threading.Timer(_gatewayStatusTimer_Elapsed, null, 3000, 10000);
|
|||
|
|
|||
|
//INIT UDP
|
|||
|
try
|
|||
|
{
|
|||
|
udpMulticast = new UdpMulticast(ConfigHelper.messageBusIP, ConfigHelper.messageBusPort);
|
|||
|
SafeMobileLib.Utils.WriteLine($"Starting UDP multicast listener on {ConfigHelper.messageBusIP}:{ConfigHelper.messageBusPort}");
|
|||
|
SafeMobileLib.Utils.WriteLine("ADDING LISTENER", ConsoleColor.Cyan);
|
|||
|
|
|||
|
udpMulticast.OnNewDataRecv += udpMulticast_OnNewDataRecv;
|
|||
|
udpMulticast.StartListen(ConfigHelper.localIP);
|
|||
|
|
|||
|
|
|||
|
// start voice bus for send
|
|||
|
voiceMulticastIP4Send = "224.10." + GWID.ToString() + "." + RadioGwId.ToString();
|
|||
|
udp4VoiceSend = new UdpMulticast(voiceMulticastIP4Send, ConfigHelper.voicePort);
|
|||
|
|
|||
|
// start voice bus for receive
|
|||
|
}
|
|||
|
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("Location Thread exception while joining the multicast group: " + ex.ToString(), ConsoleColor.Red);
|
|||
|
}
|
|||
|
|
|||
|
if(ConfigHelper.RestartOnMemoryLeak)
|
|||
|
_memoryCheckTimer = new System.Threading.Timer(RestartSoft, null, 5000, 5000);
|
|||
|
}
|
|||
|
#endregion
|
|||
|
|
|||
|
|
|||
|
|
|||
|
private void RestartSoft(object state)
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
Process curentProcess = Process.GetCurrentProcess();
|
|||
|
Process[] ProcessDispatchList = Process.GetProcessesByName("Tetra_GW");
|
|||
|
Process ProcessDispName = null;
|
|||
|
try
|
|||
|
{
|
|||
|
if (ProcessDispatchList.Length > 0)
|
|||
|
{
|
|||
|
if (ProcessDispatchList[0] != null) ProcessDispName = ProcessDispatchList[0];
|
|||
|
}
|
|||
|
}
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
smutils.WriteLine("Error on get proccess by name" + ex.ToString());
|
|||
|
}
|
|||
|
Process ProcessDispatch = Process.GetCurrentProcess();
|
|||
|
//ok i will put 650 Mega to include more stuff with hisotry and geofence
|
|||
|
if (ProcessDispName != null)
|
|||
|
{
|
|||
|
//Utils.WriteLine("CurentProcess:" + curentProcess.WorkingSet64 + " ProccessDispName:" + ProcessDispName.WorkingSet64, ConsoleColor.Green);
|
|||
|
//Utils.WriteLine("rResatr ameem value:" + MainForm2.RestartMEM, ConsoleColor.Green);
|
|||
|
long currentMemoryMb = curentProcess.WorkingSet64 / 1024 / 1024;
|
|||
|
if (currentMemoryMb > ConfigHelper.MaxMemoryAllowedMb)
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
smutils.WriteLine("Restart software due to memory: " + currentMemoryMb + " Mb");
|
|||
|
Process oldProcess = Process.GetCurrentProcess();
|
|||
|
oldProcess.WaitForExit(5000);
|
|||
|
System.Diagnostics.Process.Start(System.Windows.Forms.Application.ExecutablePath, "-l");
|
|||
|
oldProcess.Kill();
|
|||
|
System.Windows.Forms.Application.Exit();
|
|||
|
}
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
smutils.WriteLine("Error on restart timer:" + ex.ToString());
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
smutils.WriteLine("Error on restart thread:" + ex.ToString());
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
#region RADIO GATEWAY
|
|||
|
private Gateway getGateway(String gatewayIP, DBgatewaysManager gatewayManager)
|
|||
|
{
|
|||
|
List<Gateway> allGateways = gatewayManager.getAllGateways();
|
|||
|
|
|||
|
foreach (Gateway g in allGateways)
|
|||
|
{
|
|||
|
if (g.Ip == gatewayIP)
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("Gateway IP found in registration tabel. ID:" + g.Id, ConsoleColor.Yellow);
|
|||
|
currentGateway = g;
|
|||
|
ConfigHelper.GW_ID = g.Id;
|
|||
|
ConfigHelper.GW_IP = g.Ip;
|
|||
|
|
|||
|
// TODO update thegateway infos in the config file
|
|||
|
return g;
|
|||
|
}
|
|||
|
}
|
|||
|
return null;
|
|||
|
}
|
|||
|
|
|||
|
private List<RadioGateway> getRadioGWsFromDB(Int64 gatewayID, DBgatewaysManager gatewayManager)
|
|||
|
{
|
|||
|
List<RadioGateway> list = gatewayManager.gelAllRadioGateways(gatewayID);
|
|||
|
List<RadioGateway> listtoreturn = new List<RadioGateway>();
|
|||
|
foreach (RadioGateway g in list)
|
|||
|
listtoreturn.Add(g);
|
|||
|
|
|||
|
return listtoreturn;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
private void onNoRadioGatewayDefined()
|
|||
|
{
|
|||
|
DisplayMessageBox("No Gateway defined in the admin module for this computer. Please contact your administrator.", "No Gateway defined", RadMessageIcon.Exclamation);
|
|||
|
}
|
|||
|
#endregion
|
|||
|
|
|||
|
|
|||
|
|
|||
|
private RegistrationStatus registrationStatus;
|
|||
|
private void OnRegistrationStatusChanged(RegistrationStatus status)
|
|||
|
{
|
|||
|
registrationStatus = status;
|
|||
|
this.Invoke((MethodInvoker)delegate ()
|
|||
|
{
|
|||
|
rpConnectionStatus.BackColor = status.Color;
|
|||
|
rpConnectionStatus.Text = status.ToString();
|
|||
|
|
|||
|
if (status == RegistrationStatus.Connected)
|
|||
|
btConnect.Enabled = true;
|
|||
|
|
|||
|
AddEvent("Connection status : " + status);
|
|||
|
});
|
|||
|
}
|
|||
|
|
|||
|
private void AddEvent(String msg)
|
|||
|
{
|
|||
|
this.Invoke((MethodInvoker)delegate ()
|
|||
|
{
|
|||
|
rlvEvents.BeginEdit();
|
|||
|
eventsList.Add($"{DateTime.Now:HH:mm:ss} | {msg}");
|
|||
|
// remove first item if more thatn 200
|
|||
|
if (eventsList.Count > 200)
|
|||
|
eventsList.RemoveAt(0);
|
|||
|
rlvEvents.EndEdit();
|
|||
|
});
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
private void MainForm_Shown(object sender, EventArgs e)
|
|||
|
{
|
|||
|
ThemeResolutionService.ApplicationThemeName = "TelerikMetroBlue";
|
|||
|
}
|
|||
|
|
|||
|
private void MainForm_Resize(object sender, EventArgs e)
|
|||
|
{
|
|||
|
if (this.WindowState == FormWindowState.Minimized)
|
|||
|
{
|
|||
|
this.Visible = false;
|
|||
|
notifyIcon1.Visible = true;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
|
|||
|
{
|
|||
|
// disconnect from the radio
|
|||
|
if (registrationStatus == RegistrationStatus.Connected)
|
|||
|
btConnect.PerformClick();
|
|||
|
|
|||
|
_memoryCheckTimer?.Dispose();
|
|||
|
_memoryCheckTimer = null;
|
|||
|
|
|||
|
try
|
|||
|
{
|
|||
|
keepAlive = false;
|
|||
|
_shouldStop = true;
|
|||
|
_isConnected = false;
|
|||
|
stopMessageConsume = true;
|
|||
|
|
|||
|
if (serialPort.IsOpen)
|
|||
|
{
|
|||
|
e.Cancel = true; //cancel the form closing
|
|||
|
|
|||
|
Thread CloseDown = new Thread(new ThreadStart(CloseSerialOnExit)); //close port in new thread to avoid hang
|
|||
|
CloseDown.Start(); //close port in new thread to avoid hang
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
Console.WriteLine(ex.ToString());
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private void CloseApp()
|
|||
|
{
|
|||
|
MainForm_FormClosing(null, null);
|
|||
|
Process oldProcess = Process.GetCurrentProcess();
|
|||
|
oldProcess.Kill();
|
|||
|
Application.Exit();
|
|||
|
}
|
|||
|
|
|||
|
private async void btConnect_Click(object sender, EventArgs e)
|
|||
|
{
|
|||
|
//btConnect.Enabled = false;
|
|||
|
//btConnect.Enabled =
|
|||
|
await RadioConnectAsync();
|
|||
|
}
|
|||
|
|
|||
|
private void timer1_Tick(object sender, EventArgs e)
|
|||
|
{
|
|||
|
// btConect.PerformClick();
|
|||
|
|
|||
|
serialPort.BaudRate = BAUD_RATE;
|
|||
|
serialPort.PortName = radCBPorts.Text;
|
|||
|
SafeMobileLib.Utils.WriteLine("PortName: " + serialPort.PortName);
|
|||
|
|
|||
|
serialPort.Open();
|
|||
|
serialPort.ReadTimeout = 200;
|
|||
|
serialPort.WriteTimeout = 1;
|
|||
|
serialPort.DataBits = 8;
|
|||
|
if (Utils.isTetra)
|
|||
|
serialPort.Handshake = System.IO.Ports.Handshake.RequestToSend;
|
|||
|
else
|
|||
|
serialPort.Handshake = System.IO.Ports.Handshake.XOnXOff;
|
|||
|
|
|||
|
serialPort.Parity = System.IO.Ports.Parity.None;
|
|||
|
serialPort.StopBits = System.IO.Ports.StopBits.One;
|
|||
|
|
|||
|
SafeMobileLib.Utils.WriteLine("Serial port connection open.");
|
|||
|
//radCBPorts.Enabled = false;
|
|||
|
RegisterForSMSandGPS();
|
|||
|
|
|||
|
timer1.Stop();
|
|||
|
timer1.Enabled = false;
|
|||
|
}
|
|||
|
|
|||
|
private void RestartTimer_Tick(object sender, EventArgs e)
|
|||
|
{
|
|||
|
Process oldProcess = Process.GetCurrentProcess();
|
|||
|
oldProcess.WaitForExit(5000);
|
|||
|
|
|||
|
Process.Start(Application.ExecutablePath);
|
|||
|
Application.Exit();
|
|||
|
}
|
|||
|
|
|||
|
private void ckAutoconnect_ToggleStateChanged(object sender, StateChangedEventArgs args)
|
|||
|
{
|
|||
|
ConfigHelper.GW_Autoconnect = ckAutoconnect.Checked;
|
|||
|
ConfigHelper.SaveAutoConnect(ckAutoconnect.Checked);
|
|||
|
}
|
|||
|
|
|||
|
private void radCBPorts_SelectedIndexChanged(object sender, Telerik.WinControls.UI.Data.PositionChangedEventArgs e)
|
|||
|
{
|
|||
|
if (radCBPorts.SelectedItem != null)
|
|||
|
{
|
|||
|
lbStatusVAL.Text = "";
|
|||
|
|
|||
|
ConfigHelper.SerialPort = radCBPorts.SelectedItem.Text;
|
|||
|
ConfigHelper.SaveSerialPort(radCBPorts.SelectedItem.Text);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private void _gatewayStatusTimer_Elapsed(object obj)
|
|||
|
{
|
|||
|
if (serialPort.IsOpen)
|
|||
|
{
|
|||
|
//send Gateway On command to MSG bus
|
|||
|
|
|||
|
string seqID = "0.0";
|
|||
|
string toSend = "#500#" + GWID + "#" + RadioGwId + "#ON#";
|
|||
|
String cmdok = "#" + seqID + toSend;
|
|||
|
Int32 tmp = cmdok.Length + 1;
|
|||
|
tmp += tmp.ToString().Length;
|
|||
|
cmdok = "#" + tmp.ToString() + cmdok;
|
|||
|
|
|||
|
Encoding enc = Encoding.ASCII;
|
|||
|
byte[] buf = enc.GetBytes(cmdok);
|
|||
|
//put on multicast bus
|
|||
|
|
|||
|
SafeMobileLib.Utils.WriteLine("keep alive message sent on multicast bus: " + cmdok);
|
|||
|
udpMulticast.Send(buf, buf.Length);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private void waveInClass_DataAvailable(object sender, WaveInEventArgs e)
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
//SafeMobileLib.Utils.WriteLine(e.Buffer.ToString() + " " + e.BytesRecorded.ToString());
|
|||
|
if (PTTbusy && isPortable && e.BytesRecorded != 0)
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine($"Sending voice to dispatcher {voiceMulticastIP4Send}", ConsoleColor.Yellow);
|
|||
|
udp4VoiceSend.Send(e.Buffer, e.BytesRecorded);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("waveInClass_DataAvailable Error:" + ex.ToString(), ConsoleColor.Red);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private void udp4VoiceRecv_OnNewDataRecv(byte[] data, int dataLen)
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine($"Voice form SD on ip {voiceMulticastIP4Recv} -> soundIn: {selectedINDevice}; soundOut: {selectedOUTDevice}) ");
|
|||
|
buffWaveProvider?.AddSamples(data, 0, dataLen);
|
|||
|
}
|
|||
|
|
|||
|
catch (InvalidOperationException ex)
|
|||
|
{
|
|||
|
// Buffer is full
|
|||
|
SafeMobileLib.Utils.WriteLine("udp4VoiceRecv_OnNewDataRecv InvalidOperationException: " + ex.ToString(), ConsoleColor.Red);
|
|||
|
}
|
|||
|
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("udp4VoiceRecv_OnNewDataRecv Exception: " + ex.ToString(), ConsoleColor.Red);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private void udpMulticast_OnNewDataRecv(byte[] data, int dataLen)
|
|||
|
{
|
|||
|
string[] dataArr = null;
|
|||
|
|
|||
|
|
|||
|
try
|
|||
|
{
|
|||
|
string str = Encoding.ASCII.GetString(data, 0, dataLen);
|
|||
|
String[] tempArray = str.Trim().Split("#".ToCharArray());
|
|||
|
int gwid_recv = 0;
|
|||
|
int radio_gwid_recv = 0;
|
|||
|
|
|||
|
//SafeMobileLib.Utils.WriteLine("udpMulticast_OnNewDataRecv: " + str, ConsoleColor.Yellow);
|
|||
|
if (tempArray.Length > 3)
|
|||
|
{
|
|||
|
switch (tempArray[3])
|
|||
|
{
|
|||
|
//init all call request
|
|||
|
case "101":
|
|||
|
if (callState == CallState.Idle)
|
|||
|
{
|
|||
|
InitPrivateCall("16777215");
|
|||
|
voiceMulticastIP4Recv = tempArray[5];
|
|||
|
SendALLcallACK2SD(tempArray[2]);
|
|||
|
}
|
|||
|
|
|||
|
else
|
|||
|
{
|
|||
|
//send ack to SD
|
|||
|
string test = "#115#" + GWID + "." + RadioGwId + "#1#";
|
|||
|
SendOnMsgBus(tempArray[2], test);
|
|||
|
PTTbusy = false;
|
|||
|
//RadioStatusProp = RADIO_STATUS.FREE;
|
|||
|
//tCheckPTT = null;
|
|||
|
}
|
|||
|
break;
|
|||
|
//init private call request
|
|||
|
case "102":
|
|||
|
if (callState == CallState.Idle && tempArray[4].Split(".".ToCharArray())[2] != null)
|
|||
|
{
|
|||
|
|
|||
|
InitPrivateCall(tempArray[4].Split(".".ToCharArray())[2]);
|
|||
|
voiceMulticastIP4Recv = tempArray[5];
|
|||
|
SendPrivateCallACK2SD(tempArray[2]);
|
|||
|
}
|
|||
|
|
|||
|
else
|
|||
|
{
|
|||
|
//send ack to SD
|
|||
|
string test = "#116#" + GWID + "." + RadioGwId + "#1#";
|
|||
|
SendOnMsgBus(tempArray[2], test);
|
|||
|
PTTbusy = false;
|
|||
|
//RadioStatusProp = RADIO_STATUS.FREE;
|
|||
|
//tCheckPTT = null;
|
|||
|
}
|
|||
|
break;
|
|||
|
//init group call request
|
|||
|
case "103":
|
|||
|
if (callState == CallState.Idle && tempArray[4].Split(".".ToCharArray())[2] != null)
|
|||
|
{
|
|||
|
InitGroupCall(tempArray[4].Split(".".ToCharArray())[2]);
|
|||
|
voiceMulticastIP4Recv = tempArray[5];
|
|||
|
SendGroupCallACK2SD(tempArray[2]);
|
|||
|
}
|
|||
|
|
|||
|
else
|
|||
|
{
|
|||
|
//send ack to SD
|
|||
|
string test = "#117#" + GWID + "." + RadioGwId + "#1#";
|
|||
|
SendOnMsgBus(tempArray[2], test);
|
|||
|
PTTbusy = false;
|
|||
|
//RadioStatusProp = RADIO_STATUS.FREE;
|
|||
|
//tCheckPTT = null;
|
|||
|
}
|
|||
|
break;
|
|||
|
//terminate all call request:
|
|||
|
case "111":
|
|||
|
if (PTTbusy)
|
|||
|
{
|
|||
|
//all call faked with 16777215 id
|
|||
|
EndPrivateCall();
|
|||
|
SafeMobileLib.Utils.WriteLine("UDP4VoiceRecv - Stop Listen " + " PTT BUSY 111");
|
|||
|
udp4VoiceRecv.StopListen();
|
|||
|
string message = "#115#" + GWID + "." + RadioGwId + "#1#";
|
|||
|
|
|||
|
SendOnMsgBus(tempArray[2], message);
|
|||
|
PTTbusy = false;
|
|||
|
}
|
|||
|
|
|||
|
else
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("PTTbussy != true could not process all call stop");
|
|||
|
//send 115 failed to SD
|
|||
|
string message = "#115#" + GWID + "." + RadioGwId + "#2#";
|
|||
|
SendOnMsgBus(tempArray[2], message);
|
|||
|
}
|
|||
|
break;
|
|||
|
//terminate private call request
|
|||
|
case "112":
|
|||
|
if (PTTbusy)
|
|||
|
{
|
|||
|
EndPrivateCall();
|
|||
|
SafeMobileLib.Utils.WriteLine("UDP4VoiceRecv - Stop Listen " + " PTT Busy 112");
|
|||
|
udp4VoiceRecv.StopListen();
|
|||
|
string message = "#115#" + GWID + "." + RadioGwId + "#1#";
|
|||
|
|
|||
|
SendOnMsgBus(tempArray[2], message);
|
|||
|
PTTbusy = false;
|
|||
|
}
|
|||
|
|
|||
|
else
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("PTTbussy != true could not process private call stop");
|
|||
|
//send 115 failed to SD
|
|||
|
string message = "#116#" + GWID + "." + RadioGwId + "#2#";
|
|||
|
SendOnMsgBus(tempArray[2], message);
|
|||
|
}
|
|||
|
break;
|
|||
|
//terminate group call request
|
|||
|
case "113":
|
|||
|
if (PTTbusy == true)
|
|||
|
{
|
|||
|
EndGroupCall();
|
|||
|
SafeMobileLib.Utils.WriteLine("UDP4VoiceRecv - Stop Listen " + " PTT Busy 113");
|
|||
|
udp4VoiceRecv.StopListen();
|
|||
|
string message = "#115#" + GWID + "." + RadioGwId + "#1#";
|
|||
|
|
|||
|
SendOnMsgBus(tempArray[2], message);
|
|||
|
PTTbusy = false;
|
|||
|
}
|
|||
|
|
|||
|
else
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("PTTbussy != true could not process group call stop");
|
|||
|
//send 115 failed to SD
|
|||
|
string message = "#117#" + GWID + "." + RadioGwId + "#2#";
|
|||
|
SendOnMsgBus(tempArray[2], message);
|
|||
|
break;
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
case "142":
|
|||
|
case "143":
|
|||
|
int sched_timeGMT = 0;
|
|||
|
if (tempArray.Length > 6)
|
|||
|
sched_timeGMT = Convert.ToInt32(tempArray[6]);
|
|||
|
|
|||
|
dataArr = tempArray[4].Split(".".ToCharArray());
|
|||
|
|
|||
|
gwid_recv = Convert.ToInt32(dataArr[0]);
|
|||
|
radio_gwid_recv = Convert.ToInt32(dataArr[1]);
|
|||
|
|
|||
|
if (gwid_recv == currentGateway.Id && radio_gwid_recv == currentRadioGw.Id)//|| gwid_recv == 0)
|
|||
|
{
|
|||
|
if (sched_timeGMT <= DateTime.Now.ToUniversalTime().DateTo70Format() + 60)
|
|||
|
{
|
|||
|
AddMsgtoQueue(tempArray[2] , dataArr[2], tempArray[5]);
|
|||
|
}
|
|||
|
}
|
|||
|
break;
|
|||
|
case "154":
|
|||
|
dataArr = tempArray[4].Split(".".ToCharArray());
|
|||
|
|
|||
|
gwid_recv = Convert.ToInt32(dataArr[0]);
|
|||
|
radio_gwid_recv = Convert.ToInt32(dataArr[1]);
|
|||
|
|
|||
|
if (gwid_recv == currentGateway.Id && radio_gwid_recv == currentRadioGw.Id) //|| gwid_recv == 0)
|
|||
|
{
|
|||
|
SUID = dataArr[2];
|
|||
|
SendPollLIP(dataArr[2]);
|
|||
|
}
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine(ex.ToString(), ConsoleColor.Red);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private void notifyIcon1_MouseDoubleClick(object sender, MouseEventArgs e)
|
|||
|
{
|
|||
|
this.Visible = true;
|
|||
|
this.WindowState = FormWindowState.Normal;
|
|||
|
notifyIcon1.Visible = false;
|
|||
|
}
|
|||
|
#endregion form methods
|
|||
|
|
|||
|
#region methods
|
|||
|
|
|||
|
|
|||
|
public void SendOnMsgBus(string seqID, string test)
|
|||
|
{
|
|||
|
if (udpMulticast != null)
|
|||
|
{
|
|||
|
String cmdok = "#" + seqID + test; Int32 tmp = cmdok.Length + 1; tmp += tmp.ToString().Length; cmdok = "#" + tmp.ToString() + cmdok;
|
|||
|
Encoding enc = Encoding.ASCII; byte[] buf = enc.GetBytes(cmdok);
|
|||
|
|
|||
|
udpMulticast.Send(buf, buf.Length);
|
|||
|
SafeMobileLib.Utils.WriteLine("TX:" + cmdok);
|
|||
|
}
|
|||
|
|
|||
|
else
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("SendOnMsgBuss Error!!! MessageBusHandler messagebus =null", ConsoleColor.Red);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
static byte sms_seq_id = 1;
|
|||
|
public void SendSMSToRadio(String SUID, String messageBody)
|
|||
|
{
|
|||
|
//SafeMobileLib.Utils.WriteLine("++++++++++Send SMS to SU " + SUID);
|
|||
|
// send sms
|
|||
|
try
|
|||
|
{
|
|||
|
SendATCommand(CreateSMSATCommand(SUID, messageBody));
|
|||
|
|
|||
|
SafeMobileLib.Utils.WriteLine("»»» SMS [" + messageBody + "] sent to " + SUID + " [msg id " + sms_seq_id + "]");
|
|||
|
AddEvent("»»» SMS [" + messageBody + "] sent to " + SUID + " [msg id " + sms_seq_id + "]");
|
|||
|
}
|
|||
|
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("SendSMSToRadio Exception:" + ex.ToString(), ConsoleColor.Red);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private String CreateSMSATCommand(String SUID, String messageBody)
|
|||
|
{
|
|||
|
string smsTXT = "";
|
|||
|
|
|||
|
for (int i = 0; i < messageBody.Length; i++)
|
|||
|
{
|
|||
|
smsTXT += Byte2Str(messageBody[i]);
|
|||
|
}
|
|||
|
string line = "AT+CMGS=" + SUID + ",1,0," + (messageBody.Length + 4) * 8 + SerialKey.CR + "82020101" + smsTXT + SerialKey.CTRLZ;
|
|||
|
|
|||
|
return line;
|
|||
|
}
|
|||
|
|
|||
|
public void SendATCommand(String command)
|
|||
|
{
|
|||
|
serialPort.ReadExisting();
|
|||
|
|
|||
|
serialPort.Write(command);
|
|||
|
Thread.Sleep(1000);
|
|||
|
}
|
|||
|
|
|||
|
private List<String> seqIds = new List<string>();
|
|||
|
|
|||
|
private void AddMsgtoQueue(String seqId, String suid, String message)
|
|||
|
{
|
|||
|
lock (seqIds)
|
|||
|
{
|
|||
|
if (seqIds.Contains(seqId))
|
|||
|
{
|
|||
|
// already in queue
|
|||
|
return;
|
|||
|
}
|
|||
|
}
|
|||
|
// compose AT cmd
|
|||
|
String atCommand = CreateSMSATCommand(suid, message);
|
|||
|
|
|||
|
lock (seqIds)
|
|||
|
{
|
|||
|
seqIds.Add(seqId);
|
|||
|
}
|
|||
|
// add command to queue
|
|||
|
MessageQueue.PostItem(new Tuple<string, string>(seqId, atCommand));
|
|||
|
SafeMobileLib.Utils.WriteLine("Posted msg: " + atCommand);
|
|||
|
}
|
|||
|
|
|||
|
private void ConsumeMessage()
|
|||
|
{
|
|||
|
while (true)
|
|||
|
{
|
|||
|
Tuple<string, string> atCommand = MessageQueue.Peek(100);
|
|||
|
if (atCommand != null)
|
|||
|
{
|
|||
|
atCommand = MessageQueue.GetItem(1);
|
|||
|
|
|||
|
SendATCommand(atCommand.Item2);
|
|||
|
|
|||
|
lock(seqIds)
|
|||
|
{
|
|||
|
seqIds.Remove(atCommand.Item1);
|
|||
|
}
|
|||
|
|
|||
|
string test = "#242#1#";
|
|||
|
String cmdok = "#" + atCommand.Item1 + test;
|
|||
|
Int32 tmp = cmdok.Length + 1;
|
|||
|
|
|||
|
tmp += tmp.ToString().Length;
|
|||
|
cmdok = "#" + tmp.ToString() + cmdok;
|
|||
|
|
|||
|
Encoding enc = Encoding.ASCII;
|
|||
|
byte[] buf = enc.GetBytes(cmdok);
|
|||
|
//send to sd new channel value
|
|||
|
udpMulticast.Send(buf, buf.Length);
|
|||
|
|
|||
|
Thread.Sleep(2000);
|
|||
|
}
|
|||
|
|
|||
|
if (stopMessageConsume)
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
public void SendPollLIP(String SUID)
|
|||
|
{
|
|||
|
// send poll
|
|||
|
try
|
|||
|
{
|
|||
|
//serialPort.ReadExisting();
|
|||
|
string line = $"AT+CMGS={SUID},1,0,45{SerialKey.CR}{SerialKey.LF}0A44CE3A340E14{SerialKey.CTRLZ}";
|
|||
|
SafeMobileLib.Utils.WriteLine("»»» POLL location request for " + SUID);
|
|||
|
serialPort.Write(line);
|
|||
|
Thread.Sleep(500);
|
|||
|
}
|
|||
|
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("SendPOLLToRadio Exception:" + ex.ToString(), ConsoleColor.Red);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private async Task<bool> RadioConnectAsync()
|
|||
|
{
|
|||
|
return await Task.Factory.StartNew<bool>(Conn);
|
|||
|
}
|
|||
|
|
|||
|
private bool Conn()
|
|||
|
{
|
|||
|
bool ret = false;
|
|||
|
if (!serialPort.IsOpen)
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
_shouldStop = false;
|
|||
|
timer1.Stop();
|
|||
|
timer1.Enabled = false;
|
|||
|
|
|||
|
serialPort.BaudRate = BAUD_RATE;
|
|||
|
serialPort.PortName = radCBPorts.Text;
|
|||
|
SafeMobileLib.Utils.WriteLine("PortName: " + serialPort.PortName);
|
|||
|
|
|||
|
serialPort.Open();
|
|||
|
serialPort.ReadTimeout = 200;
|
|||
|
serialPort.WriteTimeout = 1;
|
|||
|
serialPort.DataBits = 8;
|
|||
|
|
|||
|
if (Utils.isTetra)
|
|||
|
serialPort.Handshake = Handshake.RequestToSend;
|
|||
|
else
|
|||
|
serialPort.Handshake = Handshake.XOnXOff;
|
|||
|
|
|||
|
serialPort.Parity = Parity.None;
|
|||
|
serialPort.StopBits = StopBits.One;
|
|||
|
|
|||
|
SafeMobileLib.Utils.WriteLine("Serial port connection open.");
|
|||
|
|
|||
|
this.Invoke((MethodInvoker)delegate
|
|||
|
{
|
|||
|
OnRegistrationStatusChanged(RegistrationStatus.Connecting);
|
|||
|
|
|||
|
lbStatusVAL.Text = "Serial port opened";
|
|||
|
lbStatusVAL.ForeColor = Color.Blue;
|
|||
|
btConnect.Text = "Disconnect";
|
|||
|
btConnect.Enabled = true;
|
|||
|
|
|||
|
|
|||
|
radCBPorts.Enabled = false;
|
|||
|
});
|
|||
|
RegisterForSMSandGPS();
|
|||
|
ThreadPool.QueueUserWorkItem(state => KeepAlive());
|
|||
|
ret = true;
|
|||
|
SetRebootTimer();
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("Error on connect:" + ex.Message);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
else
|
|||
|
{
|
|||
|
_shouldStop = true;
|
|||
|
_isConnected = false;
|
|||
|
serialPort.Close();
|
|||
|
SafeMobileLib.Utils.WriteLine("Serial port connection closed.");
|
|||
|
|
|||
|
if (registrationStatus != RegistrationStatus.Disconnected)
|
|||
|
OnRegistrationStatusChanged(RegistrationStatus.Disconnected);
|
|||
|
|
|||
|
this.Invoke((MethodInvoker)delegate
|
|||
|
{
|
|||
|
radCBPorts.Enabled = true;
|
|||
|
lbStatusVAL.Text = "Serial port closed";
|
|||
|
lbStatusVAL.ForeColor = Color.Red;
|
|||
|
btConnect.Text = "Connect";
|
|||
|
btConnect.Enabled = true;
|
|||
|
});
|
|||
|
rebootCheck.Close();
|
|||
|
|
|||
|
}
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
public static readonly object locker = new object();
|
|||
|
public void KeepAlive()
|
|||
|
{
|
|||
|
while (true)
|
|||
|
{
|
|||
|
if (!_shouldStop)
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
string line = "AT\r\n";
|
|||
|
if (serialPort.IsOpen)
|
|||
|
{
|
|||
|
serialPort.WriteTimeout = 500;
|
|||
|
serialPort.Write(line);
|
|||
|
counter++;
|
|||
|
}
|
|||
|
|
|||
|
else
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("Serial port not opened");
|
|||
|
this.Invoke((MethodInvoker)delegate
|
|||
|
{
|
|||
|
lbStatusVAL.ForeColor = Color.Red;
|
|||
|
lbStatusVAL.Text = radioMesageError;
|
|||
|
btConnect.Text = "Connect";
|
|||
|
btConnect.Enabled = true;
|
|||
|
});
|
|||
|
|
|||
|
needToRegister = true;
|
|||
|
keepAlive = false;
|
|||
|
_shouldStop = true;
|
|||
|
_isConnected = false;
|
|||
|
|
|||
|
serialPort.Close();
|
|||
|
SafeMobileLib.Utils.WriteLine("COM Port not available!", ConsoleColor.Red);
|
|||
|
}
|
|||
|
}
|
|||
|
catch (InvalidOperationException ex)
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("serialWrite InvalidOperationException: " + ex.ToString(), ConsoleColor.Red);
|
|||
|
}
|
|||
|
catch (ArgumentNullException an)
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("serialWrite ArgumentNullException: " + an.ToString(), ConsoleColor.Red);
|
|||
|
}
|
|||
|
catch (TimeoutException te)
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("serialWrite TimeoutException: " + te.ToString(), ConsoleColor.Red);
|
|||
|
}
|
|||
|
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("KeepAlive Exception: " + ex.ToString(), ConsoleColor.Red);
|
|||
|
this.Invoke((MethodInvoker)delegate
|
|||
|
{
|
|||
|
lbStatusVAL.ForeColor = Color.Red;
|
|||
|
lbStatusVAL.Text = radioMesageError;
|
|||
|
btConnect.Enabled = true;
|
|||
|
|
|||
|
});
|
|||
|
|
|||
|
needToRegister = true;
|
|||
|
keepAlive = false;
|
|||
|
|
|||
|
if (!keepAlive && !_shouldStop)
|
|||
|
{
|
|||
|
int count = 0;
|
|||
|
while (count < 400 && !_shouldStop)
|
|||
|
{
|
|||
|
Thread.Sleep(25);
|
|||
|
count++;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (!_isConnected)
|
|||
|
counter++;
|
|||
|
|
|||
|
if (counter == 2)
|
|||
|
{
|
|||
|
counter = 0;
|
|||
|
|
|||
|
this.Invoke((MethodInvoker)delegate
|
|||
|
{
|
|||
|
lbStatusVAL.ForeColor = Color.Red;
|
|||
|
lbStatusVAL.Text = radioMesageError;
|
|||
|
btConnect.Enabled = true;
|
|||
|
});
|
|||
|
|
|||
|
needToRegister = true;
|
|||
|
keepAlive = false;
|
|||
|
|
|||
|
if (!keepAlive && !_shouldStop)
|
|||
|
{
|
|||
|
int count = 0;
|
|||
|
while (count < 400 && !_shouldStop)
|
|||
|
{
|
|||
|
Thread.Sleep(25);
|
|||
|
count++;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (!_shouldStop)
|
|||
|
{
|
|||
|
int count = 0;
|
|||
|
while (count < 400 && !_shouldStop)
|
|||
|
{
|
|||
|
Thread.Sleep(25);
|
|||
|
count++;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (_shouldStop)
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
///
|
|||
|
/// </summary>
|
|||
|
private void SetRebootTimer()
|
|||
|
{
|
|||
|
// Create a timer with a two second interval.
|
|||
|
rebootCheck = new System.Timers.Timer(2000);
|
|||
|
// Hook up the Elapsed event for the timer.
|
|||
|
rebootCheck.Elapsed += RebootCheck_Elapsed;
|
|||
|
rebootCheck.AutoReset = true;
|
|||
|
rebootCheck.Enabled = true;
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Checks if no msg was received from the gateway and reboots it after 20 seconds of no information
|
|||
|
/// </summary>
|
|||
|
/// <param name="sender"></param>
|
|||
|
/// <param name="e"></param>
|
|||
|
private void RebootCheck_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
|
|||
|
{
|
|||
|
msgReceived++;
|
|||
|
if (msgReceived >= 5)
|
|||
|
{
|
|||
|
string line = "AT\r\n";
|
|||
|
serialPort.WriteTimeout = 500;
|
|||
|
serialWrite(line);
|
|||
|
Thread.Sleep(300);
|
|||
|
}
|
|||
|
|
|||
|
if (msgReceived == 10)
|
|||
|
{
|
|||
|
RebootRadio();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private void RegisterForSMSandGPS()
|
|||
|
{
|
|||
|
lock (locker)
|
|||
|
{
|
|||
|
if (Utils.isTetra)
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
intRegister = 0;
|
|||
|
SafeMobileLib.Utils.WriteLine("Send AT with 3 seconds time sleep");
|
|||
|
string line = "AT\r\n";
|
|||
|
serialPort.WriteTimeout = 500;
|
|||
|
serialWrite(line);
|
|||
|
|
|||
|
Thread.Sleep(300);
|
|||
|
serialWrite(line);
|
|||
|
|
|||
|
Thread.Sleep(300);
|
|||
|
serialWrite(line);
|
|||
|
|
|||
|
// get base station ISSI
|
|||
|
serialWrite($"AT+CNUMF?{SerialKey.CR}");
|
|||
|
Thread.Sleep(300);
|
|||
|
|
|||
|
//serialPort.Write("AT+CNUM?\r");
|
|||
|
if (!isDMO)
|
|||
|
{
|
|||
|
registerTMO();
|
|||
|
Thread.Sleep(1000);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
testDMO();
|
|||
|
Thread.Sleep(1000);
|
|||
|
}
|
|||
|
|
|||
|
registerForLRRP(AREA);
|
|||
|
Thread.Sleep(1000);
|
|||
|
|
|||
|
registerForLIP(AREA);
|
|||
|
Thread.Sleep(1000);
|
|||
|
|
|||
|
|
|||
|
registerForVoice();
|
|||
|
Thread.Sleep(1000);
|
|||
|
|
|||
|
|
|||
|
registerForSMS();
|
|||
|
Thread.Sleep(1000);
|
|||
|
|
|||
|
//fortare Doru Gheorghiu
|
|||
|
//ConfirmSMS("101", 0, 0);
|
|||
|
|
|||
|
//serialPort.DiscardOutBuffer();
|
|||
|
|
|||
|
btConnect.Enabled = true;
|
|||
|
}
|
|||
|
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
this.Invoke((MethodInvoker)delegate
|
|||
|
{
|
|||
|
lbStatusVAL.ForeColor = Color.Red;
|
|||
|
lbStatusVAL.Text = radioMesageError;
|
|||
|
btConnect.Enabled = true;
|
|||
|
});
|
|||
|
|
|||
|
needToRegister = true;
|
|||
|
SafeMobileLib.Utils.WriteLine("RegisterForSMSandGPS Exception:" + ex.Message, ConsoleColor.Red);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
else
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
//SM.Debug("Send Enable RS232");
|
|||
|
serialPort.WriteTimeout = 2000;
|
|||
|
string line = "";
|
|||
|
|
|||
|
SafeMobileLib.Utils.WriteLine("Send Enable RS232");
|
|||
|
line = "XOY\r\n";
|
|||
|
serialPort.Write(line);
|
|||
|
|
|||
|
Thread.Sleep(299);
|
|||
|
SafeMobileLib.Utils.WriteLine("Finish registering", ConsoleColor.Green);
|
|||
|
SafeMobileLib.Utils.WriteLine("The Gateway is in: " + (isDMO ? "DMO" : "TMO"), ConsoleColor.Blue);
|
|||
|
try
|
|||
|
{
|
|||
|
this.Invoke((MethodInvoker)delegate { lbUpdateVAL.Text = DateTime.Now.ToString(); });
|
|||
|
}
|
|||
|
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("Failed to update timestamp in UI Exception: " + ex.Message, ConsoleColor.Red);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("RegisterForGPS Exception: " + ex.Message, ConsoleColor.Red);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
private void registerTMO()
|
|||
|
{
|
|||
|
String line = "AT+CREG=1\r\n";
|
|||
|
SafeMobileLib.Utils.WriteLine("Register in TMO with command: " + line, ConsoleColor.Cyan);
|
|||
|
serialPort.Write(line);
|
|||
|
}
|
|||
|
|
|||
|
private void testDMO()
|
|||
|
{
|
|||
|
String line = $"AT+CTDGR=?{SerialKey.CR}";
|
|||
|
SafeMobileLib.Utils.WriteLine("Testing DMO Mode... ", ConsoleColor.Magenta);
|
|||
|
serialWrite(line);
|
|||
|
}
|
|||
|
|
|||
|
private void registerForLRRP(int area)
|
|||
|
{
|
|||
|
String line = $"AT+CMGS=0,{(int)DestinationType.SSI},{area},8\r\n83{SerialKey.CTRLZ}";
|
|||
|
SafeMobileLib.Utils.WriteLine("Register for LRRP GPS with command: " + line, ConsoleColor.Cyan);
|
|||
|
serialWrite(line);
|
|||
|
}
|
|||
|
|
|||
|
private void registerForLIP(int area)
|
|||
|
{
|
|||
|
String line = $"AT+CMGS=0,{(int)DestinationType.SSI},{area},8\r\n0A{SerialKey.CTRLZ}";
|
|||
|
SafeMobileLib.Utils.WriteLine("Register for LIP GPS with command: " + line, ConsoleColor.Cyan);
|
|||
|
serialWrite(line);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
private void registerForVoice()
|
|||
|
{
|
|||
|
String line = "AT+CTSP=2,0,0\r\n";
|
|||
|
SafeMobileLib.Utils.WriteLine("Register for voice with command: " + line, ConsoleColor.Cyan);
|
|||
|
serialPort.Write(line);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
private void registerForSMS()
|
|||
|
{
|
|||
|
String line = $"AT+CMGS=0,1,0,8\r\n82{SerialKey.CTRLZ}";
|
|||
|
SafeMobileLib.Utils.WriteLine("Register for SMS with command: " + line, ConsoleColor.Cyan);
|
|||
|
serialWrite(line);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
private void serialWrite(String msg)
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("»»» " + msg);
|
|||
|
try
|
|||
|
{
|
|||
|
serialPort.Write(msg);
|
|||
|
}
|
|||
|
catch (InvalidOperationException ex)
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("serialWrite InvalidOperationException: " + ex.ToString(), ConsoleColor.Red);
|
|||
|
rebootCheck.Close();
|
|||
|
}
|
|||
|
catch (ArgumentNullException an)
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("serialWrite ArgumentNullException: " + an.ToString(), ConsoleColor.Red);
|
|||
|
rebootCheck.Close();
|
|||
|
}
|
|||
|
catch (TimeoutException te)
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("serialWrite TimeoutException: " + te.ToString(), ConsoleColor.Red);
|
|||
|
if (te.ToString().Contains("The write timed out."))
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("Gateway Is Turned OFF!!!", ConsoleColor.Red);
|
|||
|
rebootCheck.Close();
|
|||
|
}
|
|||
|
}
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private void serialWrite(byte[] data, int offset, int count)
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("»»» " + msg);
|
|||
|
try
|
|||
|
{
|
|||
|
serialPort.Write(data, offset, count);
|
|||
|
}
|
|||
|
catch(InvalidOperationException ex)
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("serialWrite InvalidOperationException: " + ex.ToString(), ConsoleColor.Red);
|
|||
|
}
|
|||
|
catch(ArgumentNullException an)
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("serialWrite ArgumentNullException: " + an.ToString(), ConsoleColor.Red);
|
|||
|
}
|
|||
|
catch (TimeoutException te)
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("serialWrite TimeoutException: " + te.ToString(), ConsoleColor.Red);
|
|||
|
if (te.ToString().Contains("The write timed out."))
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("Gateway Is Turned OFF!!!", ConsoleColor.Red);
|
|||
|
rebootCheck.Close();
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//private void DisplayReceivedData(byte[] data, int length)
|
|||
|
//{
|
|||
|
// StringBuilder saux = new StringBuilder(2048);
|
|||
|
|
|||
|
// for (int i = 0; i < length; i++)
|
|||
|
// {
|
|||
|
// saux.Append((char)data[i]);
|
|||
|
// }
|
|||
|
|
|||
|
// SafeMobileLib.Utils.WriteLine(saux.ToString());
|
|||
|
//}
|
|||
|
|
|||
|
|
|||
|
String msg = "";
|
|||
|
next_msg nm;
|
|||
|
|
|||
|
Byte[] dataRead = new Byte[2048];
|
|||
|
int startPosition = 0;
|
|||
|
|
|||
|
int restartAfterZeroMessages = 5;
|
|||
|
int numberOfZeroLengthMessages = 0;
|
|||
|
private void CheckMessage(object s, EventArgs e)
|
|||
|
{
|
|||
|
lock (locker)
|
|||
|
{
|
|||
|
if (needToRegister)
|
|||
|
{
|
|||
|
|
|||
|
needToRegister = false;
|
|||
|
RegisterForSMSandGPS();
|
|||
|
}
|
|||
|
}
|
|||
|
counter = 0;
|
|||
|
|
|||
|
this.Invoke((MethodInvoker)delegate
|
|||
|
{
|
|||
|
lbStatusVAL.ForeColor = Color.Green;
|
|||
|
lbStatusVAL.Text = "Communication with radio established";
|
|||
|
|
|||
|
if (!_isConnected)
|
|||
|
{
|
|||
|
OnRegistrationStatusChanged(RegistrationStatus.Connected);
|
|||
|
|
|||
|
}
|
|||
|
});
|
|||
|
|
|||
|
_isConnected = true;
|
|||
|
_shouldStop = false;
|
|||
|
if (serialPort.IsOpen)
|
|||
|
{
|
|||
|
|
|||
|
try
|
|||
|
{
|
|||
|
int length = serialPort.BytesToRead;
|
|||
|
serialPort.Read(dataRead, startPosition, length);
|
|||
|
startPosition += length;
|
|||
|
|
|||
|
bool hasCRLF = length > 1 && dataRead[startPosition - 2] == 13 && dataRead[startPosition - 1] == 10;
|
|||
|
if (!hasCRLF)
|
|||
|
{
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
//=============================
|
|||
|
// display received message
|
|||
|
//=============================
|
|||
|
//DisplayReceivedData(dataRead, startPosition);
|
|||
|
|
|||
|
|
|||
|
for(int i = 0; i< startPosition; i++)
|
|||
|
//foreach (Byte b in dataRead)
|
|||
|
{
|
|||
|
byte b = dataRead[i];
|
|||
|
if ((b != 10) && (b != 13))
|
|||
|
{
|
|||
|
msg += (char)b;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
if (msg.Length > 0)
|
|||
|
SafeMobileLib.Utils.WriteLine($"Received message from serial port [{msg.Length} bytes]: " + msg);
|
|||
|
|
|||
|
numberOfZeroLengthMessages = msg.Length == 0 ? (numberOfZeroLengthMessages + 1) : 0;
|
|||
|
|
|||
|
|
|||
|
if(numberOfZeroLengthMessages == restartAfterZeroMessages)
|
|||
|
{
|
|||
|
numberOfZeroLengthMessages = 0;
|
|||
|
Conn();
|
|||
|
Thread.Sleep(1200);
|
|||
|
Conn();
|
|||
|
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
try
|
|||
|
{
|
|||
|
#region TETRA
|
|||
|
if (Utils.isTetra)
|
|||
|
{
|
|||
|
if (msg.Trim().Equals("OK"))
|
|||
|
{
|
|||
|
this.Invoke((MethodInvoker)delegate
|
|||
|
{
|
|||
|
lbUpdateVAL.Text = DateTime.Now.ToString();
|
|||
|
});
|
|||
|
}
|
|||
|
|
|||
|
// parse a location report
|
|||
|
if (nm.parse && msg.Length > 2)
|
|||
|
{
|
|||
|
nm.parse = false;
|
|||
|
ParseReport(msg, nm);
|
|||
|
}
|
|||
|
//notifies if the gateway should re-register to the Mobile Radio
|
|||
|
if (msg.Contains("+MCCFG"))
|
|||
|
{
|
|||
|
Conn();
|
|||
|
Thread.Sleep(1000);
|
|||
|
Conn();
|
|||
|
}
|
|||
|
|
|||
|
if (msg.Contains("+CME ERROR"))
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("Error : " + ParseCMEError(msg), ConsoleColor.Yellow);
|
|||
|
if (ParseCMEError(msg) == "40")
|
|||
|
{
|
|||
|
isDMO = true;
|
|||
|
SafeMobileLib.Utils.WriteLine("Radio changed to DMO Mode", ConsoleColor.Red);
|
|||
|
Conn();
|
|||
|
Thread.Sleep(1000);
|
|||
|
Conn();
|
|||
|
}
|
|||
|
else if (ParseCMEError(msg) == "43")
|
|||
|
{
|
|||
|
isDMO = false;
|
|||
|
SafeMobileLib.Utils.WriteLine("Radio changed to TMO Mode", ConsoleColor.Red);
|
|||
|
Conn();
|
|||
|
Thread.Sleep(1000);
|
|||
|
Conn();
|
|||
|
}
|
|||
|
else if (ParseCMEError(msg) == "41")
|
|||
|
{
|
|||
|
MessageBox.Show("Transmissions are inhibited!!!", "MT is in TXI!!! Disable the TXI and reconnect!", MessageBoxButtons.OK);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
if (msg.Contains("+CNUMF"))
|
|||
|
{
|
|||
|
ParseCNUMF(msg);
|
|||
|
}
|
|||
|
|
|||
|
if (msg.Contains("+CTOM"))
|
|||
|
{
|
|||
|
ParseCTOM(msg);
|
|||
|
}
|
|||
|
|
|||
|
// see if it is a cmt message
|
|||
|
if (msg.Contains("CMT:"))
|
|||
|
{
|
|||
|
nm.parse = true;
|
|||
|
ParseCMT(msg);
|
|||
|
}
|
|||
|
|
|||
|
if (msg.Contains("CME") && (msg.Contains("667")))
|
|||
|
{
|
|||
|
System.Threading.Timer tCheckSTATUS = new System.Threading.Timer(ExecuteDisc, null, 500, Timeout.Infinite);
|
|||
|
}
|
|||
|
|
|||
|
if (msg.Contains("CMGS"))
|
|||
|
{
|
|||
|
intRegister++;
|
|||
|
if (intRegister == 2)
|
|||
|
{
|
|||
|
keepAlive = true;
|
|||
|
SafeMobileLib.Utils.WriteLine("Finish registering", ConsoleColor.Green);
|
|||
|
SafeMobileLib.Utils.WriteLine("The Gateway is in: " + (isDMO ? "DMO" : "TMO"), ConsoleColor.Blue);
|
|||
|
try
|
|||
|
{
|
|||
|
this.Invoke((MethodInvoker)delegate { lbUpdateVAL.Text = DateTime.Now.ToString(); });
|
|||
|
}
|
|||
|
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("Incoming call notification (init call): " + ex.Message, ConsoleColor.DarkGreen);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
#region voice stuff
|
|||
|
// Voice AT from radio
|
|||
|
// +CTICN -> Incoming call notification (init call)
|
|||
|
// +CTCC -> call connect notification
|
|||
|
// +CTXG -> call transmission granted
|
|||
|
// +CDTXC -> call transmit cease notification
|
|||
|
// +CTCR -> call release notification (end call)
|
|||
|
// +CTSDC -> Define Call Parameters
|
|||
|
|
|||
|
if (msg.Contains("CTICN"))
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("Incomming call notification (init call)", ConsoleColor.DarkGreen);
|
|||
|
|
|||
|
callerID = msg.Split(",".ToCharArray())[4];
|
|||
|
if (!string.IsNullOrEmpty(callerID) && isDMO)
|
|||
|
callerID = callerID.Remove(0, 8).TrimStart('0'); //remove MCC&MNC infront of CallerID
|
|||
|
|
|||
|
callStatus = "1"; //init call
|
|||
|
_callType = msg.Split(",".ToCharArray())[8] == "1" ? "103" : "102";
|
|||
|
groupID = msg.Split(",".ToCharArray())[11];
|
|||
|
if (!string.IsNullOrEmpty(groupID) && isDMO)
|
|||
|
groupID = groupID.Remove(0, 8).TrimStart('0'); //remove MCC&MNC infront of GroupID
|
|||
|
|
|||
|
//for private call groupID=1
|
|||
|
//if (msg.Split(",".ToCharArray())[8] == "4")
|
|||
|
//{
|
|||
|
// //_callType = "101";
|
|||
|
// groupID = "1";
|
|||
|
//}
|
|||
|
|
|||
|
OnCallStartedHandler();
|
|||
|
}
|
|||
|
|
|||
|
if (msg.Contains("CTCC"))
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("Call connect notification", ConsoleColor.DarkGreen);
|
|||
|
}
|
|||
|
|
|||
|
if (msg.Contains("CTXG"))
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("Call transmission grant", ConsoleColor.DarkGreen);
|
|||
|
|
|||
|
// parse the call instance
|
|||
|
//TODO
|
|||
|
//msg = +CTXG: 1,0,0,0
|
|||
|
int idxOfDots = msg.IndexOf(":");
|
|||
|
int idxOnFirstComma = msg.IndexOf(",");
|
|||
|
|
|||
|
callInstance = msg.Substring(idxOfDots + 1, idxOnFirstComma - idxOfDots - 1).Trim();
|
|||
|
|
|||
|
|
|||
|
if (callState == CallState.HangTime)
|
|||
|
OnCallStartedHandler();
|
|||
|
|
|||
|
callState = CallState.InProgress;
|
|||
|
}
|
|||
|
|
|||
|
if (msg.Contains("CDTXC"))
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("Call transmit cease notification (hang)", ConsoleColor.DarkGreen);
|
|||
|
|
|||
|
callState = CallState.HangTime;
|
|||
|
|
|||
|
OnCallHangTimeHandler();
|
|||
|
}
|
|||
|
|
|||
|
if (msg.Contains("CTCR"))
|
|||
|
{
|
|||
|
PTTbusy = false;
|
|||
|
SafeMobileLib.Utils.WriteLine("Call release notification (end call)", ConsoleColor.DarkGreen);
|
|||
|
|
|||
|
callState = CallState.Idle;
|
|||
|
|
|||
|
OnCallEndedHandler();
|
|||
|
}
|
|||
|
#endregion voice stuff
|
|||
|
}
|
|||
|
#endregion
|
|||
|
else
|
|||
|
{
|
|||
|
if (msg.Length > 2)
|
|||
|
{
|
|||
|
ParseBarret(msg, SUID);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
catch(Exception ex)
|
|||
|
{
|
|||
|
smutils.WriteLine("Exception on parsing serial message: " + ex.ToString());
|
|||
|
}
|
|||
|
msg = "";
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
Array.Clear(dataRead, 0, dataRead.Length);
|
|||
|
startPosition = 0;
|
|||
|
}
|
|||
|
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("error while reading from serial port: " + ex.StackTrace, ConsoleColor.Red);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
private void ForceTimer(Object state)
|
|||
|
{
|
|||
|
System.Threading.Timer tCheckSTATUS = new System.Threading.Timer(ExecuteDisc, null, 300, Timeout.Infinite);
|
|||
|
SafeMobileLib.Utils.WriteLine("Force Timer");
|
|||
|
}
|
|||
|
|
|||
|
private void ExecuteDisc(Object state)
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
// get old process and wait UP TO 5 secs then give up!
|
|||
|
Process oldProcess = Process.GetCurrentProcess();
|
|||
|
oldProcess.WaitForExit(5000);
|
|||
|
|
|||
|
Process.Start(Application.ExecutablePath);
|
|||
|
Application.Exit();
|
|||
|
}
|
|||
|
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("ExecuteDisc: " + ex.ToString(), ConsoleColor.Red);
|
|||
|
// the process did not exist - probably already closed!
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private void ExecuteConnect(Object state)
|
|||
|
{
|
|||
|
btConnect.PerformClick();
|
|||
|
SafeMobileLib.Utils.WriteLine("Force Connect");
|
|||
|
}
|
|||
|
|
|||
|
private float ProcessGPSLat(String latitude, String lat_dir)
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
long LAT, LAT2;
|
|||
|
char LAT3;
|
|||
|
long llat, grade, zec;
|
|||
|
char[] param = new char[50];
|
|||
|
String[] latList;
|
|||
|
float flat;
|
|||
|
|
|||
|
param = lat_dir.ToCharArray();
|
|||
|
if (param[0] != 'N' && param[0] != 'S')
|
|||
|
return 0;
|
|||
|
|
|||
|
//Console.WriteLine("Latitude " + latitude + " dir " + lat_dir);
|
|||
|
|
|||
|
latList = latitude.Split('.');
|
|||
|
LAT = Convert.ToInt32(latList[0]);
|
|||
|
if (latList[1].Length > 4)
|
|||
|
latList[1] = latList[1].Remove(4);
|
|||
|
LAT2 = Convert.ToInt32(latList[1]);
|
|||
|
LAT3 = param[0];
|
|||
|
|
|||
|
// process the lat and lng for display
|
|||
|
grade = (LAT / 100L);
|
|||
|
zec = (LAT % 100L) * 1000L + LAT2; // get MMMMM*1000, from MM.mmmmm by MM*1000+mmm (0-59999)
|
|||
|
zec = (zec * 100L) / 60L; // translate MMMMM*1000 to DD * 100 * 1000 (0-99998)
|
|||
|
grade = grade * 100000 + zec; // translate all to DDddddd
|
|||
|
llat = grade;
|
|||
|
|
|||
|
flat = (float)llat / 100000;
|
|||
|
|
|||
|
if (param[0] == 'S')
|
|||
|
flat = -flat;
|
|||
|
|
|||
|
if (flat < -90 || flat > 90)
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine($"[warning \"overflow lat\": flat={flat} llat={llat}]");
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
return flat;
|
|||
|
}
|
|||
|
|
|||
|
catch (Exception ee)
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("Error in ProcessGPSLat: " + ee.ToString(), ConsoleColor.Red);
|
|||
|
return 0;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private float ProcessGPSLong(String longitude, String lng_dir)
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
long LNG, LNG2;
|
|||
|
char LNG3;
|
|||
|
long llng, grade, zec;
|
|||
|
char[] param = new char[50];
|
|||
|
String[] lngList;
|
|||
|
float flong;
|
|||
|
|
|||
|
param = lng_dir.ToCharArray();
|
|||
|
if (param[0] != 'E' && param[0] != 'W')
|
|||
|
return 0;
|
|||
|
|
|||
|
lngList = longitude.Split('.');
|
|||
|
LNG = Convert.ToInt32(lngList[0]);
|
|||
|
if (lngList[1].Length > 4)
|
|||
|
lngList[1] = lngList[1].Remove(4);
|
|||
|
LNG2 = Convert.ToInt32(lngList[1]);
|
|||
|
LNG3 = param[0];
|
|||
|
|
|||
|
grade = LNG / 100; // get DD (0-90)
|
|||
|
zec = (LNG % 100L) * 1000L + LNG2; // get MMMMM*1000, from MM.mmmmm by MM*1000+mmm (0-59999)
|
|||
|
zec = (zec * 100L) / 60L; // translate MMMMM*1000 to DD * 100 * 1000 (0-99998)
|
|||
|
grade = grade * 100000 + zec; // translate all to DDddddd
|
|||
|
llng = grade;
|
|||
|
|
|||
|
flong = (float)llng / 100000;
|
|||
|
|
|||
|
if (param[0] == 'W')
|
|||
|
flong = -flong;
|
|||
|
|
|||
|
if (flong < -180 || flong > 180)
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine($"[warning \"overflow lng\": flng={flong} llng={llng}]");
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
return flong;
|
|||
|
}
|
|||
|
|
|||
|
catch (Exception ee)
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("Error in ProcessGPSLong: " + ee.ToString(), ConsoleColor.Red);
|
|||
|
return 0;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private void ParseBarret(String msg, String suid)
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
htCell_t ht = new htCell_t();
|
|||
|
ht.suid = suid;
|
|||
|
|
|||
|
String latstr = "";
|
|||
|
String directLAT = "N";
|
|||
|
String lngstr = "";
|
|||
|
String directLNG = "E";
|
|||
|
SafeMobileLib.Utils.WriteLine("Message is:X" + msg + "X");
|
|||
|
|
|||
|
if (msg.Length > 20)
|
|||
|
{
|
|||
|
latstr = msg.Substring(1, 9);
|
|||
|
directLAT = msg[10].ToString();
|
|||
|
lngstr = msg.Substring(12, 9);
|
|||
|
directLNG = msg[21].ToString();
|
|||
|
}
|
|||
|
|
|||
|
ht.lat = ProcessGPSLat(latstr, directLAT).ToString();//lat.ToString();
|
|||
|
ht.lng = ProcessGPSLong(lngstr, directLNG).ToString();
|
|||
|
ht.spd = "0";
|
|||
|
ht.location_time = DateTime.UtcNow;
|
|||
|
InsertXML(ht);
|
|||
|
}
|
|||
|
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("Error on parse location on barret: " + ex.ToString(), ConsoleColor.Red);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Parse the CME Error message received on a serial connection
|
|||
|
/// </summary>
|
|||
|
/// <param name="msg">Message containing the CME Error flag, it containg the error code</param>
|
|||
|
/// <returns></returns>
|
|||
|
private String ParseCMEError(String msg)
|
|||
|
{
|
|||
|
String[] split = msg.Split(new char[] { ':' });
|
|||
|
if (split.Length > 0)
|
|||
|
{
|
|||
|
Int16 code = 0;
|
|||
|
Int16.TryParse(split[1].Trim(), out code);
|
|||
|
|
|||
|
return ((CMEError)code).ToString();
|
|||
|
}
|
|||
|
|
|||
|
return msg;
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Parse a CNUMF message received on serial connection
|
|||
|
/// </summary>
|
|||
|
/// <param name="msg">Message containing the TETRA Identities (ITSI, PABX, PSTN, Store & Forward Service centre addresses)</param>
|
|||
|
void ParseCNUMF(string msg)
|
|||
|
{
|
|||
|
String[] splited = msg.Split(new char[] { ':' }, StringSplitOptions.RemoveEmptyEntries);
|
|||
|
|
|||
|
if (splited.Length >= 1)
|
|||
|
{
|
|||
|
|
|||
|
try
|
|||
|
{
|
|||
|
String issi = splited[1].Substring(splited[1].Length - 16, 16);
|
|||
|
ISSI = Int64.Parse(issi);
|
|||
|
|
|||
|
SafeMobileLib.Utils.WriteLine($"Radio ISSI is {ISSI}", ConsoleColor.Magenta);
|
|||
|
}
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("Exception ParseCNUMF: " + msg.ToString());
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Detects Mobil Radio Operating Mode (0 - TMO/1 - DMO/5-DM-Gateway/6-DM-Repeater
|
|||
|
/// </summary>
|
|||
|
/// <param name="msg"></param>
|
|||
|
private void ParseCTOM(string msg)
|
|||
|
{
|
|||
|
if (msg.Contains("1") && !isDMO)
|
|||
|
{
|
|||
|
isDMO = true;
|
|||
|
SafeMobileLib.Utils.WriteLine("Radio changed to DMO Mode", ConsoleColor.Red);
|
|||
|
AddEvent("Radio changed to DMO Mode");
|
|||
|
Conn();
|
|||
|
Thread.Sleep(1000);
|
|||
|
Conn();
|
|||
|
}
|
|||
|
else if (msg.Contains("0") && isDMO)
|
|||
|
{
|
|||
|
isDMO = false;
|
|||
|
SafeMobileLib.Utils.WriteLine("Radio changed to TMO Mode", ConsoleColor.Red);
|
|||
|
AddEvent("Radio changed to TMO Mode");
|
|||
|
Conn();
|
|||
|
Thread.Sleep(1000);
|
|||
|
Conn();
|
|||
|
}
|
|||
|
else if (msg.Contains("5") || msg.Contains("6"))
|
|||
|
{
|
|||
|
isDMO = false;
|
|||
|
SafeMobileLib.Utils.WriteLine("Radio changed to an unkown Mode", ConsoleColor.Red);
|
|||
|
Conn();
|
|||
|
}
|
|||
|
else
|
|||
|
SafeMobileLib.Utils.WriteLine("Operating mode is: " + (isDMO ? "DMO" : "TMO"), ConsoleColor.Blue);
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Receiving Status, Alarm, SDS type 1, 2, 3 and 4 messages (also covers SDS-TL and UDH).
|
|||
|
/// </summary>
|
|||
|
/// <param name="msg"></param>
|
|||
|
private void ParseCMT(string msg)
|
|||
|
{
|
|||
|
char[] separators = { ' ', ',' };
|
|||
|
string[] vals = msg.Split(separators);
|
|||
|
nm.src_SUID = int.Parse(vals[1]);
|
|||
|
nm.msg_len = int.Parse(vals[3]);
|
|||
|
nm.parse = true;
|
|||
|
|
|||
|
nm.suid_type = int.Parse(vals[2]);
|
|||
|
nm.data_type = DataType.SDS_TYPE_4;
|
|||
|
|
|||
|
try
|
|||
|
{
|
|||
|
if(vals.Length >= 5)
|
|||
|
nm.data_type = (DataType)Enum.Parse(typeof(DataType), vals[4]);
|
|||
|
}
|
|||
|
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("ParseCMT error: " + ex.ToString(), ConsoleColor.Red);
|
|||
|
}
|
|||
|
|
|||
|
if (nm.suid_type == 1 && nm.data_type == DataType.STATUS_MESSAGE)
|
|||
|
{
|
|||
|
EmergencyAlarm(nm.src_SUID + "");
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Parse the message that comes after the <CR> flag
|
|||
|
/// </summary>
|
|||
|
/// <param name="msg">Current parsing message that can be seen as a payload</param>
|
|||
|
/// <param name="nm">Message that contains this payload. Has informations regarding the subscriber that sent this message</param>
|
|||
|
private void ParseReport(string msg, next_msg nm)
|
|||
|
{
|
|||
|
// ellipse-3d (lat, long, angle, semi-major, semi-minor, altitude, altitude-acc?)
|
|||
|
if ((msg.Length / 2) == (nm.msg_len / 8))
|
|||
|
{
|
|||
|
string suid = nm.src_SUID.ToString();
|
|||
|
|
|||
|
int i = 0;
|
|||
|
byte b = GetNextByte(msg, ref i);
|
|||
|
|
|||
|
int pi = (int)b;
|
|||
|
|
|||
|
if (pi == (int)ProtocolIdentifier.GPSUsingSDSTL)// (byte)0x83:
|
|||
|
ParseLocation(msg, suid);
|
|||
|
else if (pi == (int)ProtocolIdentifier.SimpleTextUsingSDSTL)
|
|||
|
ParseSMS(msg, suid, nm.msg_len / 8 - 4);
|
|||
|
else if (pi == (int)ProtocolIdentifier.GPS)
|
|||
|
parseLIPLocation(msg, suid);
|
|||
|
|
|||
|
else
|
|||
|
{
|
|||
|
ParseLocation(msg, suid);
|
|||
|
SafeMobileLib.Utils.WriteLine("Warning: This is not a location protocol 0x83, ignore");
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
// LIP messages are having the lengths in bits so the first verification will always fail
|
|||
|
int i = 0;
|
|||
|
byte b = GetNextByte(msg, ref i);
|
|||
|
|
|||
|
if ((int)b == (int)ProtocolIdentifier.GPS)
|
|||
|
parseLIPLocation(msg, nm.src_SUID.ToString());
|
|||
|
else
|
|||
|
SafeMobileLib.Utils.WriteLine("ParseReport: length does not match " + msg.Length + "/2 vs " + nm.msg_len + "/8");
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
private void SU_ChangeState(string name, bool state)
|
|||
|
{
|
|||
|
UpdateSUStatus(name, state);
|
|||
|
}
|
|||
|
|
|||
|
public void UpdateSUStatus(string suid, bool status)
|
|||
|
{
|
|||
|
Byte[] receivedBytes = { 0x00, 0x00, 0x31 };
|
|||
|
if (status) receivedBytes[2] = 0x30;
|
|||
|
|
|||
|
Byte[] toSendMulticast = Utils.CreateMulticastMessage(130, suid, receivedBytes);
|
|||
|
udpMulticast.Send(toSendMulticast, toSendMulticast.Length);
|
|||
|
SafeMobileLib.Utils.WriteLine("ARS thread successfully sent data to message bus");
|
|||
|
|
|||
|
string seqID = "0.0";
|
|||
|
//build string
|
|||
|
string fullSource = "";
|
|||
|
try
|
|||
|
{
|
|||
|
|
|||
|
fullSource = currentGateway.Id.ToString() + "#" + currentRadioGw.Ip.ToString() + "#" + suid;
|
|||
|
}
|
|||
|
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
fullSource = currentGateway.Id.ToString() + "#192.168.10.60#" + suid;
|
|||
|
SafeMobileLib.Utils.WriteLine("Error on parse IP: " + ex.ToString(), ConsoleColor.Red);
|
|||
|
}
|
|||
|
|
|||
|
string test = "#139#" + fullSource + "#";
|
|||
|
String cmdok = "#" + seqID + test; Int32 tmp = cmdok.Length + 1; tmp += tmp.ToString().Length; cmdok = "#" + tmp.ToString() + cmdok;
|
|||
|
Encoding enc = Encoding.ASCII;
|
|||
|
byte[] buf = enc.GetBytes(cmdok);
|
|||
|
|
|||
|
//send to messagebus
|
|||
|
SafeMobileLib.Utils.WriteLine("Sending to MessageBus: " + cmdok);
|
|||
|
udpMulticast.Send(buf, buf.Length);
|
|||
|
|
|||
|
try
|
|||
|
{
|
|||
|
this.Invoke((MethodInvoker)delegate {
|
|||
|
lbUpdateVAL.Text = DateTime.Now.ToString();
|
|||
|
});
|
|||
|
}
|
|||
|
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("Failed to update timestamp in UI: " + ex.ToString(), ConsoleColor.Red);
|
|||
|
}
|
|||
|
|
|||
|
Thread.Sleep(100);
|
|||
|
}
|
|||
|
|
|||
|
private void ParseLocation(String message, String suid)
|
|||
|
{
|
|||
|
htCell_t ht = new htCell_t();
|
|||
|
ht.suid = suid;
|
|||
|
//ht.spd = "0";
|
|||
|
bool parsed_req_id = false, parsed_elipse = false, parsed_time = false, parse_spd = false, parse_periodic = false, parse_circle = false;
|
|||
|
int i = 12;
|
|||
|
|
|||
|
if ((htSU[suid] != null) && (!((htCell_t)htSU[suid]).state))
|
|||
|
{
|
|||
|
((htCell_t)htSU[suid]).state = true;
|
|||
|
SU_ChangeState(suid, true);
|
|||
|
}
|
|||
|
|
|||
|
else if (htSU[suid] == null)
|
|||
|
{
|
|||
|
ht.state = true;
|
|||
|
htSU.Add(suid, ht);
|
|||
|
SU_ChangeState(suid, true);
|
|||
|
}
|
|||
|
|
|||
|
while (i < msg.Length)
|
|||
|
{
|
|||
|
byte b = GetNextByte(msg, ref i);
|
|||
|
if (b == (byte)Report_Messages_Tokens_ENUM.request_id && !parsed_req_id)
|
|||
|
{
|
|||
|
b = GetNextByte(msg, ref i);
|
|||
|
DisplayReqId(b, suid);
|
|||
|
parsed_req_id = true;
|
|||
|
if (b == (byte)Request_Identifier.Periodic_report) parse_periodic = true;
|
|||
|
|
|||
|
// ARS ON OFF and emerg
|
|||
|
Boolean getoutfast = false;
|
|||
|
if (b == (byte)Request_Identifier.SU_is_powered_ON)
|
|||
|
{
|
|||
|
if (htSU[suid] != null) ((htCell_t)htSU[suid]).state = true;
|
|||
|
else
|
|||
|
{
|
|||
|
ht.state = true;
|
|||
|
htSU.Add(suid, ht);
|
|||
|
}
|
|||
|
SU_ChangeState(suid, true);
|
|||
|
getoutfast = true;
|
|||
|
AddEvent("ARS ON from radio " + suid);
|
|||
|
}
|
|||
|
|
|||
|
else if (b == (byte)Request_Identifier.SU_is_powered_OFF)
|
|||
|
{
|
|||
|
if (htSU[suid] != null) ((htCell_t)htSU[suid]).state = false;
|
|||
|
SU_ChangeState(suid, false);
|
|||
|
getoutfast = true;
|
|||
|
AddEvent("ARS OFF from radio " + suid);
|
|||
|
}
|
|||
|
else if (b == (byte)Request_Identifier.Emergency_condition_detected)
|
|||
|
{
|
|||
|
EmergencyAlarm(ht.suid);
|
|||
|
getoutfast = true;
|
|||
|
AddEvent("Emergency from radio " + suid);
|
|||
|
}
|
|||
|
|
|||
|
if (getoutfast)
|
|||
|
{
|
|||
|
//Write_htSU(suid, ht);
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
//BACK TO GPS STATE
|
|||
|
if ((b == (byte)Report_Messages_Tokens_ENUM.info_time ||
|
|||
|
b == (byte)Report_Messages_Tokens_ENUM.info_time1
|
|||
|
) && !parsed_time
|
|||
|
)
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine(Report_Messages_Tokens_ENUM.info_time + " (" + b.ToString("X") + ")");
|
|||
|
Byte[] time = new byte[5];
|
|||
|
time[0] = GetNextByte(msg, ref i);
|
|||
|
time[1] = GetNextByte(msg, ref i);
|
|||
|
time[2] = GetNextByte(msg, ref i);
|
|||
|
time[3] = GetNextByte(msg, ref i);
|
|||
|
time[4] = GetNextByte(msg, ref i);
|
|||
|
try
|
|||
|
{
|
|||
|
ht.location_time = ProcessTime(time, 0, 5);
|
|||
|
}
|
|||
|
catch(Exception ex)
|
|||
|
{
|
|||
|
smutils.WriteLine("Exception on processing time for location: " + ex.ToString(), ConsoleColor.Yellow);
|
|||
|
ht.location_time = DateTime.UtcNow;
|
|||
|
}
|
|||
|
|
|||
|
parsed_time = true;
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
if((b== (byte)Report_Messages_Tokens_ENUM.circle_2d ||
|
|||
|
b == (byte)Report_Messages_Tokens_ENUM.circle_2d1 ||
|
|||
|
b== (byte)Report_Messages_Tokens_ENUM.circle_3d ||
|
|||
|
b == (byte)Report_Messages_Tokens_ENUM.circle_3d1 ||
|
|||
|
b == (byte)Report_Messages_Tokens_ENUM.circle_3d2 ||
|
|||
|
b == (byte) Report_Messages_Tokens_ENUM.circle_3d3 ||
|
|||
|
b == (byte) Report_Messages_Tokens_ENUM.circle_3d4) && !parse_circle)
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("Circle (" + b.ToString("X") + "):");
|
|||
|
Byte[] data = new byte[4];
|
|||
|
data[0] = GetNextByte(msg, ref i);
|
|||
|
data[1] = GetNextByte(msg, ref i);
|
|||
|
data[2] = GetNextByte(msg, ref i);
|
|||
|
data[3] = GetNextByte(msg, ref i);
|
|||
|
double lat = ProcessLat(data, 0, 4);
|
|||
|
ht.lat = lat.ToString();
|
|||
|
lastLat = lat.ToString();
|
|||
|
|
|||
|
data[0] = GetNextByte(msg, ref i);
|
|||
|
data[1] = GetNextByte(msg, ref i);
|
|||
|
data[2] = GetNextByte(msg, ref i);
|
|||
|
data[3] = GetNextByte(msg, ref i);
|
|||
|
double lng = ProcessLng(data, 0, 4);
|
|||
|
ht.lng = lng.ToString();
|
|||
|
lastLng = lng.ToString();
|
|||
|
|
|||
|
SafeMobileLib.Utils.WriteLine("\tLat = " + lat);
|
|||
|
SafeMobileLib.Utils.WriteLine("\tLng = " + lng);
|
|||
|
parse_circle = true;
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
if ((b == (byte)Report_Messages_Tokens_ENUM.ellipse_2d ||
|
|||
|
b == (byte)Report_Messages_Tokens_ENUM.ellipse_2d1 ||
|
|||
|
b == (byte)Report_Messages_Tokens_ENUM.ellipse_3d ||
|
|||
|
b == (byte)Report_Messages_Tokens_ENUM.ellipse_3d1 ||
|
|||
|
b == (byte)Report_Messages_Tokens_ENUM.ellipse_3d2 ||
|
|||
|
b == (byte)Report_Messages_Tokens_ENUM.ellipse_3d3 ||
|
|||
|
b == (byte)Report_Messages_Tokens_ENUM.point_2d
|
|||
|
) && !parsed_elipse
|
|||
|
)
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("Ellipse (" + b.ToString("X") + "):");
|
|||
|
Byte[] data = new byte[4];
|
|||
|
data[0] = GetNextByte(msg, ref i);
|
|||
|
data[1] = GetNextByte(msg, ref i);
|
|||
|
data[2] = GetNextByte(msg, ref i);
|
|||
|
data[3] = GetNextByte(msg, ref i);
|
|||
|
double lat = ProcessLat(data, 0, 4);
|
|||
|
ht.lat = lat.ToString();
|
|||
|
lastLat = lat.ToString();
|
|||
|
|
|||
|
data[0] = GetNextByte(msg, ref i);
|
|||
|
data[1] = GetNextByte(msg, ref i);
|
|||
|
data[2] = GetNextByte(msg, ref i);
|
|||
|
data[3] = GetNextByte(msg, ref i);
|
|||
|
double lng = ProcessLng(data, 0, 4);
|
|||
|
ht.lng = lng.ToString();
|
|||
|
lastLng = lng.ToString();
|
|||
|
|
|||
|
SafeMobileLib.Utils.WriteLine("\tLat = " + lat);
|
|||
|
SafeMobileLib.Utils.WriteLine("\tLng = " + lng);
|
|||
|
parsed_elipse = true;
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
if (b == (byte)Report_Messages_Tokens_ENUM.speed_hor_int && !parse_spd)
|
|||
|
{
|
|||
|
Console.Write(Report_Messages_Tokens_ENUM.speed_hor_int + "(" + b.ToString("X") + "): ");
|
|||
|
int aux = (int)GetNextByte(msg, ref i);
|
|||
|
aux &= 0xff;
|
|||
|
int spd = 0;
|
|||
|
|
|||
|
while ((aux & 0x80) != 0)
|
|||
|
{
|
|||
|
spd |= (aux ^ 0x80);
|
|||
|
spd <<= 7;
|
|||
|
aux = GetNextByte(msg, ref i);
|
|||
|
aux &= 0xff;
|
|||
|
}
|
|||
|
spd |= aux;
|
|||
|
spd = (int)(spd * 3.6);
|
|||
|
SafeMobileLib.Utils.WriteLine("speed :" + spd);
|
|||
|
ht.spd = spd.ToString();
|
|||
|
parse_spd = true;
|
|||
|
continue;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (parsed_time && parsed_elipse)
|
|||
|
InsertXML(ht);
|
|||
|
else if (parse_periodic)
|
|||
|
{
|
|||
|
ht.lat = "0";
|
|||
|
ht.lng = "0";
|
|||
|
ht.spd = "0";
|
|||
|
ht.location_time = DateTime.UtcNow;
|
|||
|
InsertXML(ht);
|
|||
|
}
|
|||
|
else if (parse_circle)
|
|||
|
InsertXML(ht);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
private static byte reqID_lastByte = 0;
|
|||
|
private static UdpClient udpClient;
|
|||
|
private static string sendTriggeredLocationReq(int report_time)
|
|||
|
{
|
|||
|
reqID_lastByte++;
|
|||
|
if (reqID_lastByte > 0xfe) reqID_lastByte = 0x00;
|
|||
|
|
|||
|
|
|||
|
reqID_lastByte = 0x05;
|
|||
|
|
|||
|
Byte[] sendBytes = { (byte)Document_Identifiers_ENUM.Triggered_Location_Request_NoCDT,
|
|||
|
0x0B, // length in Bytes
|
|||
|
(byte)Common_Element_Tokens_ENUM.request_id,
|
|||
|
//0x04, 0x24, 0x68, 0xAC, 0xE0,
|
|||
|
0x04, 0x24, 0x68, 0xAC, reqID_lastByte,
|
|||
|
|
|||
|
0x51,
|
|||
|
(byte)Query_Request_Messages_Tokens_ENUM.request_speed_hor,
|
|||
|
|
|||
|
(byte)Query_Request_Messages_Tokens_ENUM.periodic_trigger,
|
|||
|
(byte)Query_Request_Messages_Tokens_ENUM.interval,
|
|||
|
0x00, 0x00 //(byte)report_time// in seconds
|
|||
|
};
|
|||
|
|
|||
|
try
|
|||
|
{
|
|||
|
if (report_time < 0x80)
|
|||
|
{
|
|||
|
//sendBytes[10] = (byte)report_time;
|
|||
|
sendBytes[12] = (byte)report_time;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
sendBytes[1] += 1; // adjust length
|
|||
|
|
|||
|
int process = report_time; // MSB
|
|||
|
process >>= 7;
|
|||
|
process &= 0x007F;
|
|||
|
process |= 0x0080;
|
|||
|
|
|||
|
sendBytes[12] = (byte)process;
|
|||
|
sendBytes[13] = (byte)(report_time & 0x007F); //LSB
|
|||
|
}
|
|||
|
return sendBytes.ToString();
|
|||
|
|
|||
|
}
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("Location Thread SendTriggeredLocationRequest exception: " + ex.ToString(), ConsoleType.GPS);
|
|||
|
return null;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public void TriggerLocationRequest()
|
|||
|
{
|
|||
|
// send poll
|
|||
|
try
|
|||
|
{
|
|||
|
//serialPort.ReadExisting();
|
|||
|
string line = $"AT+CMGS=102,1,0,{sendTriggeredLocationReq(60).Length + 8}{SerialKey.CR}{SerialKey.LF}82{sendTriggeredLocationReq(60)}{SerialKey.CTRLZ}";
|
|||
|
SafeMobileLib.Utils.WriteLine("»»» POLL location request for " + SUID);
|
|||
|
serialPort.Write(line);
|
|||
|
Thread.Sleep(500);
|
|||
|
}
|
|||
|
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("SendPOLLToRadio Exception:" + ex.ToString(), ConsoleColor.Red);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Parse a LIP location received over the serial connection
|
|||
|
/// </summary>
|
|||
|
/// <param name="message">Location message that was received</param>
|
|||
|
/// <param name="suid">Subscriber id from which the location was received</param>
|
|||
|
private void parseLIPLocation(String message, String suid)
|
|||
|
{
|
|||
|
htCell_t ht = new htCell_t();
|
|||
|
ht.suid = suid;
|
|||
|
|
|||
|
//if ((htSU[suid] != null) && (!((htCell_t)htSU[suid]).state))
|
|||
|
//{
|
|||
|
// ((htCell_t)htSU[suid]).state = true;
|
|||
|
// SU_ChangeState(suid, true);
|
|||
|
//}
|
|||
|
//else if (htSU[suid] == null)
|
|||
|
//{
|
|||
|
// ht.state = true;
|
|||
|
// htSU.Add(suid, ht);
|
|||
|
// SU_ChangeState(suid, true);
|
|||
|
//}
|
|||
|
|
|||
|
SafeMobileLib.Utils.WriteLine("LIP Location");
|
|||
|
var result = lipDecoder.DecodeLipDataMessage(message);
|
|||
|
|
|||
|
#region LONG LOCATION
|
|||
|
if (lipDecoder.pduType == PDUType.LONG_LOCATION)
|
|||
|
{
|
|||
|
//SafeMobileLib.Utils.WriteLine("LIP LONG_LOCATION", ConsoleColor.Magenta);
|
|||
|
#region LONG_LOCATION_REPORT
|
|||
|
if (lipDecoder.pduTypeExtension == PDUTypeExtension.LONG_LOCATION_REPORT)
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("LIP LONG_LOCATION_REPORT", ConsoleColor.Green);
|
|||
|
//LAT latitude
|
|||
|
if (lipDecoder.latitude != "")
|
|||
|
ht.lat = lipDecoder.latitude;
|
|||
|
|
|||
|
//LNG
|
|||
|
if (lipDecoder.longitude != "")
|
|||
|
ht.lng = lipDecoder.longitude;
|
|||
|
|
|||
|
if (lipDecoder.timePositionHour == null || lipDecoder.timePositionHour == "")
|
|||
|
{
|
|||
|
lipDecoder.timePositionHour = DateTime.UtcNow.Hour.ToString();
|
|||
|
}
|
|||
|
|
|||
|
if (lipDecoder.timePositionMinute == null || lipDecoder.timePositionMinute == "")
|
|||
|
{
|
|||
|
lipDecoder.timePositionMinute = DateTime.UtcNow.Minute.ToString();
|
|||
|
}
|
|||
|
|
|||
|
if (lipDecoder.timePositionSecond == null || lipDecoder.timePositionSecond == "")
|
|||
|
{
|
|||
|
lipDecoder.timePositionSecond = DateTime.UtcNow.Second.ToString();
|
|||
|
}
|
|||
|
|
|||
|
//time
|
|||
|
DateTime time = new DateTime((int)DateTime.UtcNow.Year,
|
|||
|
(int)DateTime.UtcNow.Month,
|
|||
|
(int)DateTime.UtcNow.Day,
|
|||
|
(int)Convert.ToInt32(lipDecoder.timePositionHour),
|
|||
|
(int)Convert.ToInt32(lipDecoder.timePositionMinute),
|
|||
|
(int)Convert.ToInt32(lipDecoder.timePositionSecond));
|
|||
|
if (time != null)
|
|||
|
ht.location_time = time;
|
|||
|
;
|
|||
|
|
|||
|
//speed speed
|
|||
|
double spd = 0;
|
|||
|
//SafeMobileLib.Utils.WriteLine("Horizontal speed : " + lipDecoder.horizontalVelocity, ConsoleColor.DarkCyan);
|
|||
|
|
|||
|
if (lipDecoder.horizontalVelocity.Contains("Horizontal speed is unknown"))
|
|||
|
{
|
|||
|
// Console.WriteLine("Horizontal speed is unknown");
|
|||
|
lipDecoder.horizontalVelocity = "0";
|
|||
|
}
|
|||
|
if (lipDecoder.horizontalVelocity.Contains("km/h"))
|
|||
|
{
|
|||
|
lipDecoder.horizontalVelocity = lipDecoder.horizontalVelocity.Replace("km/h", "");
|
|||
|
//Console.WriteLine("After replace km/h: " + lip.horizontalVelocity);
|
|||
|
}
|
|||
|
if (!double.TryParse(lipDecoder.horizontalVelocity, out spd))
|
|||
|
{
|
|||
|
//Console.WriteLine("!ulong.TryParse(lip.horizontalVelocity, out spd) " + lip.horizontalVelocity);
|
|||
|
lipDecoder.horizontalVelocity = "0";
|
|||
|
}
|
|||
|
spd = double.Parse(lipDecoder.horizontalVelocity);
|
|||
|
try
|
|||
|
{
|
|||
|
spd = (ulong)Math.Round((double)spd);
|
|||
|
}
|
|||
|
catch (Exception ex) { Console.WriteLine("ERROR rounding speed:" + ex.Message); }
|
|||
|
try
|
|||
|
{
|
|||
|
ht.spd = spd + "";
|
|||
|
}
|
|||
|
catch (Exception ex) { SafeMobileLib.Utils.WriteLine("Exceptie pe aici : " + ex.ToString()); };
|
|||
|
|
|||
|
|
|||
|
Boolean isGPSErrorValid = true;
|
|||
|
ht.poll = lipDecoder.reasonForSendingBinaryValue.Length > 1 && Convert.ToInt32(lipDecoder.reasonForSendingBinaryValue, 2) == 32;
|
|||
|
if (lipDecoder.reasonForSendingBinaryValue== "00000000") //ARS ON
|
|||
|
{
|
|||
|
if (htSU[suid] != null)
|
|||
|
((htCell_t)htSU[suid]).state = true;
|
|||
|
else
|
|||
|
{
|
|||
|
ht.state = true;
|
|||
|
htSU.Add(suid, ht);
|
|||
|
}
|
|||
|
SU_ChangeState(suid, true);
|
|||
|
AddEvent("ARS ON from radio " + suid);
|
|||
|
|
|||
|
if (ConfigHelper.ReportType.ToUpper() == "SHORT")
|
|||
|
{
|
|||
|
string line = $"AT+CMGS={suid},1,0,45{SerialKey.CR}{SerialKey.LF}0A59E6840C08{SerialKey.CTRLZ}";
|
|||
|
SafeMobileLib.Utils.WriteLine($"Change Report Type to SHORT for Radio {suid}... ", ConsoleColor.Magenta);
|
|||
|
serialWrite(line);
|
|||
|
Thread.Sleep(1000);
|
|||
|
}
|
|||
|
else if (ConfigHelper.ReportType.ToUpper() == "LONG")
|
|||
|
{
|
|||
|
string line = $"AT+CMGS={suid},1,0,45{SerialKey.CR}{SerialKey.LF}0A59A6840C08{SerialKey.CTRLZ}";
|
|||
|
SafeMobileLib.Utils.WriteLine($"Change Report Type to LONG for Radio { suid}... ", ConsoleColor.Magenta);
|
|||
|
serialWrite(line);
|
|||
|
Thread.Sleep(1000);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
else if (lipDecoder.reasonForSendingBinaryValue == "00000001") //ARS OFF
|
|||
|
{
|
|||
|
if (htSU[suid] != null)
|
|||
|
((htCell_t)htSU[suid]).state = false;
|
|||
|
SU_ChangeState(suid, false);
|
|||
|
AddEvent("ARS OFF from radio " + suid);
|
|||
|
}
|
|||
|
else
|
|||
|
SendPositionOnMessageBus(ht);
|
|||
|
}
|
|||
|
#endregion
|
|||
|
|
|||
|
#region BASIC_LOCATION_PARAM_REQ_REP
|
|||
|
else if (lipDecoder.pduTypeExtension == PDUTypeExtension.BASIC_LOCATION_PARAM_REQ_REP)
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("LIP BASIC_LOCATION_PARAM_REQ_REP", ConsoleColor.Green);
|
|||
|
}
|
|||
|
#endregion
|
|||
|
|
|||
|
#region LONG_LOCATION_ACK
|
|||
|
else if (lipDecoder.pduTypeExtension == PDUTypeExtension.LONG_LOCATION_ACK)
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("LIP LONG_LOCATION_ACK", ConsoleColor.Green);
|
|||
|
}
|
|||
|
#endregion
|
|||
|
|
|||
|
#region ENABLE/DISABLE RESPONSE
|
|||
|
else if (lipDecoder.pduTypeExtension == PDUTypeExtension.LOCATION_REPORTING_ENABLE_DISABLE)
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("LIP LOCATION_REPORTING_ENABLE_DISABLE", ConsoleColor.Green);
|
|||
|
}
|
|||
|
#endregion
|
|||
|
|
|||
|
|
|||
|
#region Add MODIFY TRIGGER RESPONSE
|
|||
|
else if (lipDecoder.pduTypeExtension == PDUTypeExtension.ADD_MODIFY_TRIGGER_REQ_REP)
|
|||
|
{
|
|||
|
if(lipDecoder.resultCodeBinaryValue == "00011000")
|
|||
|
SafeMobileLib.Utils.WriteLine($"The request to change LIP GPS TYPE to: {lipDecoder.reportingType} was {lipDecoder.resultCode}", ConsoleColor.Green);
|
|||
|
else
|
|||
|
SafeMobileLib.Utils.WriteLine($"The request to change LIP GPS TYPE to: {lipDecoder.reportingType} was {lipDecoder.resultCode}", ConsoleColor.Red);
|
|||
|
|
|||
|
|
|||
|
}
|
|||
|
#endregion
|
|||
|
|
|||
|
#region REMOVE TRIGGER RESPONSE
|
|||
|
else if (lipDecoder.pduTypeExtension == PDUTypeExtension.REMOVE_TRIGGER_REQ_REP)
|
|||
|
{
|
|||
|
RemoveTriggerResponse rtr = result as RemoveTriggerResponse;
|
|||
|
SafeMobileLib.Utils.WriteLine("LIP REMOVE_TRIGGER_REQ_REP with result: " + rtr.ResultCode, ConsoleColor.Green);
|
|||
|
|
|||
|
}
|
|||
|
#endregion
|
|||
|
|
|||
|
SafeMobileLib.Utils.WriteLine("Reason for sending GPS: " + lipDecoder.reasonForSending, ConsoleColor.DarkCyan);
|
|||
|
}
|
|||
|
#endregion
|
|||
|
|
|||
|
#region SHORT LOCATION
|
|||
|
else if (lipDecoder.pduType == PDUType.SHORT_LOCATION)
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("LIP SHORT_LOCATION");
|
|||
|
ht.lat = lipDecoder.latitude ?? "0";
|
|||
|
ht.lng = lipDecoder.longitude ?? "0";
|
|||
|
ht.spd = "0";
|
|||
|
ht.location_time = DateTime.UtcNow;
|
|||
|
|
|||
|
if (lipDecoder.reasonForSendingBinaryValue == "00000000") //ARS ON
|
|||
|
{
|
|||
|
if (htSU[suid] != null)
|
|||
|
((htCell_t)htSU[suid]).state = true;
|
|||
|
else
|
|||
|
{
|
|||
|
ht.state = true;
|
|||
|
htSU.Add(suid, ht);
|
|||
|
}
|
|||
|
SU_ChangeState(suid, true);
|
|||
|
AddEvent("ARS ON from radio " + suid);
|
|||
|
|
|||
|
if (ConfigHelper.ReportType.ToUpper() == "SHORT")
|
|||
|
{
|
|||
|
string line = $"AT+CMGS={suid},1,0,45{SerialKey.CR}{SerialKey.LF}0A59E6840C08{SerialKey.CTRLZ}";
|
|||
|
SafeMobileLib.Utils.WriteLine($"Change Report Type to SHORT for Radio {suid}... ", ConsoleColor.Magenta);
|
|||
|
serialWrite(line);
|
|||
|
Thread.Sleep(1000);
|
|||
|
}
|
|||
|
else if (ConfigHelper.ReportType.ToUpper() == "LONG")
|
|||
|
{
|
|||
|
string line = $"AT+CMGS={suid},1,0,45{SerialKey.CR}{SerialKey.LF}0A59A6840C08{SerialKey.CTRLZ}";
|
|||
|
SafeMobileLib.Utils.WriteLine($"Change Report Type to LONG for Radio {suid}... ", ConsoleColor.Magenta);
|
|||
|
serialWrite(line);
|
|||
|
Thread.Sleep(1000);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
else if (lipDecoder.reasonForSendingBinaryValue == "00000001") //ARS OFF
|
|||
|
{
|
|||
|
if (htSU[suid] != null) ((htCell_t)htSU[suid]).state = false;
|
|||
|
SU_ChangeState(suid, false);
|
|||
|
AddEvent("ARS OFF from radio " + suid);
|
|||
|
}
|
|||
|
else if (lipDecoder.reasonForSending == "DMO ON")
|
|||
|
{ }
|
|||
|
else
|
|||
|
SendPositionOnMessageBus(ht);
|
|||
|
SafeMobileLib.Utils.WriteLine("Reason for sending GPS: " + lipDecoder.reasonForSending, ConsoleColor.DarkCyan);
|
|||
|
}
|
|||
|
#endregion
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
public void SendPositionOnMessageBus(htCell_t cell)
|
|||
|
{
|
|||
|
if (cell.spd == null)
|
|||
|
cell.spd = "0";
|
|||
|
try
|
|||
|
{
|
|||
|
String[] toSendString = new String[4];
|
|||
|
toSendString[0] = DateTo70Format(cell.location_time).ToString();
|
|||
|
toSendString[1] = cell.spd.ToString();
|
|||
|
toSendString[2] = cell.lat.ToString();
|
|||
|
toSendString[3] = cell.lng.ToString();
|
|||
|
|
|||
|
SafeMobileLib.Utils.WriteLine(String.Format("»»» " + (cell.poll ? "Poll resp" : "Position") + " [{0:0.0000},{1:0.0000}] from {2} [{3} kmh]",
|
|||
|
Math.Round(Double.Parse(cell.lat), 4), Math.Round(Double.Parse(cell.lng), 4), cell.suid, cell.spd));
|
|||
|
AddEvent(String.Format("»»» " + (cell.poll ? "Poll resp" : "Position") + " [{0:0.0000},{1:0.0000}] from {2} [{3} kmh]",
|
|||
|
Math.Round(Double.Parse(cell.lat), 4), Math.Round(Double.Parse(cell.lng), 4), cell.suid, cell.spd));
|
|||
|
|
|||
|
Byte[] toSendMulticast = Utils.CreateLocationMessage(cell.poll ? (int)MessageBusCmds.PollResponseReceived : (int)MessageBusCmds.LocationReceived,
|
|||
|
cell.suid, toSendString);
|
|||
|
udpMulticast.Send(toSendMulticast, toSendMulticast.Length);
|
|||
|
//SafeMobileLib.Utils.WriteLine("Send #131 location data: " + xml);
|
|||
|
try
|
|||
|
{
|
|||
|
this.Invoke((MethodInvoker)delegate { lbUpdateVAL.Text = DateTime.Now.ToString(); });
|
|||
|
}
|
|||
|
catch { SafeMobileLib.Utils.WriteLine("Failed to update timestamp in UI", ConsoleColor.Red); }
|
|||
|
}
|
|||
|
catch (Exception e)
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("error on send #131 location data \n" + e.ToString(), ConsoleColor.Red);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private void DisplayReqId(byte b, string suid)
|
|||
|
{
|
|||
|
switch (b)
|
|||
|
{
|
|||
|
case (byte)Request_Identifier.SU_is_powered_ON: SafeMobileLib.Utils.WriteLine($"Unit {suid} sent ARS ON", ConsoleColor.Blue); break;
|
|||
|
case (byte)Request_Identifier.SU_is_powered_OFF: SafeMobileLib.Utils.WriteLine($"Unit {suid} sent ARS OFF", ConsoleColor.Blue); break;
|
|||
|
case (byte)Request_Identifier.Emergency_condition_detected: SafeMobileLib.Utils.WriteLine($"Unit {suid} is in Emergency", ConsoleColor.DarkBlue); break;
|
|||
|
case (byte)Request_Identifier.PTT_condition_detected: SafeMobileLib.Utils.WriteLine(Request_Identifier.PTT_condition_detected.ToString(), ConsoleColor.Green); break;
|
|||
|
case (byte)Request_Identifier.Status: SafeMobileLib.Utils.WriteLine(Request_Identifier.Status.ToString(), ConsoleColor.Green); break;
|
|||
|
case (byte)Request_Identifier.Transmit_Inhibit_Mode_ON: SafeMobileLib.Utils.WriteLine(Request_Identifier.Transmit_Inhibit_Mode_ON.ToString(), ConsoleColor.Green); break;
|
|||
|
case (byte)Request_Identifier.Transmit_Inhibit_Mode_OFF: SafeMobileLib.Utils.WriteLine(Request_Identifier.Transmit_Inhibit_Mode_OFF.ToString(), ConsoleColor.Green); break;
|
|||
|
case (byte)Request_Identifier.System_access: SafeMobileLib.Utils.WriteLine(Request_Identifier.System_access.ToString(), ConsoleColor.Green); break;
|
|||
|
case (byte)Request_Identifier.DMO_ON: SafeMobileLib.Utils.WriteLine(Request_Identifier.DMO_ON.ToString(), ConsoleColor.Green); break;
|
|||
|
case (byte)Request_Identifier.Enter_service: SafeMobileLib.Utils.WriteLine(Request_Identifier.Enter_service.ToString(), ConsoleColor.Green); break;
|
|||
|
case (byte)Request_Identifier.Leave_service: SafeMobileLib.Utils.WriteLine(Request_Identifier.Leave_service.ToString(), ConsoleColor.Green); break;
|
|||
|
case (byte)Request_Identifier.Cell_reselection: SafeMobileLib.Utils.WriteLine(Request_Identifier.Cell_reselection.ToString(), ConsoleColor.Green); break;
|
|||
|
case (byte)Request_Identifier.Low_battery: SafeMobileLib.Utils.WriteLine(Request_Identifier.Low_battery.ToString(), ConsoleColor.Green); break;
|
|||
|
case (byte)Request_Identifier.SU_connected_Digital_Car_Kit: SafeMobileLib.Utils.WriteLine(Request_Identifier.SU_connected_Digital_Car_Kit.ToString(), ConsoleColor.Green); break;
|
|||
|
case (byte)Request_Identifier.SU_disconnected_Digital_Car_Kit: SafeMobileLib.Utils.WriteLine(Request_Identifier.SU_disconnected_Digital_Car_Kit.ToString(), ConsoleColor.Green); break;
|
|||
|
case (byte)Request_Identifier.Loss_of_coverage: SafeMobileLib.Utils.WriteLine(Request_Identifier.Loss_of_coverage.ToString(), ConsoleColor.Green); break;
|
|||
|
case (byte)Request_Identifier.Recovery_of_coverage: SafeMobileLib.Utils.WriteLine(Request_Identifier.Recovery_of_coverage.ToString(), ConsoleColor.Green); break;
|
|||
|
case (byte)Request_Identifier.SU_movement_by_amount: SafeMobileLib.Utils.WriteLine(Request_Identifier.SU_movement_by_amount.ToString(), ConsoleColor.Green); break;
|
|||
|
case (byte)Request_Identifier.Predefined_text_message: SafeMobileLib.Utils.WriteLine(Request_Identifier.Predefined_text_message.ToString(), ConsoleColor.Green); break;
|
|||
|
case (byte)Request_Identifier.Periodic_report: SafeMobileLib.Utils.WriteLine($"Unit {suid} sent periodic Location Report", ConsoleColor.Blue); break;
|
|||
|
default: SafeMobileLib.Utils.WriteLine("Unknown Request: 0x" + b.ToString("X"), ConsoleColor.DarkRed); break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private void EmergencyAlarm(String suid)
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("Emergency alarm received, inserting into db");
|
|||
|
try
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("Received emergency from radio id: " + suid);
|
|||
|
AddEvent("Received emergency from radio id: " + suid);
|
|||
|
|
|||
|
string seqID = "0.0";
|
|||
|
string toSend = "#138#" + suid + "#";
|
|||
|
String cmdok = "#" + seqID + toSend;
|
|||
|
Int32 tmp = cmdok.Length + 1;
|
|||
|
tmp += tmp.ToString().Length;
|
|||
|
cmdok = "#" + tmp.ToString() + cmdok;
|
|||
|
Encoding enc = Encoding.ASCII;
|
|||
|
byte[] buf = enc.GetBytes(cmdok);
|
|||
|
//put on multicast bus
|
|||
|
|
|||
|
SafeMobileLib.Utils.WriteLine("Emergency alarm sent on multicast bus: " + cmdok);
|
|||
|
udpMulticast.Send(buf, buf.Length);
|
|||
|
|
|||
|
try
|
|||
|
{
|
|||
|
this.Invoke((MethodInvoker)delegate
|
|||
|
{
|
|||
|
lbUpdateVAL.Text = DateTime.Now.ToString();
|
|||
|
});
|
|||
|
}
|
|||
|
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("Failed to update timestamp in UI: " + ex.ToString(), ConsoleColor.Red);
|
|||
|
}
|
|||
|
|
|||
|
if (htSU[suid] != null)
|
|||
|
{
|
|||
|
// ((htCell_t)htSU[suid]).activity_time = DateTime.Now;
|
|||
|
//((htCell_t)htSU[suid]).changeState(true);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
catch (Exception e)
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("emergencyAlarm Exception: " + e.ToString(), ConsoleColor.Red);
|
|||
|
}
|
|||
|
//}
|
|||
|
}
|
|||
|
|
|||
|
public void SendSMSOnMessageBus(Int64 radioID, string message)
|
|||
|
{
|
|||
|
|
|||
|
string msg = "#" + (int)MessageBusCmds.SMSReceived + "#" + radioID + "#" + message + "#hyt#";
|
|||
|
SendOnMsgBus(msg);
|
|||
|
SU_ChangeState(radioID + "", true);
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Send a string on the message bus. The string will be converted into a byte array before
|
|||
|
/// beeing sent
|
|||
|
/// </summary>
|
|||
|
/// <param name="commandMsg">The message which needs to be sent on the message bus</param>
|
|||
|
public void SendOnMsgBus(string commandMsg)
|
|||
|
{
|
|||
|
String seqID = "1." + (Utils.GetSecondsLocalFromDT(DateTime.Now)) + DateTime.Now.Millisecond.ToString();
|
|||
|
|
|||
|
byte[] buf = smutils.Convert_text_For_multicast("#" + seqID + commandMsg);
|
|||
|
SendOnMessageBus(buf, buf.Length);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Send a byte array of a specific length on the message bus
|
|||
|
/// </summary>
|
|||
|
/// <param name="data">Data which needs to be sent on the message bus</param>
|
|||
|
/// <param name="length">Data which needs to be sent on the message bus</param>
|
|||
|
private void SendOnMessageBus(byte[] message, int length)
|
|||
|
{
|
|||
|
if (udpMulticast != null)
|
|||
|
{
|
|||
|
udpMulticast.Send(message, length);
|
|||
|
SafeMobileLib.Utils.WriteLine(String.Format("+++ MB [{0}] ", ConvertBytesToString(message)), ConsoleColor.White);
|
|||
|
}
|
|||
|
|
|||
|
else
|
|||
|
{
|
|||
|
SM.Debug("••• Could not send on MB, it is null");
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private void ConfirmSMS(string suid, byte hb, byte lb)
|
|||
|
{
|
|||
|
int i;
|
|||
|
try
|
|||
|
{
|
|||
|
serialPort.DiscardOutBuffer();
|
|||
|
SafeMobileLib.Utils.WriteLine("Confirming SMS");
|
|||
|
|
|||
|
string line = "AT+CMGS=" + suid + ",1,0,32";
|
|||
|
serialPort.Write(line); // AT+CMGS=suid,1,0,len (len of buf+header in bits)
|
|||
|
SafeMobileLib.Utils.WriteLine(line);
|
|||
|
|
|||
|
byte[] buf = { 13, (byte)'8', (byte)'2',
|
|||
|
(byte)'1', (byte)'0',
|
|||
|
(byte)'0', (byte)'0',
|
|||
|
(byte)'0', (byte)'0'}; // dummy fill (2B) for msg id
|
|||
|
buf[7] = hb;
|
|||
|
buf[8] = lb;
|
|||
|
serialPort.Write(buf, 0, 9); // <cr> 82 10 00 id <ctrl+z>
|
|||
|
|
|||
|
buf[0] = 26;
|
|||
|
serialPort.Write(buf, 0, 1); // <ctrl+z>
|
|||
|
string saux = "";
|
|||
|
|
|||
|
for (i = 1; i < 9; i++)
|
|||
|
{
|
|||
|
char c = (char)buf[i];
|
|||
|
saux += c;
|
|||
|
if (i % 2 == 0)
|
|||
|
saux += " ";
|
|||
|
}
|
|||
|
|
|||
|
SafeMobileLib.Utils.WriteLine(saux + "\r\nEND");
|
|||
|
}
|
|||
|
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("ConfirmSMS Exception:" + ex.Message, ConsoleColor.Red);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public void InsertXML(htCell_t cell)
|
|||
|
{
|
|||
|
String xml = ""; // this is the xml message that will be uploaded into the DB
|
|||
|
xml = "id=\"100001\" mode=\"GPRS\" Hw_Type=\"NAVL\" subscriber=\"" + cell.suid;
|
|||
|
xml += "\" time=\"" + DateTo70Format(cell.location_time).ToString() + "\" latitude=\"" + cell.lat + "\" longitude=\"" + cell.lng;
|
|||
|
xml += "\" speed=\"" + cell.spd + "\" dgr=\"" + "0";
|
|||
|
xml += "\" ai1=\"" + "0" + "\" ai2=\"" + "0";
|
|||
|
xml += "\" ai3=\"" + "0" + "\" ai4=\"" + "0";
|
|||
|
xml += "\" ai5=\"" + "0" + "\" ai6=\"" + "0";
|
|||
|
xml += "\" ai7=\"" + "0" + "\" ai8=\"" + "0";
|
|||
|
xml += "\" di=\"" + "0" + "\" do=\"" + "0" + "\"";
|
|||
|
|
|||
|
if (xml.Length > 0)
|
|||
|
{
|
|||
|
xml = "<rsp " + xml + "></rsp>";
|
|||
|
}
|
|||
|
|
|||
|
if (cell.spd == null)
|
|||
|
cell.spd = "0";
|
|||
|
try
|
|||
|
{
|
|||
|
String[] toSendString = new String[4];
|
|||
|
toSendString[0] = DateTo70Format(cell.location_time).ToString();
|
|||
|
toSendString[1] = cell.spd.ToString();
|
|||
|
toSendString[2] = cell.lat.ToString();
|
|||
|
toSendString[3] = cell.lng.ToString();
|
|||
|
|
|||
|
String eventConsole = "";
|
|||
|
SafeMobileLib.Utils.WriteLine(eventConsole = String.Format("»»» Position [{0:0.0000},{1:0.0000}] from {2} [{3} kmh]", Math.Round(Double.Parse(cell.lat), 4),
|
|||
|
Math.Round(Double.Parse(cell.lng), 4), cell.suid, cell.spd));
|
|||
|
|
|||
|
AddEvent(eventConsole);
|
|||
|
|
|||
|
Byte[] toSendMulticast = Utils.CreateLocationMessage(131, cell.suid, toSendString);
|
|||
|
udpMulticast.Send(toSendMulticast, toSendMulticast.Length);
|
|||
|
//SafeMobileLib.Utils.WriteLine("Send #131 location data: " + xml);
|
|||
|
try
|
|||
|
{
|
|||
|
this.Invoke((MethodInvoker)delegate { lbUpdateVAL.Text = DateTime.Now.ToString(); });
|
|||
|
}
|
|||
|
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("Failed to update timestamp in UI: " + ex.Message, ConsoleColor.Red);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
catch (Exception e)
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("error on send #131 location data \n" + e.ToString(), ConsoleColor.Red);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private void RestartApp()
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
Process oldProcess = Process.GetCurrentProcess();
|
|||
|
oldProcess.WaitForExit(5000);
|
|||
|
System.Diagnostics.Process.Start(Application.ExecutablePath, "-c");
|
|||
|
Application.Exit();
|
|||
|
}
|
|||
|
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("Error on restart thread:" + ex.ToString(), ConsoleColor.Red);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private void CloseSerialOnExit()
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
serialPort.Close(); //close the serial port
|
|||
|
}
|
|||
|
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("CloseSerialOnExit error: " + ex.Message, ConsoleColor.Red);
|
|||
|
//MessageBox.Show(ex.Message); //catch any serial port closing error messages
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
this.Invoke((MethodInvoker)delegate ()
|
|||
|
{
|
|||
|
NowClose(this, new EventArgs());
|
|||
|
});
|
|||
|
|
|||
|
//this.Invoke(new EventHandler(NowClose)); //now close back in the main thread
|
|||
|
}
|
|||
|
|
|||
|
private void NowClose(object sender, EventArgs e)
|
|||
|
{
|
|||
|
|
|||
|
this.Close(); //now close the form
|
|||
|
}
|
|||
|
|
|||
|
#endregion methods
|
|||
|
|
|||
|
#region voice commands to serial port
|
|||
|
private void InitPrivateCall(string imei)
|
|||
|
{
|
|||
|
string line = null;
|
|||
|
hasPresenceCheck = ConfigHelper.HasPresenceCheck;
|
|||
|
SafeMobileLib.Utils.WriteLine("Set call parameters");
|
|||
|
if(isDMO && !hasPresenceCheck)
|
|||
|
line = "AT+CTSDC=0,0,0,1,1,0,4,1,0,0,0\r\n";
|
|||
|
else if (isDMO && hasPresenceCheck)
|
|||
|
line = "AT+CTSDC=0,0,0,1,1,0,0,1,0,0\r\n";
|
|||
|
else if(!isDMO)
|
|||
|
line = "AT+CTSDC=0,0,0,0,0,0,0,1,0,0\r\n";
|
|||
|
|
|||
|
serialPort.WriteTimeout = 500;
|
|||
|
serialPort.Write(line);
|
|||
|
|
|||
|
Thread.Sleep(299);
|
|||
|
SafeMobileLib.Utils.WriteLine($"call unit {imei}");
|
|||
|
//line = $"ATD{imei}\r\n";
|
|||
|
|
|||
|
line = $"ATD{imei}\r\n";
|
|||
|
serialPort.WriteTimeout = 500;
|
|||
|
serialPort.Write(line);
|
|||
|
|
|||
|
Thread.Sleep(299);
|
|||
|
}
|
|||
|
|
|||
|
private void EndPrivateCall()
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("Set end call parameters");
|
|||
|
string line = "ATH\r\n";
|
|||
|
|
|||
|
serialPort.WriteTimeout = 500;
|
|||
|
serialPort.Write(line);
|
|||
|
|
|||
|
Thread.Sleep(299);
|
|||
|
}
|
|||
|
|
|||
|
private void InitGroupCall(string grp)
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("Set call parameters");
|
|||
|
string line = "AT+CTSDC=0,0,0,1,1,0,1,1,0,0\r\n";
|
|||
|
|
|||
|
serialPort.WriteTimeout = 500;
|
|||
|
serialPort.Write(line);
|
|||
|
|
|||
|
Thread.Sleep(299);
|
|||
|
SafeMobileLib.Utils.WriteLine($"call group {grp}");
|
|||
|
line = $"ATD{grp}\r\n";
|
|||
|
|
|||
|
serialPort.WriteTimeout = 500;
|
|||
|
serialPort.Write(line);
|
|||
|
|
|||
|
Thread.Sleep(299);
|
|||
|
}
|
|||
|
|
|||
|
private void EndGroupCall()
|
|||
|
{
|
|||
|
string line = $"AT+CUTXC={callInstance}\r\n";
|
|||
|
SafeMobileLib.Utils.WriteLine("Set end call parameters: " + line, ConsoleColor.Cyan);
|
|||
|
serialPort.WriteTimeout = 500;
|
|||
|
serialPort.Write(line);
|
|||
|
|
|||
|
Thread.Sleep(299);
|
|||
|
}
|
|||
|
#endregion voice commands to serial port
|
|||
|
|
|||
|
#region utils
|
|||
|
|
|||
|
private static string Byte2Str(char c)
|
|||
|
{
|
|||
|
char[] Byte2Char = {'0', '1', '2', '3', '4', '5',
|
|||
|
'6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
|
|||
|
};
|
|||
|
byte b = (byte)c;
|
|||
|
|
|||
|
byte hb = b;
|
|||
|
hb >>= 4;
|
|||
|
hb &= 0x0f;
|
|||
|
char hc = Byte2Char[hb];
|
|||
|
|
|||
|
byte lb = b;
|
|||
|
lb &= 0x0f;
|
|||
|
char lc = Byte2Char[lb];
|
|||
|
|
|||
|
string ret = hc.ToString() + lc.ToString();
|
|||
|
return ret;
|
|||
|
}
|
|||
|
|
|||
|
private DateTime ProcessTime(Byte[] data, int startIndex, int len)
|
|||
|
{
|
|||
|
// (yyyy*2^26) + (MM*2^22) + (DD*2^17) + (hh*2^12) + (mm*2^6) + ss
|
|||
|
Byte B1 = data[startIndex];
|
|||
|
Byte B2 = data[startIndex + 1];
|
|||
|
Byte B3 = data[startIndex + 2];
|
|||
|
Byte B4 = data[startIndex + 3];
|
|||
|
Byte B5 = data[startIndex + 4];
|
|||
|
|
|||
|
int hh, mm, ss, YY, MM, DD;
|
|||
|
ss = B5 & 0x3F; // remove first 2b
|
|||
|
|
|||
|
mm = B4 & 0x0F;
|
|||
|
mm <<= 2;
|
|||
|
mm |= ((B5 >> 6) & 0x03);
|
|||
|
|
|||
|
hh = B3 & 0x01;
|
|||
|
hh <<= 4;
|
|||
|
hh |= ((B4 & 0xf0) >> 4);
|
|||
|
|
|||
|
DD = B3 & 0x3E;
|
|||
|
DD >>= 1;
|
|||
|
|
|||
|
MM = B2 & 0x03;
|
|||
|
MM <<= 2;
|
|||
|
MM |= ((B3 >> 6) & 0x03);
|
|||
|
|
|||
|
YY = B1;
|
|||
|
YY <<= 6;
|
|||
|
YY |= ((B2 >> 2) & 0x3F);
|
|||
|
|
|||
|
SafeMobileLib.Utils.WriteLine("\tGPSTime : " + YY + "/" + MM + "/" + DD + " " + hh + ":" + mm + ":" + ss);
|
|||
|
return new DateTime(YY, MM, DD, hh, mm, ss, DateTimeKind.Utc);
|
|||
|
}
|
|||
|
|
|||
|
private double ProcessLat(Byte[] data, int startIndex, int len)
|
|||
|
{
|
|||
|
bool sign = false;
|
|||
|
if ((data[0] & 0x80) != 0)
|
|||
|
{
|
|||
|
sign = true;
|
|||
|
}
|
|||
|
ulong l = (ulong)data[startIndex];
|
|||
|
|
|||
|
if (sign)
|
|||
|
l ^= 0x80; // remove the sign
|
|||
|
|
|||
|
l <<= 8;
|
|||
|
l |= (ulong)data[startIndex + 1];
|
|||
|
l <<= 8;
|
|||
|
l |= (ulong)data[startIndex + 2];
|
|||
|
l <<= 8;
|
|||
|
l |= (ulong)data[startIndex + 3];
|
|||
|
|
|||
|
|
|||
|
//Console.WriteLine("lat ulong=0x" + l.ToString("X"));
|
|||
|
|
|||
|
double ld = (double)l;
|
|||
|
ld *= 90;
|
|||
|
ld /= 1024;
|
|||
|
ld /= 1024;
|
|||
|
ld /= 1024;
|
|||
|
ld /= 2;
|
|||
|
if (sign)
|
|||
|
ld *= -1;
|
|||
|
|
|||
|
return ld;
|
|||
|
}
|
|||
|
|
|||
|
private double ProcessLng(Byte[] data, int startIndex, int len)
|
|||
|
{
|
|||
|
bool sign = false;
|
|||
|
|
|||
|
if ((data[startIndex] & 0x80) != 0)
|
|||
|
{
|
|||
|
sign = true;
|
|||
|
}
|
|||
|
|
|||
|
ulong l = (ulong)data[startIndex];
|
|||
|
|
|||
|
if (sign)
|
|||
|
l ^= 0x80; // remove the sign
|
|||
|
|
|||
|
l <<= 8;
|
|||
|
l |= (ulong)data[startIndex + 1];
|
|||
|
l <<= 8;
|
|||
|
l |= (ulong)data[startIndex + 2];
|
|||
|
l <<= 8;
|
|||
|
l |= (ulong)data[startIndex + 3];
|
|||
|
|
|||
|
|
|||
|
//Console.WriteLine("lng ulong=0x" + l.ToString("X"));
|
|||
|
|
|||
|
double ld = (double)l;
|
|||
|
ld *= 360;
|
|||
|
ld /= 1024;
|
|||
|
ld /= 1024;
|
|||
|
ld /= 1024;
|
|||
|
ld /= 4;
|
|||
|
if (sign)
|
|||
|
{
|
|||
|
ld = 180 - ld;
|
|||
|
ld *= -1;
|
|||
|
}
|
|||
|
|
|||
|
return ld;
|
|||
|
}
|
|||
|
|
|||
|
private void ParseSMS(string msg, string suid, int len)
|
|||
|
{
|
|||
|
//SafeMobileLib.Utils.WriteLine("SMS len=" + len);
|
|||
|
int i = 2;
|
|||
|
byte type = GetNextByte(msg, ref i);
|
|||
|
//SafeMobileLib.Utils.WriteLine("Type:" + type);
|
|||
|
switch (type)
|
|||
|
{
|
|||
|
case 0x06:
|
|||
|
case 0x04:// this is a SMS message
|
|||
|
i = 8;
|
|||
|
Byte[] receivedBytes = new Byte[len + 4];
|
|||
|
receivedBytes[0] = (Byte)((len + 2) / 256);
|
|||
|
receivedBytes[1] = (Byte)((len + 2) % 256);
|
|||
|
receivedBytes[2] = 0x00;
|
|||
|
receivedBytes[3] = 0x00;
|
|||
|
|
|||
|
Char[] cs = new Char[150];
|
|||
|
for (int k = 0; k < len; k++)
|
|||
|
{
|
|||
|
byte b = GetNextByte(msg, ref i);
|
|||
|
cs[k] = (char)b;
|
|||
|
receivedBytes[k + 4] = b;
|
|||
|
}
|
|||
|
|
|||
|
string s = new string(cs, 0, len);
|
|||
|
//string key = suid + " | " + DateTime.Now;
|
|||
|
|
|||
|
SafeMobileLib.Utils.WriteLine("The SMS is [" + s + "]");
|
|||
|
// confirm sms
|
|||
|
ConfirmSMS(suid, (byte)msg[4], (byte)msg[5]);
|
|||
|
|
|||
|
if (htSU[suid] != null)
|
|||
|
{
|
|||
|
//((htCell_t)htSU[suid]).activity_time = DateTime.Now;
|
|||
|
//((htCell_t)htSU[suid]).changeState(true);
|
|||
|
}
|
|||
|
|
|||
|
String sms = s;
|
|||
|
|
|||
|
// remove first 24 characters if is fug
|
|||
|
if (s.Length > 24 && Utils.isFug)
|
|||
|
sms = s.Substring(24).Trim();
|
|||
|
|
|||
|
AddEvent($"Text message [{sms}] received from radio {suid}");
|
|||
|
// send message on message bus
|
|||
|
SendSMSOnMessageBus(Int64.Parse(suid), sms);
|
|||
|
|
|||
|
try
|
|||
|
{
|
|||
|
this.Invoke((MethodInvoker)delegate { lbUpdateVAL.Text = DateTime.Now.ToString(); });
|
|||
|
}
|
|||
|
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("Failed to update timestamp in UI" + ex.ToString(), ConsoleColor.Red);
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
case 0x10: // this is a sms confirmation
|
|||
|
byte ack = GetNextByte(msg, ref i);
|
|||
|
|
|||
|
if (ack == 0)
|
|||
|
{
|
|||
|
byte id = GetNextByte(msg, ref i);
|
|||
|
SafeMobileLib.Utils.WriteLine("Received confirmation for message with ID = " + id);
|
|||
|
|
|||
|
AddEvent($"Received text message ack form message with id {id}");
|
|||
|
}
|
|||
|
|
|||
|
else
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("No acknowledge received for sent message.");
|
|||
|
AddEvent($"No acknowledge received for sent message");
|
|||
|
}
|
|||
|
|
|||
|
if (htSU[suid] != null)
|
|||
|
{
|
|||
|
//((htCell_t)htSU[suid]).activity_time = DateTime.Now;
|
|||
|
//((htCell_t)htSU[suid]).changeState(true);
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
SafeMobileLib.Utils.WriteLine("Error: ParseSMS: Unknown message type");
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public static string ConvertBytesToString(Byte[] receivedBytes)
|
|||
|
{
|
|||
|
string response = "";
|
|||
|
|
|||
|
for (int i = 0; i < receivedBytes.Length; i++)
|
|||
|
{
|
|||
|
response = $"{response}{(char)receivedBytes[i]}";
|
|||
|
}
|
|||
|
return response;
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// takes 2chars from the string, and returns creates a byte from them
|
|||
|
/// (hex to byte)
|
|||
|
/// </summary>
|
|||
|
/// <param name="msg"></param>
|
|||
|
/// <param name="i"></param>
|
|||
|
/// <returns></returns>
|
|||
|
private byte GetNextByte(string msg, ref int i)
|
|||
|
{
|
|||
|
if (i >= msg.Length)
|
|||
|
return 0;
|
|||
|
|
|||
|
byte high_nibble = bVal(msg[i]);
|
|||
|
|
|||
|
byte low_nibble = bVal(msg[i + 1]);
|
|||
|
byte ret = high_nibble;
|
|||
|
ret <<= 4;
|
|||
|
ret |= low_nibble;
|
|||
|
i += 2;
|
|||
|
return ret;
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// char -> byte value
|
|||
|
/// </summary>
|
|||
|
/// <param name="c"></param>
|
|||
|
/// <returns></returns>
|
|||
|
private byte bVal(char c)
|
|||
|
{
|
|||
|
byte ret;
|
|||
|
|
|||
|
if (c >= '0' && c <= '9')
|
|||
|
{
|
|||
|
ret = (byte)(c - '0');
|
|||
|
}
|
|||
|
|
|||
|
else
|
|||
|
{
|
|||
|
ret = (byte)(c - 'A');
|
|||
|
ret += 10;
|
|||
|
}
|
|||
|
|
|||
|
return ret;
|
|||
|
}
|
|||
|
|
|||
|
private uint DateTo70Format(DateTime time)
|
|||
|
{
|
|||
|
long nOfSeconds;
|
|||
|
DateTime dt70 = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
|
|||
|
TimeSpan span = time - dt70;
|
|||
|
nOfSeconds = (long)span.TotalSeconds;
|
|||
|
|
|||
|
return ((uint)nOfSeconds);
|
|||
|
}
|
|||
|
#endregion utils
|
|||
|
|
|||
|
#region worker
|
|||
|
private void FindPortsWorker_DoWork(object sender, DoWorkEventArgs e)
|
|||
|
{
|
|||
|
Utils.GetAvailableSerialPorts(ref portHT);
|
|||
|
ports = Utils.GetOpenPorts();
|
|||
|
}
|
|||
|
|
|||
|
private void FindPortsWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
|
|||
|
{
|
|||
|
RadListDataItem[] radCBItems = new RadListDataItem[ports.Length];
|
|||
|
|
|||
|
for (int i = 0; i < ports.Length; i++)
|
|||
|
{
|
|||
|
String portName = ports[i];
|
|||
|
RadListDataItem item = new RadListDataItem();
|
|||
|
// item.Name = portName;
|
|||
|
item.Text = portName;
|
|||
|
radCBItems[i] = item;
|
|||
|
}
|
|||
|
|
|||
|
if (SerialPort.GetPortNames().Length > 0)
|
|||
|
{
|
|||
|
radCBPorts.Items.AddRange(radCBItems);
|
|||
|
|
|||
|
int s = 0;
|
|||
|
|
|||
|
foreach (RadListDataItem li in radCBPorts.Items)
|
|||
|
{
|
|||
|
if (portHT.Contains(li.Text))
|
|||
|
radCBPorts.SelectedIndex = s;
|
|||
|
s++;
|
|||
|
}
|
|||
|
|
|||
|
if (ConfigHelper.SerialPort != null)
|
|||
|
{
|
|||
|
if (portHT.Contains(ConfigHelper.SerialPort))
|
|||
|
{
|
|||
|
radCBPorts.Text = ConfigHelper.SerialPort;
|
|||
|
}
|
|||
|
}
|
|||
|
btConnect.Enabled = true;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
lbStatusVAL.Text = "No COM port found";
|
|||
|
}
|
|||
|
|
|||
|
if (ConfigHelper.SerialPort != null)
|
|||
|
{
|
|||
|
if (portHT.Contains(ConfigHelper.SerialPort))
|
|||
|
{
|
|||
|
ckAutoconnect.Checked = ConfigHelper.GW_Autoconnect;
|
|||
|
if (ConfigHelper.GW_Autoconnect)
|
|||
|
{
|
|||
|
|
|||
|
btConnect.PerformClick();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
else
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine(String.Format("Port: {0} not available", ConfigHelper.SerialPort));
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private void rbApplyAudioConfiguration_Click(object sender, EventArgs e)
|
|||
|
{
|
|||
|
selectedOUTDevice = OutputSoundList.SelectedIndex;
|
|||
|
selectedINDevice = InputSoundList.SelectedIndex;
|
|||
|
|
|||
|
StartnVoice();
|
|||
|
|
|||
|
ConfigHelper.SaveSpeakerDevice(OutputSoundList.SelectedItem.Text);
|
|||
|
ConfigHelper.SaveMicDevice(InputSoundList.SelectedItem.Text);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
private void serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("serialPort_DataReceived " + msgReceived, ConsoleColor.Green);
|
|||
|
msgReceived = 0;
|
|||
|
//this.Invoke(new EventHandler(CheckMessage));
|
|||
|
CheckMessage(null, null);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
private void serialPort_ErrorReceived(object sender, SerialErrorReceivedEventArgs e)
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("serialPort_ErrorReceived: " + e.ToString(), ConsoleColor.Red);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
#endregion worker
|
|||
|
|
|||
|
#region update
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Check for new version release on SafeMobile Portal
|
|||
|
/// The check is done by comparing Current Assembly Version with the one
|
|||
|
/// written in a xml file on the portal.
|
|||
|
/// </summary>
|
|||
|
private void CheckForUpdate()
|
|||
|
{
|
|||
|
App appType = App.GW_TETRA;
|
|||
|
AutoUpdate au = new AutoUpdate(appType)
|
|||
|
{
|
|||
|
IsDevelop = Utils.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 = Utils.isDevelop
|
|||
|
};
|
|||
|
|
|||
|
uf.Show();
|
|||
|
}
|
|||
|
};
|
|||
|
};
|
|||
|
// call method to check for new updated
|
|||
|
au.CheckUpdate();
|
|||
|
}
|
|||
|
|
|||
|
#endregion update
|
|||
|
|
|||
|
#region AT Commands
|
|||
|
|
|||
|
//MCC & MNC parse needed
|
|||
|
//$"AT+MCTGDR=1,{SerialKey.CR}";
|
|||
|
|
|||
|
//Reboot - GW needs to re-register
|
|||
|
//$"ATR{SerialKey.CR}";
|
|||
|
|
|||
|
//Boud Rate Set/Read/Test
|
|||
|
//$"AT+IRP=<baud rate>{SerialKey.CR}";
|
|||
|
//$"AT+IPR?{SerialKey.CR}";
|
|||
|
//$"AT+IPR=?{SerialKey.CR}";
|
|||
|
|
|||
|
//Radio Volume
|
|||
|
//$"AT+CLVL?{SerialKey.CR}";
|
|||
|
//$"AT+CLVL=6{SerialKey.CR}";
|
|||
|
|
|||
|
//Change reporting to LIP LONG: $"AT+CMGS=102,1,0,45{SerialKey.CR}{SerialKey.LF}0A59A6840C08{SerialKey.CTRLZ}";
|
|||
|
//Change reporting to LIP Short: $"AT+CMGS=102,1,0,45{SerialKey.CR}{SerialKey.LF}0A59E6840C08{SerialKey.CTRLZ}";
|
|||
|
|
|||
|
private void radButton1_Click(object sender, EventArgs e)
|
|||
|
{
|
|||
|
String line = $"AT+CTSDC=?\r\n";
|
|||
|
SafeMobileLib.Utils.WriteLine("Test CTSDC: " + line, ConsoleColor.Cyan);
|
|||
|
serialWrite(line);
|
|||
|
Thread.Sleep(1000);
|
|||
|
|
|||
|
line = $"AT+CTSDC?\r\n";
|
|||
|
SafeMobileLib.Utils.WriteLine("Read CTSDC: " + line, ConsoleColor.Cyan);
|
|||
|
serialWrite(line);
|
|||
|
Thread.Sleep(1000);
|
|||
|
}
|
|||
|
|
|||
|
private void rebootRadio_Click(object sender, EventArgs e)
|
|||
|
{
|
|||
|
//Test();
|
|||
|
RebootRadio();
|
|||
|
}
|
|||
|
|
|||
|
private void tmoDMO_Click(object sender, EventArgs e)
|
|||
|
{
|
|||
|
String line = $"AT+CTOM?{SerialKey.CR}";
|
|||
|
SafeMobileLib.Utils.WriteLine("Radio Mode: " + line, ConsoleColor.Magenta);
|
|||
|
serialWrite(line);
|
|||
|
Thread.Sleep(1000);
|
|||
|
}
|
|||
|
|
|||
|
private void RebootRadio()
|
|||
|
{
|
|||
|
String line = $"ATR{SerialKey.CR}";
|
|||
|
SafeMobileLib.Utils.WriteLine("Rebooting Gateway Radio...", ConsoleColor.Magenta);
|
|||
|
serialWrite(line);
|
|||
|
Thread.Sleep(1000);
|
|||
|
needToRegister = true;
|
|||
|
}
|
|||
|
|
|||
|
#endregion
|
|||
|
|
|||
|
#region Testing methods
|
|||
|
public void Test()
|
|||
|
{
|
|||
|
string line = $"AT+IRP=9600{SerialKey.CR}";
|
|||
|
serialWrite(line);
|
|||
|
Thread.Sleep(1000);
|
|||
|
}
|
|||
|
|
|||
|
#endregion
|
|||
|
|
|||
|
#region EVENTS
|
|||
|
public delegate void RegistrationCompleted(RegistrationResponse response);
|
|||
|
public event RegistrationCompleted OnRegistrationCompleted;
|
|||
|
#endregion
|
|||
|
}
|
|||
|
}
|