1380 lines
59 KiB
C#
1380 lines
59 KiB
C#
|
using System;
|
|||
|
using SafeMobileLib;
|
|||
|
using MotoTRBO_XNL_Cmd;
|
|||
|
using MotoTRBO_GW;
|
|||
|
using System.ComponentModel;
|
|||
|
using System.Threading;
|
|||
|
using NAudio.Wave;
|
|||
|
|
|||
|
namespace MotoTrbo_GW
|
|||
|
{
|
|||
|
public class RadioComHandler : INotifyPropertyChanged
|
|||
|
{
|
|||
|
private bool connected = false;
|
|||
|
private RADIO_STATUS RadioStatus;
|
|||
|
public RADIO_STATUS RadioStatusProp
|
|||
|
{
|
|||
|
get { return RadioStatus; }
|
|||
|
set
|
|||
|
{
|
|||
|
RadioStatus = value;
|
|||
|
RadioStatusChanged("RadioStatusProp");
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public event PropertyChangedEventHandler PropertyChanged;
|
|||
|
|
|||
|
private int radioID, radioIMEI,radioNetworkID;
|
|||
|
private string radioIP;
|
|||
|
private int INdevId, OUTdevID;
|
|||
|
|
|||
|
private UdpMulticast udp4VoiceSend;
|
|||
|
private UdpMulticast udp4VoiceRecv;
|
|||
|
private RadioConnection radioCon;
|
|||
|
private System.Threading.Timer tCheckPTT;
|
|||
|
private System.Threading.Timer tCheckSTATUS;
|
|||
|
|
|||
|
bool speakersOn = false;
|
|||
|
bool PTTbussy = false;
|
|||
|
private int voice_port = 17234;
|
|||
|
|
|||
|
|
|||
|
#region LINX
|
|||
|
#if LINXB
|
|||
|
public int CallType
|
|||
|
{
|
|||
|
get { return callType; }
|
|||
|
set { callType = value; }
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Returns true if the base station is in PTT, else returns false
|
|||
|
/// </summary>
|
|||
|
public bool IsPTTbussy
|
|||
|
{
|
|||
|
get { return PTTbussy; }
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Returns the radio id of the attached mobile radio
|
|||
|
/// </summary>
|
|||
|
public int RadioID
|
|||
|
{
|
|||
|
get { return radioID; }
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
private LINX.LinxCall _linxCallInfo;
|
|||
|
/// <summary>
|
|||
|
/// Gets or sets information about linx call
|
|||
|
/// </summary>
|
|||
|
public LINX.LinxCall LinxCallInfo {
|
|||
|
get { return _linxCallInfo; }
|
|||
|
set {
|
|||
|
_linxCallInfo = value;
|
|||
|
}
|
|||
|
}
|
|||
|
public bool GroupCallInitiatedByRadio { get; set; }
|
|||
|
private const int MS_TO_WAIT_FOR_LINX_CALL_SETUP = 3000;
|
|||
|
private System.Timers.Timer _timerPrivatePTTToLinx = null;
|
|||
|
#endif
|
|||
|
#endregion
|
|||
|
|
|||
|
bool monitorRequest = false;
|
|||
|
int monitorID = 0;
|
|||
|
|
|||
|
private int CALLER_ID = 0;
|
|||
|
private int CALL_TYPE = 0;
|
|||
|
|
|||
|
private int callType=0;
|
|||
|
private string callSeqID="0.0";
|
|||
|
private string voiceMulticastIP4Send;
|
|||
|
private string voiceMulticastIP4Recv;
|
|||
|
|
|||
|
private int sw_zone_nr=0, sw_channel_nr=0;
|
|||
|
private static int id = 0;
|
|||
|
private int id_local = 0;
|
|||
|
|
|||
|
private Thread listenThread;
|
|||
|
public BufferedWaveProvider buffWaveProvider = null;
|
|||
|
|
|||
|
// voice settings region
|
|||
|
private AudioManager _audioManager = null;
|
|||
|
public int OutDevIDProperty { get { return OUTdevID; } }
|
|||
|
|
|||
|
public int InDevIDProperty { get { return INdevId; } }
|
|||
|
//
|
|||
|
|
|||
|
protected void RadioStatusChanged(string name)
|
|||
|
{
|
|||
|
PropertyChangedEventHandler handler = PropertyChanged;
|
|||
|
if (handler != null)
|
|||
|
{
|
|||
|
PropertyChangedEventArgs e =new PropertyChangedEventArgs(name);
|
|||
|
|
|||
|
handler(this, e);
|
|||
|
}
|
|||
|
}
|
|||
|
/// <summary>
|
|||
|
/// HAndles messageBus->GW com & GW->radio com
|
|||
|
/// </summary>
|
|||
|
/// <param name="radioID"></param>
|
|||
|
/// <param name="radioIP"></param>
|
|||
|
/// <param name="messageBusIP"></param>
|
|||
|
/// <param name="messageBusPort"></param>
|
|||
|
/// <param name="INdevID"></param>
|
|||
|
/// <param name="OUTdevID"></param>
|
|||
|
public RadioComHandler(RadioConnection rc,int radioID,
|
|||
|
string radioIP,int radioNetworkID, int radioIMEI,
|
|||
|
int INdevID, int OUTdevID)
|
|||
|
{
|
|||
|
id++;
|
|||
|
id_local = id;
|
|||
|
SafeMobileLib.Utils.WriteLine(id_local + "Constructor for radioConHandler with ID:" + radioID);
|
|||
|
RadioStatusProp = RADIO_STATUS.OFF;
|
|||
|
this.radioIP = radioIP;
|
|||
|
this.radioNetworkID = radioNetworkID;
|
|||
|
this.radioIMEI = radioIMEI;
|
|||
|
this.radioID = radioID;
|
|||
|
this.INdevId = INdevID; this.OUTdevID = OUTdevID;
|
|||
|
|
|||
|
//start radio com
|
|||
|
//radioCon = new RadioConnection(radioIP, 8002, user4radioCon);
|
|||
|
radioCon = rc;
|
|||
|
//radioCon.OnAuthDone2 += new RadioConnection.AuthDoneDEl2(radioCon_OnAuthDone);
|
|||
|
radioCon.OnChannelEvent += new RadioConnection.ChannelEvent(radioCon_OnChannelEvent);
|
|||
|
radioCon.OnCallEvent += new RadioConnection.CallEvent(radioCon_OnCallEvent);
|
|||
|
radioCon.OnSpeakersEvent += new RadioConnection.SpeakersEvent(radioCon_OnSpeakersEvent);
|
|||
|
radioCon.OnRemoteControlEvent += new RadioConnection.RemoteControlEvent(radioCon_OnRemoteControlEvent);
|
|||
|
radioCon.OnTransmitEvent += new RadioConnection.TransmitEvent(radioCon_OnTransmitEvent);
|
|||
|
radioCon.OnRestartEvent += new RadioConnection.RestartEvent(radioCon_OnRestartEvent);
|
|||
|
|
|||
|
//start voice bus for send
|
|||
|
voiceMulticastIP4Send = "224.10." + Main.GWID.ToString() + "." + radioID.ToString();
|
|||
|
udp4VoiceSend = new UdpMulticast(voiceMulticastIP4Send, voice_port);
|
|||
|
|
|||
|
|
|||
|
RadioStatusProp = RADIO_STATUS.FREE;
|
|||
|
|
|||
|
listenThread = new Thread(new ThreadStart(Listen2MessageBus));
|
|||
|
listenThread.IsBackground = true;
|
|||
|
listenThread.Start();
|
|||
|
|
|||
|
#region LINX
|
|||
|
#if LINXB
|
|||
|
_timerPrivatePTTToLinx = new System.Timers.Timer(MS_TO_WAIT_FOR_LINX_CALL_SETUP);
|
|||
|
_timerPrivatePTTToLinx.Elapsed += _timerLinx_Elapsed;
|
|||
|
_timerPrivatePTTToLinx.AutoReset = false;
|
|||
|
#endif
|
|||
|
#endregion
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
private void Listen2MessageBus()
|
|||
|
{
|
|||
|
//SafeMobileLib.Utils.WriteLine("UDP multicast listen thread started!!!"+mcastGroup);
|
|||
|
while (true)
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
if (MessageBusHandler.MBMessageQueues_Hash.ContainsKey(radioID))
|
|||
|
{
|
|||
|
MessageBusMessage msg = ((InterthreadMessageQueue<MessageBusMessage>)
|
|||
|
MessageBusHandler.MBMessageQueues_Hash[radioID]).GetItem(100);
|
|||
|
if (msg!=null)
|
|||
|
BusMessageParser(msg);
|
|||
|
}
|
|||
|
Thread.Sleep(100);
|
|||
|
}
|
|||
|
catch (ThreadAbortException)
|
|||
|
{
|
|||
|
break;
|
|||
|
}
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("RadioComHandler.cs->Listen2MessageBus" + ex.ToString());
|
|||
|
Thread.Sleep(10);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private void BusMessageParser(MessageBusMessage msg)
|
|||
|
{
|
|||
|
|
|||
|
SafeMobileLib.Utils.WriteLine("Got " + msg.OPcode, ConsoleColor.Red);
|
|||
|
|
|||
|
if ((RadioStatus != RADIO_STATUS.FREE)
|
|||
|
&& (msg.OPcode != 111)//all call stop
|
|||
|
&& (msg.OPcode != 112)//private call stop
|
|||
|
&& (msg.OPcode != 113)//group call stop
|
|||
|
&& (msg.OPcode != 160)//Dkey
|
|||
|
&& (RadioStatus != RADIO_STATUS.HangTime))
|
|||
|
{
|
|||
|
SendRadioBussy(msg.SeqID, RadioStatus);
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
switch (msg.OPcode)
|
|||
|
{
|
|||
|
case 104:
|
|||
|
SafeMobileLib.Utils.WriteLine("RadioComHandler ID:"+radioID+" processing zone and channel change request");
|
|||
|
channelQuerry_seqID = msg.SeqID;
|
|||
|
RadioStatusProp = RADIO_STATUS.ChannelQuery;
|
|||
|
StartCheckStatusTimer();
|
|||
|
//send channel change request to radio
|
|||
|
radioCon.SendChannelChange(msg.ZoneNr, msg.ChannelNr);
|
|||
|
break;
|
|||
|
|
|||
|
case 94:
|
|||
|
SafeMobileLib.Utils.WriteLine("RadioComHandler ID:" + radioID + "processing SOFTWARE zone and channel change request ");
|
|||
|
channelQuerry_seqID = msg.SeqID;
|
|||
|
SafeMobileLib.Utils.WriteLine("SOFTWARE channel broadcast sending it to message bus(opcode-124)");
|
|||
|
//build string
|
|||
|
string test = "#124#" + Main.GWID + "." + radioID + "#" + sw_zone_nr.ToString() + "." + sw_channel_nr.ToString() + "#";
|
|||
|
if (channelQuerry_seqID.Length > 2) MessageBusHandler.SendOnMsgBuss(channelQuerry_seqID, test);
|
|||
|
else MessageBusHandler.SendOnMsgBuss("0.0", test);//Broadcast
|
|||
|
break;
|
|||
|
|
|||
|
case 101:
|
|||
|
SafeMobileLib.Utils.WriteLine($"RadioComHandler - processing all call request radioID = {radioID} ");
|
|||
|
//setting status to all call ini and starting timer
|
|||
|
RadioStatusProp = RADIO_STATUS.ALLcall_INIT;
|
|||
|
StartCheckStatusTimer();
|
|||
|
|
|||
|
if (PTTbussy)
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("PTTbussy=" + PTTbussy + " speakersOn=" + speakersOn);
|
|||
|
test = "#121#" + Main.GWID + "." + radioID + "#2#";
|
|||
|
MessageBusHandler.SendOnMsgBuss(msg.SeqID, test, $"It is busy. cannot process all call request radioID = {radioID}");
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
radioCon.SendCallType(2, 0);
|
|||
|
bool ret = radioCon.SendPTTon();
|
|||
|
if (ret)
|
|||
|
{
|
|||
|
voiceMulticastIP4Recv = msg.VoiceMulticastIP4Send;
|
|||
|
callType = 101;
|
|||
|
callSeqID = msg.SeqID;
|
|||
|
#if LINXB
|
|||
|
// Reset Linx call info to default value just in case
|
|||
|
ResetLinxCallInfoValue();
|
|||
|
#endif
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
test = "#121#" + Main.GWID + "." + radioID + "#2#";
|
|||
|
MessageBusHandler.SendOnMsgBuss(msg.SeqID, test, $"cannot process all call request radioID = {radioID}");
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
case 111:
|
|||
|
SafeMobileLib.Utils.WriteLine($"RadioComHandler - processing all call stop for radioID = {radioID}");
|
|||
|
|
|||
|
if (RadioStatus != RADIO_STATUS.ALLcall_INPROGRES)
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("Radio status!= ALLcall_INPROGRES could not process all call stop.Current Status:" + RadioStatus);
|
|||
|
//send 115 failed to SD
|
|||
|
string message = "#115#" + Main.GWID + "." + radioID + "#2#";
|
|||
|
MessageBusHandler.SendOnMsgBuss(msg.SeqID, message, $"Not in progres, cannot process all call stop for radioID = {radioID}");
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
if (PTTbussy == true)
|
|||
|
{
|
|||
|
callType = 101;
|
|||
|
callSeqID = msg.SeqID;
|
|||
|
radioCon.SendPTToff();
|
|||
|
|
|||
|
SafeMobileLib.Utils.WriteLine("UDP4VoiceRecv - Stop Listen " + " PTT BUSY 111");
|
|||
|
udp4VoiceRecv.StopListen();
|
|||
|
|
|||
|
StopCheckPTTTimer();
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("PTTbussy != true could not process all call stop");
|
|||
|
//send 115 failed to SD
|
|||
|
string message = "#115#" + Main.GWID + "." + radioID + "#2#";
|
|||
|
MessageBusHandler.SendOnMsgBuss(msg.SeqID, message);
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
case 102:
|
|||
|
SafeMobileLib.Utils.WriteLine($"RadioComHandler - processing private call request for radioID = {radioID}");
|
|||
|
|
|||
|
//temporary removed speakersOn from IF
|
|||
|
if (PTTbussy)
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("PTTbussy=" + PTTbussy + " speakersOn=" + speakersOn);
|
|||
|
test = "#122#" + Main.GWID + "." + radioID + "#2#";
|
|||
|
MessageBusHandler.SendOnMsgBuss(msg.SeqID, test, $"It is busy, cannot process all call request for radioID = {radioID}");
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
if (callType != 102 || RadioStatus != RADIO_STATUS.HangTime)
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("Changing call type to private call 102");
|
|||
|
radioCon.SendCallType(1, msg.SUID);
|
|||
|
}
|
|||
|
|
|||
|
//seting status to private call and starting timer
|
|||
|
RadioStatusProp = RADIO_STATUS.PrivateCall_INIT;
|
|||
|
|
|||
|
StartCheckStatusTimer();
|
|||
|
|
|||
|
bool ret2 = radioCon.SendPTTon();
|
|||
|
if (ret2)
|
|||
|
{
|
|||
|
voiceMulticastIP4Recv = msg.VoiceMulticastIP4Send;
|
|||
|
callType = 102;
|
|||
|
callSeqID = msg.SeqID;
|
|||
|
#if LINXB
|
|||
|
// Reset Linx call info to default value just in case
|
|||
|
ResetLinxCallInfoValue();
|
|||
|
#endif
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("SendPTTon command has failed");
|
|||
|
test = "#122#" + Main.GWID + "." + radioID + "#2#";
|
|||
|
MessageBusHandler.SendOnMsgBuss(msg.SeqID, test, $"cannot process all call request for radioID = {radioID}");
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
case 112:
|
|||
|
SafeMobileLib.Utils.WriteLine($"RadioComHandler - processing private call stop for radioID = {radioID}");
|
|||
|
if (RadioStatus != RADIO_STATUS.PrivateCall_INPROGRES)
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("Radio status!= PrivateCall_INPROGRES could not process private call stop.Current Status:" + RadioStatus);
|
|||
|
|
|||
|
//send 115 failed to SD
|
|||
|
string message = "#116#" + Main.GWID + "." + radioID + "#2#";
|
|||
|
MessageBusHandler.SendOnMsgBuss(msg.SeqID, message, $"Not in progress, cannot process private call stop for radioID = {radioID}");
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
if (PTTbussy == true)
|
|||
|
{
|
|||
|
callType = 102;
|
|||
|
callSeqID = msg.SeqID;
|
|||
|
radioCon.SendPTToff();
|
|||
|
|
|||
|
SafeMobileLib.Utils.WriteLine("UDP4VoiceRecv - Stop Listen " + " PTT Busy 112");
|
|||
|
udp4VoiceRecv.StopListen();
|
|||
|
|
|||
|
StopCheckPTTTimer();
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("PTTbussy != true could not process private call stop");
|
|||
|
//send 115 failed to SD
|
|||
|
string message = "#116#" + Main.GWID + "." + radioID + "#2#";
|
|||
|
MessageBusHandler.SendOnMsgBuss(msg.SeqID, message, $"Not in call, cannot process private call stop for radioID = {radioID}");
|
|||
|
}
|
|||
|
break;
|
|||
|
case 103:
|
|||
|
SafeMobileLib.Utils.WriteLine($"RadioComHandler - processing group call request radioID = {radioID}");
|
|||
|
|
|||
|
if (PTTbussy)
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("PTTbussy=" + PTTbussy + " speakersOn=" + speakersOn);
|
|||
|
test = "#123#" + Main.GWID + "." + radioID + "#2#";
|
|||
|
MessageBusHandler.SendOnMsgBuss(msg.SeqID, test, $"It is busy, cannot process group call request for radioID = {radioID}");
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
if (callType!=103 || RadioStatus != RADIO_STATUS.HangTime)
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("Changing call type to group call 103");
|
|||
|
radioCon.SendCallType(0, msg.GroupID);
|
|||
|
}
|
|||
|
|
|||
|
RadioStatusProp = RADIO_STATUS.GroupCall_INIT;
|
|||
|
|
|||
|
StartCheckStatusTimer();
|
|||
|
|
|||
|
ret = radioCon.SendPTTon();
|
|||
|
if (ret)
|
|||
|
{
|
|||
|
voiceMulticastIP4Recv = msg.VoiceMulticastIP4Send;
|
|||
|
callType = 103;
|
|||
|
callSeqID = msg.SeqID;
|
|||
|
#if LINXB
|
|||
|
// Reset Linx call info to default value just in case
|
|||
|
ResetLinxCallInfoValue();
|
|||
|
#endif
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
test = "#123#" + Main.GWID + "." + radioID + "#2#";
|
|||
|
MessageBusHandler.SendOnMsgBuss(msg.SeqID, test, $"cannot process group call request for radioID = {radioID}");
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
case 113:
|
|||
|
SafeMobileLib.Utils.WriteLine($"RadioComHandler - processing group call stop for radioID = {radioID}");
|
|||
|
if (RadioStatus != RADIO_STATUS.GroupCall_INPROGRES)
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("Radio status!= GroupCall_INPROGRES could not process group call stop.Current Status:" + RadioStatus);
|
|||
|
//send 115 failed to SD
|
|||
|
string message = "#117#" + Main.GWID + "." + radioID + "#2#";
|
|||
|
MessageBusHandler.SendOnMsgBuss(msg.SeqID, message, $"Not in progress, cannot process group call stop for radioID = {radioID}");
|
|||
|
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
if (PTTbussy == true)
|
|||
|
{
|
|||
|
callType = 103;
|
|||
|
callSeqID = msg.SeqID;
|
|||
|
radioCon.SendPTToff();
|
|||
|
|
|||
|
SafeMobileLib.Utils.WriteLine("UDP4VoiceRecv - Stop Listen " + " PTT Busy 113");
|
|||
|
udp4VoiceRecv.StopListen();
|
|||
|
|
|||
|
StopCheckPTTTimer();
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("PTTbussy != true could not process group call stop");
|
|||
|
//send 115 failed to SD
|
|||
|
string message = "#117#" + Main.GWID + "." + radioID + "#2#";
|
|||
|
MessageBusHandler.SendOnMsgBuss(msg.SeqID, message, $"Not in call, cannot process group call stop for radioID = {radioID}");
|
|||
|
break;
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
case 158:
|
|||
|
{
|
|||
|
// Got new update available
|
|||
|
SafeMobileLib.Utils.WriteLine("GOT Update available " + msg.versionNumber, ConsoleColor.Green);
|
|||
|
|
|||
|
OnNewVersionAvailable?.Invoke(msg.versionNumber);
|
|||
|
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
case 160:
|
|||
|
SafeMobileLib.Utils.WriteLine("RadioComHandler ID:" + radioID + "processing DeKey");
|
|||
|
RadioStatusProp = RADIO_STATUS.DKEY;
|
|||
|
StartCheckStatusTimer();
|
|||
|
radioCon.SendDeKey();
|
|||
|
break;
|
|||
|
case 161:
|
|||
|
SafeMobileLib.Utils.WriteLine("RadioComHandler ID:" + radioID + "processing remote monitor request." + "Id for remote monitor:" + msg.SUID);
|
|||
|
if (RadioStatus != RADIO_STATUS.FREE)
|
|||
|
{
|
|||
|
SendRadioBussy(msg.SeqID, RadioStatus);
|
|||
|
break;
|
|||
|
}
|
|||
|
RadioStatusProp = RADIO_STATUS.RemoteMonitor;
|
|||
|
StartCheckStatusTimer();
|
|||
|
radioCon.SendRemoteMonitor(msg.SUID);
|
|||
|
RemoteseqID = msg.SeqID;
|
|||
|
break;
|
|||
|
|
|||
|
case 238:
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("GOT EMERGENCY ACK " + "[ type " + msg.AlarmType + "] for " + msg.SUID);
|
|||
|
if(msg.AlarmType != AlarmTypes.unknown)
|
|||
|
radioCon.SendEmergencyAck(msg.SUID);
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
default:
|
|||
|
//SafeMobileLib.Utils.WriteLine("Unknown opcode for BusMessageParser file: RADIOCOMHANDLER.cs " + opCode);
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private string GetCallType()
|
|||
|
{
|
|||
|
|
|||
|
switch (RadioStatus)
|
|||
|
{
|
|||
|
case RADIO_STATUS.ALLcall_INIT:
|
|||
|
case RADIO_STATUS.ALLcall_INPROGRES:
|
|||
|
return "all call";
|
|||
|
|
|||
|
case RADIO_STATUS.PrivateCall_INIT:
|
|||
|
case RADIO_STATUS.PrivateCall_INPROGRES:
|
|||
|
return "private call";
|
|||
|
|
|||
|
case RADIO_STATUS.GroupCall_INIT:
|
|||
|
case RADIO_STATUS.GroupCall_INPROGRES:
|
|||
|
return "group call";
|
|||
|
|
|||
|
default:
|
|||
|
return "unknown call";
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
void udp4VoiceRecv_OnNewDataRecv(byte[] data, int dataLen)
|
|||
|
{
|
|||
|
|
|||
|
SafeMobileLib.Utils.WriteLine($"Voice ({GetCallType()}) form SD on ip {voiceMulticastIP4Recv} -> Radio (IMEI: {this.radioIMEI}; IP: {this.radioIP}; soundIn: {INdevId}; soundOut: {OUTdevID}) ");
|
|||
|
try
|
|||
|
{
|
|||
|
buffWaveProvider?.AddSamples(data, 0, dataLen);
|
|||
|
}
|
|||
|
catch (InvalidOperationException)
|
|||
|
{
|
|||
|
// Buffer is full
|
|||
|
SafeMobileLib.Utils.WriteLine($"Radio (IMEI: {this.radioIMEI}; IP: {this.radioIP}; soundIn: {INdevId}; soundOut: {OUTdevID}) has voice from SD buffer full",
|
|||
|
ConsoleColor.Red);
|
|||
|
}
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine(ex.ToString(), ConsoleColor.Red);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private void waveInClass_DataAvailable(object sender, WaveInEventArgs e)
|
|||
|
{
|
|||
|
VoiceReceivedFromRadio(e.Buffer, e.BytesRecorded);
|
|||
|
}
|
|||
|
|
|||
|
public void VoiceReceivedFromRadio(byte[] voiceBuffer, int nbOfAudioBytes)
|
|||
|
{
|
|||
|
|
|||
|
if (speakersOn && nbOfAudioBytes != 0 && PTTbussy && !monitorRequest)
|
|||
|
{
|
|||
|
#if LINXB
|
|||
|
if (LinxCallInfo != LINX.LinxCall.DefaultValue)
|
|||
|
{
|
|||
|
// voice to linx
|
|||
|
RadioVoiceToLinx?.Invoke(this, new LINX.RadioVoiceToLinxEventArgs(voiceBuffer, nbOfAudioBytes));
|
|||
|
if (CALL_TYPE == 103 && GroupCallInitiatedByRadio)
|
|||
|
{
|
|||
|
// Group call initiated by radio
|
|||
|
// Send voice to dispatcher also
|
|||
|
udp4VoiceSend.Send(voiceBuffer, nbOfAudioBytes);
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
//SafeMobileLib.Utils.WriteLine("catre bigu Length: "+dataLen+"#" + voiceMulticastIP4Send);
|
|||
|
udp4VoiceSend.Send(voiceBuffer, nbOfAudioBytes);
|
|||
|
}
|
|||
|
#else
|
|||
|
SafeMobileLib.Utils.WriteLine($"Radio (IMEI: {this.radioIMEI}, IP: {this.radioIP}, soundIN: {INdevId}, soundOUT: {OUTdevID}) puts voice on multicast; " + nbOfAudioBytes + "#" + voiceMulticastIP4Send);
|
|||
|
udp4VoiceSend.Send(voiceBuffer, nbOfAudioBytes);
|
|||
|
#endif
|
|||
|
}
|
|||
|
|
|||
|
if (speakersOn && nbOfAudioBytes != 0 && monitorRequest)
|
|||
|
{
|
|||
|
//SafeMobileLib.Utils.WriteLine("Sending audio data for ROMOTE MONITORING");
|
|||
|
udp4VoiceSend.Send(voiceBuffer, nbOfAudioBytes);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
#region radio connection events
|
|||
|
static int count = 0;
|
|||
|
void radioCon_OnRestartEvent()
|
|||
|
{
|
|||
|
throw new NotImplementedException();
|
|||
|
}
|
|||
|
|
|||
|
void radioCon_OnRemoteControlEvent(bool status, REMOTE_RADIO_FUNCS func, int remote_radioId)
|
|||
|
{
|
|||
|
if (func == REMOTE_RADIO_FUNCS.Monitor)
|
|||
|
{
|
|||
|
if (status)
|
|||
|
{
|
|||
|
string test = "#162#" + Main.GWID + "." + radioID + "." + remote_radioId + "#1#";
|
|||
|
MessageBusHandler.SendOnMsgBuss(RemoteseqID, test);
|
|||
|
monitorID = remote_radioId;
|
|||
|
monitorRequest = true;
|
|||
|
//start voice buss for send
|
|||
|
RadioStatusProp = RADIO_STATUS.RemoteMonitor_INPROGRES;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
string test = "#162#" + Main.GWID + "." + radioID + "." + remote_radioId + "#2#";
|
|||
|
MessageBusHandler.SendOnMsgBuss(RemoteseqID, test);
|
|||
|
RadioStatusProp = RADIO_STATUS.FREE;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
void radioCon_OnChannelEvent(int zoneNr, int channelNr)
|
|||
|
{
|
|||
|
sw_zone_nr = zoneNr;
|
|||
|
sw_channel_nr = channelNr;
|
|||
|
//seqID = "0.0";
|
|||
|
SafeMobileLib.Utils.WriteLine(id_local+"Got a channel broadcast sending it to message bus(opcode-124)");
|
|||
|
//build string
|
|||
|
string test = "#124#" + Main.GWID + "." + radioID + "#" + zoneNr.ToString() + "." + channelNr.ToString() + "#";
|
|||
|
if (channelQuerry_seqID.Length > 2) MessageBusHandler.SendOnMsgBuss(channelQuerry_seqID, test);
|
|||
|
else MessageBusHandler.SendOnMsgBuss("0.0", test);//Broadcast
|
|||
|
|
|||
|
RadioStatusProp = RADIO_STATUS.FREE;
|
|||
|
//send event to GW
|
|||
|
if (this.OnChannelEvent != null)
|
|||
|
{
|
|||
|
this.OnChannelEvent(zoneNr, channelNr);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
void radioCon_OnCallEvent(CALL_STATUS status, int callerID, int callType, int groupID)
|
|||
|
{
|
|||
|
if (radioIMEI != callerID && callerID != 0)
|
|||
|
{
|
|||
|
//SafeMobileLib.Utils.WriteLine("#### " + status);
|
|||
|
SafeMobileLib.Utils.WriteLine("Portable On Call Event #### " + status, ConsoleColor.Magenta);
|
|||
|
//register route
|
|||
|
|
|||
|
if (!Main.capacityPlus)
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("RadioGW received a call from field unit with ID " + callerID + " on gateway radio with IP " + radioIP + " \n\r Adding route to route table if route not present.", ConsoleColor.Red);
|
|||
|
if (RouteManager.NetworkIDs_Hash.ContainsKey(radioIP))
|
|||
|
{
|
|||
|
//RoutingUtils.addRoute(callerID.ToString(), radioIP, RouteManager.NetworkIDs_Hash[radioIP].ToString());
|
|||
|
RoutingUtils.addRoute_withBuffer(callerID.ToString(), radioIP, RouteManager.NetworkIDs_Hash[radioIP].ToString());
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("RouteManager.NetworkIDs_Hash does not contain a key for " + radioIP);
|
|||
|
}
|
|||
|
//RoutingUtils.displayRoutes();
|
|||
|
}
|
|||
|
CALLER_ID = callerID;
|
|||
|
|
|||
|
int callStatus = 0;
|
|||
|
int _callType = 101;
|
|||
|
if (callType == 0x04)
|
|||
|
{
|
|||
|
_callType = 102;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
_callType = (groupID == 0xffffff) ? 101 : 103;
|
|||
|
|
|||
|
}
|
|||
|
CALL_TYPE = _callType;
|
|||
|
|
|||
|
string message = "";
|
|||
|
switch (status)
|
|||
|
{
|
|||
|
case CALL_STATUS.INIT:
|
|||
|
if ((_callType == 101)) // all call
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("------------------------------------------------");
|
|||
|
SafeMobileLib.Utils.WriteLine("Got INITIAL call from:" + callerID + " callType:" + callType + " groupID:" + groupID);
|
|||
|
callStatus = 1;
|
|||
|
|
|||
|
|
|||
|
//send broadcast
|
|||
|
message = "#125#" + Main.GWID + "." + radioID + "." + callerID.ToString() + "#" + callStatus + "#" + _callType + "#" + groupID + "#";
|
|||
|
MessageBusHandler.SendOnMsgBuss("0.0", message, "all call - init");
|
|||
|
|
|||
|
//setting voice on/off
|
|||
|
PTTbussy = true;
|
|||
|
RadioStatusProp = RADIO_STATUS.ALLcall_INPROGRES;
|
|||
|
}
|
|||
|
break;
|
|||
|
case CALL_STATUS.INCALL:
|
|||
|
if (_callType == 102 || _callType == 103) // private or group call
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("Got INCALL call from:" + callerID + " callType:" + callType + " groupID:" + groupID);
|
|||
|
callStatus = 1;
|
|||
|
#if LINXB
|
|||
|
bool isGroupCall = (_callType == 103);
|
|||
|
int? linxIDForPrivateCall = null;
|
|||
|
if (LinxCallInfo != LINX.LinxCall.DefaultValue) // Check if I'm in hangtime with a Linx
|
|||
|
{
|
|||
|
if (_callType == 102)
|
|||
|
{
|
|||
|
// Start timer just for private calls
|
|||
|
_timerPrivatePTTToLinx.Start();
|
|||
|
}
|
|||
|
}
|
|||
|
else if (_callType == 102 && (linxIDForPrivateCall = LinxIDForPrivateCall(callerID)) != null) // Check if i make a private call to a linx
|
|||
|
{
|
|||
|
this.LinxCallInfo = new LINX.LinxCall(linxIDForPrivateCall.Value.ToString(), GetRadioSipID(callerID, false));
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
// normal info for mBus
|
|||
|
//build string
|
|||
|
message = "#125#" + Main.GWID + "." + radioID + "." + callerID.ToString() + "#" + callStatus + "#" + _callType + "#" + groupID + "#";
|
|||
|
MessageBusHandler.SendOnMsgBuss("0.0", message);
|
|||
|
}
|
|||
|
CallLinx?.Invoke(this, new LINX.CallLinxEventArgs(callerID, isGroupCall, groupID));
|
|||
|
#else
|
|||
|
//send broadcast
|
|||
|
message = "#125#" + Main.GWID + "." + radioID + "." + callerID.ToString() + "#" + callStatus + "#" + _callType + "#" + groupID + "#";
|
|||
|
MessageBusHandler.SendOnMsgBuss("0.0", message, "broadcast inCall");
|
|||
|
#endif
|
|||
|
//setting voice on/off
|
|||
|
PTTbussy = true;
|
|||
|
RadioStatusProp = ( _callType == 102 ) ? RADIO_STATUS.PrivateCall_INPROGRES : RADIO_STATUS.GroupCall_INPROGRES;
|
|||
|
|
|||
|
}
|
|||
|
break;
|
|||
|
case CALL_STATUS.HANGTIMER:
|
|||
|
if (_callType == 102 || _callType == 103)
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("Got HANGtimmer call from:" + callerID + " callType:" + callType + " groupID:" + groupID);
|
|||
|
callStatus = 2;
|
|||
|
#if LINXB
|
|||
|
// Check if I'm in hangtime with a Linx
|
|||
|
if (LinxCallInfo != LINX.LinxCall.DefaultValue)
|
|||
|
{
|
|||
|
RadioEndsPTTtoLinx?.Invoke(this, new EventArgs());
|
|||
|
if (this.CALL_TYPE == 103)
|
|||
|
{
|
|||
|
// group call, send hang time command to SD
|
|||
|
// normal info for mBus
|
|||
|
//build string
|
|||
|
message = "#125#" + Main.GWID + "." + radioID + "." + callerID.ToString() + "#" + callStatus + "#" + _callType + "#" + groupID + "#";
|
|||
|
MessageBusHandler.SendOnMsgBuss("0.0", message);
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
// normal info for mBus
|
|||
|
//build string
|
|||
|
message = "#125#" + Main.GWID + "." + radioID + "." + callerID.ToString() + "#" + callStatus + "#" + _callType + "#" + groupID + "#";
|
|||
|
MessageBusHandler.SendOnMsgBuss("0.0", message);
|
|||
|
}
|
|||
|
#else
|
|||
|
//send broadcast
|
|||
|
message = "#125#" + Main.GWID + "." + radioID + "." + callerID.ToString() + "#" + callStatus + "#" + _callType + "#" + groupID + "#";
|
|||
|
MessageBusHandler.SendOnMsgBuss("0.0", message, "broadcast hangtime");
|
|||
|
#endif
|
|||
|
|
|||
|
//setting voice on/off
|
|||
|
PTTbussy = false;
|
|||
|
RadioStatusProp = RADIO_STATUS.HangTime;
|
|||
|
}
|
|||
|
break;
|
|||
|
case CALL_STATUS.CALLEND:
|
|||
|
SafeMobileLib.Utils.WriteLine("Got callend from:" + callerID + " callType:" + callType + " groupID:" + groupID);
|
|||
|
callStatus = 3;
|
|||
|
|
|||
|
#if LINXB
|
|||
|
if (RadioStatusProp != RADIO_STATUS.GroupCall_INIT && LinxCallInfo != LINX.LinxCall.DefaultValue)
|
|||
|
{
|
|||
|
// Clear the details of the previous linx call
|
|||
|
ResetLinxCallInfoValue();
|
|||
|
GroupCallInitiatedByRadio = false;
|
|||
|
|
|||
|
if (this.CALL_TYPE == 103)
|
|||
|
{
|
|||
|
// If is group call, send call end on mbus for dispatcher
|
|||
|
message = "#125#" + Main.GWID + "." + radioID + "." + callerID.ToString() + "#" + callStatus + "#" + _callType + "#" + groupID + "#";
|
|||
|
MessageBusHandler.SendOnMsgBuss("0.0", message);
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
//build string
|
|||
|
message = "#125#" + Main.GWID + "." + radioID + "." + callerID.ToString() + "#" + callStatus + "#" + _callType + "#" + groupID + "#";
|
|||
|
MessageBusHandler.SendOnMsgBuss("0.0", message);
|
|||
|
}
|
|||
|
#else
|
|||
|
//send broadcast
|
|||
|
message = "#125#" + Main.GWID + "." + radioID + "." + callerID.ToString() + "#" + callStatus + "#" + _callType + "#" + groupID + "#";
|
|||
|
MessageBusHandler.SendOnMsgBuss("0.0", message, "broadcast callend");
|
|||
|
#endif
|
|||
|
//setting voice on/off
|
|||
|
PTTbussy = false;
|
|||
|
RadioStatusProp = RADIO_STATUS.FREE;
|
|||
|
SafeMobileLib.Utils.WriteLine("------------------------------------------------");
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
//this is for calls made from SD to GW.
|
|||
|
//callerID is the same as the ID of base station
|
|||
|
SafeMobileLib.Utils.WriteLine("Base Station On Call Event #### " + status, ConsoleColor.Magenta);
|
|||
|
if (status == CALL_STATUS.HANGTIMER)
|
|||
|
{
|
|||
|
//send broadcast
|
|||
|
string test = "#125#" + Main.GWID + "." + radioID + "." + callerID.ToString() + "#2#0#0#";
|
|||
|
MessageBusHandler.SendOnMsgBuss("0.0", test, "broadcast hangtime");
|
|||
|
|
|||
|
|
|||
|
RadioStatusProp = RADIO_STATUS.FREE;
|
|||
|
SafeMobileLib.Utils.WriteLine("------------------------------------------------");
|
|||
|
}
|
|||
|
if (status == CALL_STATUS.CALLEND)
|
|||
|
{
|
|||
|
#if LINXB
|
|||
|
if (RadioStatusProp != RADIO_STATUS.GroupCall_INIT && LinxCallInfo != LINX.LinxCall.DefaultValue)
|
|||
|
{
|
|||
|
// Clear the details of the previous linx call
|
|||
|
ResetLinxCallInfoValue();
|
|||
|
GroupCallInitiatedByRadio = false;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
string test = "#125#" + Main.GWID + "." + radioID + "." + callerID.ToString() + "#3#0#0#";
|
|||
|
MessageBusHandler.SendOnMsgBuss("0.0", test);
|
|||
|
}
|
|||
|
#else
|
|||
|
//send broadcast
|
|||
|
string test = "#125#" + Main.GWID + "." + radioID + "." + callerID.ToString() + "#3#0#0#";
|
|||
|
MessageBusHandler.SendOnMsgBuss("0.0", test, "broadcast callend");
|
|||
|
#endif
|
|||
|
RadioStatusProp = RADIO_STATUS.FREE;
|
|||
|
SafeMobileLib.Utils.WriteLine("------------------------------------------------");
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
void radioCon_OnSpeakersEvent(bool onOFF)
|
|||
|
{
|
|||
|
if (onOFF) { SafeMobileLib.Utils.WriteLine("=============================="); }
|
|||
|
SafeMobileLib.Utils.WriteLine("speakers "+onOFF);
|
|||
|
if (!onOFF) { SafeMobileLib.Utils.WriteLine("=============================="); }
|
|||
|
speakersOn = onOFF;
|
|||
|
if (monitorRequest && !speakersOn)
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("Speakers off.Turning remote monitor OFF");
|
|||
|
RadioStatusProp = RADIO_STATUS.FREE;
|
|||
|
monitorRequest = false;
|
|||
|
string test = "#172#" + Main.GWID + "." + radioID + "." + monitorID + "#1#";
|
|||
|
MessageBusHandler.SendOnMsgBuss("0.0", test);
|
|||
|
}
|
|||
|
|
|||
|
//hangtimmer for private call is handled in speakers event
|
|||
|
|
|||
|
//if (RadioStatus == RADIO_STATUS.CallEvent && !speakersOn && CALL_TYPE==102)
|
|||
|
if (RadioStatus == RADIO_STATUS.PrivateCall_INPROGRES && !speakersOn && CALL_TYPE == 102)
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("Got HANGtimmer call from:" + CALLER_ID + " callType:" + callType + " groupID:0");
|
|||
|
bool onOff = false;
|
|||
|
int callStatus = 2;
|
|||
|
|
|||
|
//send broadcast
|
|||
|
string message = "#125#" + Main.GWID + "." + radioID + "." + CALLER_ID.ToString() + "#" + callStatus + "#102#0#";
|
|||
|
MessageBusHandler.SendOnMsgBuss("0.0", message);
|
|||
|
|
|||
|
//setting voice on/off
|
|||
|
PTTbussy = onOff;
|
|||
|
RadioStatusProp = RADIO_STATUS.FREE;
|
|||
|
}
|
|||
|
PTTbussy = onOFF;
|
|||
|
}
|
|||
|
|
|||
|
void radioCon_OnTransmitEvent(bool onOFF)
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
//if call originate from BASE stattion it means that the base sation made a call
|
|||
|
// 101-all call 102 - private call 103- group call
|
|||
|
// send back to SD the appropiete response(call on/off)
|
|||
|
SafeMobileLib.Utils.WriteLine($"radioCon_OnTransmitEvent CALL TYPE : {callType}" );
|
|||
|
if (callType != 0)
|
|||
|
{
|
|||
|
switch (callType)
|
|||
|
{
|
|||
|
case 101:
|
|||
|
if (onOFF)
|
|||
|
{
|
|||
|
SendALLcallACK2SD(callSeqID);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
if (RadioStatusProp == RADIO_STATUS.ALLcall_INIT)
|
|||
|
{
|
|||
|
//ALL call could not be performend!!!(channel bussy or something)
|
|||
|
radioCon.SendPTToff();
|
|||
|
}
|
|||
|
//send ack to SD
|
|||
|
string test = "#115#" + Main.GWID + "." +radioID + "#1#";
|
|||
|
MessageBusHandler.SendOnMsgBuss(callSeqID, test, "all call off - send ack to SD");
|
|||
|
|
|||
|
PTTbussy = false;
|
|||
|
RadioStatusProp = RADIO_STATUS.FREE;
|
|||
|
tCheckPTT = null;
|
|||
|
}
|
|||
|
callType = 0;
|
|||
|
break;
|
|||
|
|
|||
|
case 102:
|
|||
|
if (onOFF)
|
|||
|
SendPrivateCallACK2SD(callSeqID);
|
|||
|
else
|
|||
|
{
|
|||
|
if (RadioStatusProp == RADIO_STATUS.PrivateCall_INIT)
|
|||
|
{
|
|||
|
//Private call could not be performend!!!(channel bussy or something)
|
|||
|
radioCon.SendPTToff();
|
|||
|
}
|
|||
|
//send ack to SD
|
|||
|
string test = "#116#" +Main.GWID + "." + radioID +"#1#";
|
|||
|
MessageBusHandler.SendOnMsgBuss(callSeqID, test, "private call off - send ack to SD");
|
|||
|
|
|||
|
PTTbussy = false;
|
|||
|
RadioStatusProp = RADIO_STATUS.FREE;
|
|||
|
tCheckPTT = null;
|
|||
|
}
|
|||
|
callType = 0;
|
|||
|
break;
|
|||
|
#if LINXB
|
|||
|
case 1002: // Private linx call
|
|||
|
if (onOFF)
|
|||
|
{
|
|||
|
PTTbussy = true;
|
|||
|
RadioStatusProp = RADIO_STATUS.PrivateCall_INPROGRES;
|
|||
|
// Send 122 to notify dispatchers on mbus that radio gw is busy
|
|||
|
MessageBusHandler.SendOnMsgBuss("123456789", "#122#" + Main.GWID + "." + radioID + "#1#");
|
|||
|
|
|||
|
if (LinxCallInfo != LINX.LinxCall.DefaultValue)
|
|||
|
{
|
|||
|
// Fire event - linx call established
|
|||
|
LinxCallEstablished?.Invoke(this, new EventArgs());
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
if (RadioStatusProp == RADIO_STATUS.PrivateCall_INIT)
|
|||
|
{
|
|||
|
//Private call could not be performend!!!(channel bussy or something)
|
|||
|
radioCon.SendPTToff();
|
|||
|
if (LinxCallInfo != LINX.LinxCall.DefaultValue)
|
|||
|
{
|
|||
|
// Notify the Linx
|
|||
|
LinxCallFailed?.Invoke(this, new EventArgs());
|
|||
|
}
|
|||
|
}
|
|||
|
PTTbussy = false;
|
|||
|
RadioStatusProp = RADIO_STATUS.FREE;
|
|||
|
// send 116 on mbus to notify dispatchers that the radio gw is free
|
|||
|
string test = "#116#" + Main.GWID + "." + radioID + "#1#";
|
|||
|
MessageBusHandler.SendOnMsgBuss("123456789", test);
|
|||
|
// tCheckPTT = null is not necessary
|
|||
|
}
|
|||
|
break;
|
|||
|
#endif
|
|||
|
case 103:
|
|||
|
if (onOFF)
|
|||
|
SendGroupCallACK2SD(callSeqID);
|
|||
|
else
|
|||
|
{
|
|||
|
if (RadioStatusProp == RADIO_STATUS.GroupCall_INIT)
|
|||
|
{
|
|||
|
//Group call could not be performend!!!(channel bussy or something)
|
|||
|
radioCon.SendPTToff();
|
|||
|
}
|
|||
|
//send ack to SD
|
|||
|
string test = "#117#" + Main.GWID + "." + radioID + "#1#";
|
|||
|
MessageBusHandler.SendOnMsgBuss(callSeqID, test, "group call off - send ack to SD");
|
|||
|
|
|||
|
PTTbussy = false;
|
|||
|
RadioStatusProp = RADIO_STATUS.FREE;
|
|||
|
tCheckPTT = null;
|
|||
|
}
|
|||
|
callType = 0;
|
|||
|
break;
|
|||
|
#if LINXB
|
|||
|
case 1003: // Group Linx call
|
|||
|
if (onOFF)
|
|||
|
{
|
|||
|
PTTbussy = true;
|
|||
|
RadioStatusProp = RADIO_STATUS.GroupCall_INPROGRES;
|
|||
|
// Send 123 to notify dispatchers on mbus that radio gw is busy
|
|||
|
MessageBusHandler.SendOnMsgBuss("123456789", "#123#" + Main.GWID + "." + radioID + "#1#");
|
|||
|
if (LinxCallInfo != LINX.LinxCall.DefaultValue)
|
|||
|
{
|
|||
|
// Fire event - linx call established
|
|||
|
LinxCallEstablished?.Invoke(this, new EventArgs());
|
|||
|
}
|
|||
|
else
|
|||
|
SafeMobileLib.Utils.WriteLine("------------- Here i should start the call but i dont do it", ConsoleColor.Red);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
if (RadioStatusProp == RADIO_STATUS.GroupCall_INIT)
|
|||
|
{
|
|||
|
//Group call could not be performend!!!(channel bussy or something)
|
|||
|
radioCon.SendPTToff();
|
|||
|
if (LinxCallInfo != LINX.LinxCall.DefaultValue)
|
|||
|
{
|
|||
|
// Notify linx to close the call
|
|||
|
LinxCallFailed?.Invoke(this, new EventArgs());
|
|||
|
}
|
|||
|
}
|
|||
|
PTTbussy = false;
|
|||
|
RadioStatusProp = RADIO_STATUS.FREE;
|
|||
|
// send 117 on mbus to notify dispatchers that the readio gw is free
|
|||
|
string test = "#117#" + Main.GWID + "." + radioID + "#1#";
|
|||
|
MessageBusHandler.SendOnMsgBuss(callSeqID, test);
|
|||
|
// tCheckPTT = null; this in useless
|
|||
|
}
|
|||
|
break;
|
|||
|
#endif
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine(ex.ToString());
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//if timer expired(1min) auto send PTT off
|
|||
|
private void CheckPTT(Object state)
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("@@@@@@@@@ PTT timer expired ... sending PTT oFF !!!!!!!!for:"+radioIP+"@@@@@@@@@@");
|
|||
|
if (PTTbussy == true)
|
|||
|
{
|
|||
|
radioCon.SendPTToff();
|
|||
|
|
|||
|
SafeMobileLib.Utils.WriteLine("UDP4VoiceRecv - Stop Listen " + " PTT Expired ");
|
|||
|
udp4VoiceRecv.StopListen();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private void CheckSTATUS(Object state)
|
|||
|
{
|
|||
|
if ((RadioStatus != RADIO_STATUS.ALLcall_INPROGRES) &&
|
|||
|
(RadioStatus != RADIO_STATUS.PrivateCall_INPROGRES)&&
|
|||
|
(RadioStatus != RADIO_STATUS.GroupCall_INPROGRES)&&
|
|||
|
(RadioStatus != RADIO_STATUS.RemoteMonitor_INPROGRES)&&
|
|||
|
(RadioStatus != RADIO_STATUS.HangTime) &&
|
|||
|
(RadioStatus != RADIO_STATUS.FREE))
|
|||
|
{
|
|||
|
RadioStatusProp = RADIO_STATUS.FREE;
|
|||
|
SafeMobileLib.Utils.WriteLine("!!!!!!!!Timer expired and nothing happend... setting radio status to FREE!!!!!");
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private String RemoteseqID = "";
|
|||
|
private string channelQuerry_seqID = "";
|
|||
|
|
|||
|
#endregion
|
|||
|
//methods for GW
|
|||
|
#region methods for GW
|
|||
|
public bool Start()
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("IndecId:" + INdevId + "outdev:" + OUTdevID);
|
|||
|
//test radio com
|
|||
|
if (radioCon.Connected)
|
|||
|
{
|
|||
|
//start messageBus listner
|
|||
|
//udp.StartListen();
|
|||
|
//start voice
|
|||
|
if ((INdevId != -1) && (OUTdevID != -1))
|
|||
|
{
|
|||
|
NAudio.Wave.WaveFormat waveFormat = new NAudio.Wave.WaveFormat(Main.sampleRate, Main.bitdepth, 1);
|
|||
|
buffWaveProvider = new BufferedWaveProvider(waveFormat);
|
|||
|
if (Main.AudioDriver == AudioDriverType.Windows)
|
|||
|
{
|
|||
|
|
|||
|
_audioManager = new AudioManager(OUTdevID, INdevId, Main.recordedBufferMiliseconds, waveFormat);
|
|||
|
_audioManager.WaveInAudioAvailable += waveInClass_DataAvailable;
|
|||
|
_audioManager.Init(buffWaveProvider);
|
|||
|
_audioManager.WaveInStartRecording();
|
|||
|
_audioManager.Play();
|
|||
|
}
|
|||
|
connected = true;
|
|||
|
return true;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("Unable to start audio device");
|
|||
|
connected = false;
|
|||
|
return false;
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
public void Stop()
|
|||
|
{
|
|||
|
|
|||
|
connected = false;
|
|||
|
//send stop message to MSG bus
|
|||
|
string test = "#100#" + Main.GWID + "." + radioID + "#0#";
|
|||
|
MessageBusHandler.SendOnMsgBuss("0.0", test);
|
|||
|
_audioManager?.Dispose();
|
|||
|
if (udp4VoiceRecv != null)
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("UDP4VoiceRecv - Stop Listen " + " STOP");
|
|||
|
udp4VoiceRecv.StopListen();
|
|||
|
}
|
|||
|
|
|||
|
//detach events
|
|||
|
radioCon.OnChannelEvent -= new RadioConnection.ChannelEvent(radioCon_OnChannelEvent);
|
|||
|
radioCon.OnCallEvent -= new RadioConnection.CallEvent(radioCon_OnCallEvent);
|
|||
|
radioCon.OnSpeakersEvent -= new RadioConnection.SpeakersEvent(radioCon_OnSpeakersEvent);
|
|||
|
radioCon.OnRemoteControlEvent -= new RadioConnection.RemoteControlEvent(radioCon_OnRemoteControlEvent);
|
|||
|
radioCon.OnTransmitEvent -= new RadioConnection.TransmitEvent(radioCon_OnTransmitEvent);
|
|||
|
radioCon.OnRestartEvent -= new RadioConnection.RestartEvent(radioCon_OnRestartEvent);
|
|||
|
|
|||
|
if (listenThread != null)
|
|||
|
{
|
|||
|
listenThread.Abort();
|
|||
|
listenThread = null;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public void SendZoneChannelChange(int zoneNr, int channelNr)
|
|||
|
{
|
|||
|
radioCon.SendChannelChange(zoneNr, channelNr);
|
|||
|
}
|
|||
|
|
|||
|
public void StartCheckStatusTimer()
|
|||
|
{
|
|||
|
tCheckSTATUS = new System.Threading.Timer(CheckSTATUS, null, 5000, System.Threading.Timeout.Infinite);
|
|||
|
}
|
|||
|
|
|||
|
#endregion
|
|||
|
|
|||
|
private void StartCheckPTTTimer()
|
|||
|
{
|
|||
|
if (tCheckPTT != null)
|
|||
|
tCheckPTT.Dispose();
|
|||
|
|
|||
|
tCheckPTT = new System.Threading.Timer(CheckPTT, null, 55000, System.Threading.Timeout.Infinite);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
private void StopCheckPTTTimer()
|
|||
|
{
|
|||
|
if (tCheckPTT != null)
|
|||
|
tCheckPTT.Dispose();
|
|||
|
|
|||
|
tCheckPTT = null;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
#region events
|
|||
|
public delegate void ChannelEvent(int zoneNr, int channelNr);
|
|||
|
public event ChannelEvent OnChannelEvent;
|
|||
|
|
|||
|
public delegate void AuthDoneDEl();
|
|||
|
public event AuthDoneDEl OnAuthDone;
|
|||
|
#endregion
|
|||
|
|
|||
|
private void SendALLcallACK2SD(string _seqID)
|
|||
|
{
|
|||
|
string test = "#121#" + Main.GWID + "." + radioID + "#1#";
|
|||
|
MessageBusHandler.SendOnMsgBuss(_seqID, test, "all call on - send ack to SD");
|
|||
|
|
|||
|
SafeMobileLib.Utils.WriteLine("\n\n########### **************** ALL CALL VOICE ACK: " + voiceMulticastIP4Recv);
|
|||
|
SafeMobileLib.Utils.WriteLine("########### **************** GwID =" + Main.GWID + " | radioID = " + radioID + " | \n\n");
|
|||
|
|
|||
|
PTTbussy = true;
|
|||
|
|
|||
|
//start voice buss for send
|
|||
|
StartVoiceBuss();
|
|||
|
StartCheckPTTTimer();
|
|||
|
|
|||
|
RadioStatusProp = RADIO_STATUS.ALLcall_INPROGRES;
|
|||
|
}
|
|||
|
|
|||
|
private void SendPrivateCallACK2SD(string _seqID)
|
|||
|
{
|
|||
|
string test = "#122#" + Main.GWID + "." + radioID + "#1#";
|
|||
|
MessageBusHandler.SendOnMsgBuss(_seqID, test, "private call on - send ack to SD");
|
|||
|
|
|||
|
SafeMobileLib.Utils.WriteLine("\n\n########### **************** PRIVATE CALL VOICE ACK: " + voiceMulticastIP4Recv);
|
|||
|
SafeMobileLib.Utils.WriteLine("########### **************** GwID =" + Main.GWID + " | radioID = " + radioID + " | \n\n");
|
|||
|
|
|||
|
PTTbussy = true;
|
|||
|
|
|||
|
//start voice buss for send
|
|||
|
StartVoiceBuss();
|
|||
|
StartCheckPTTTimer();
|
|||
|
|
|||
|
RadioStatusProp = RADIO_STATUS.PrivateCall_INPROGRES;
|
|||
|
}
|
|||
|
|
|||
|
private void StartVoiceBuss()
|
|||
|
{
|
|||
|
udp4VoiceRecv = new UdpMulticast(voiceMulticastIP4Recv, voice_port);
|
|||
|
udp4VoiceRecv.OnNewDataRecv += new UdpMulticast.newData4Send(udp4VoiceRecv_OnNewDataRecv);
|
|||
|
udp4VoiceRecv.StartListen(Main.LocalIP);
|
|||
|
}
|
|||
|
|
|||
|
private void SendGroupCallACK2SD(string _seqID)
|
|||
|
{
|
|||
|
string test = "#123#" + Main.GWID + "." + radioID + "#1#";
|
|||
|
MessageBusHandler.SendOnMsgBuss(_seqID, test, "group call on - send ack to SD");
|
|||
|
|
|||
|
SafeMobileLib.Utils.WriteLine("\n\n########### **************** GROUP CALL VOICE ACK: " + voiceMulticastIP4Recv);
|
|||
|
SafeMobileLib.Utils.WriteLine("########### **************** GwID = " + Main.GWID + " | radioID = " + radioID + " | \n\n");
|
|||
|
|
|||
|
PTTbussy = true;
|
|||
|
|
|||
|
//start voice buss for send
|
|||
|
StartVoiceBuss();
|
|||
|
StartCheckPTTTimer();
|
|||
|
|
|||
|
RadioStatusProp = RADIO_STATUS.GroupCall_INPROGRES;
|
|||
|
}
|
|||
|
|
|||
|
private void SendRadioBussy(string _seqID,RADIO_STATUS status)
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine("Sending Radio bussy. reason "+status +" status byte:"+((byte)status));
|
|||
|
//string test = "#10#" + Main.GWID + "." + radioID + "#"+((byte)status).ToString()+"#2#";
|
|||
|
string test = "#122#" + Main.GWID + "." + radioID + "#2#";
|
|||
|
MessageBusHandler.SendOnMsgBuss(_seqID, test, "Radio is busy!");
|
|||
|
}
|
|||
|
|
|||
|
internal void ClearVoiceResources()
|
|||
|
{
|
|||
|
//if (r.rcHandler.waveOutClass != null)
|
|||
|
//{
|
|||
|
// r.rcHandler.waveOutClass.Dispose();
|
|||
|
// r.rcHandler.waveOutClass = null;
|
|||
|
//}
|
|||
|
|
|||
|
//if (r.rcHandler.waveInClass != null)
|
|||
|
//{
|
|||
|
// r.rcHandler.waveInClass.DataAvailable -= r.rcHandler.waveInClass_DataAvailable;
|
|||
|
// r.rcHandler.waveInClass.Dispose();
|
|||
|
// r.rcHandler.waveInClass = null;
|
|||
|
//}
|
|||
|
|
|||
|
if (_audioManager != null)
|
|||
|
{
|
|||
|
_audioManager.WaveInAudioAvailable -= waveInClass_DataAvailable;
|
|||
|
_audioManager.Dispose();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public delegate void NewVersionAvailableDel(String version);
|
|||
|
public event NewVersionAvailableDel OnNewVersionAvailable;
|
|||
|
|
|||
|
|
|||
|
#region METHODS for Linx
|
|||
|
|
|||
|
#if LINXB
|
|||
|
internal bool InviteFromLinx(string linxSipID, int radioSipID, int radioID, bool isGroupCall)
|
|||
|
{
|
|||
|
bool success = false;
|
|||
|
|
|||
|
if (IsPTTbussy)
|
|||
|
{
|
|||
|
SafeMobileLib.Utils.WriteLine($@"Decline the inivite from sip id {linxSipID} to radio {radioID}
|
|||
|
because base station {this.radioID} is ptt busy", ConsoleColor.DarkRed);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
if (isGroupCall)
|
|||
|
{
|
|||
|
radioCon.SendCallType(0, radioID); // group radio ptt
|
|||
|
RadioStatusProp = RADIO_STATUS.GroupCall_INIT;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
radioCon.SendCallType(1, radioID); // private radio ptt
|
|||
|
RadioStatusProp = RADIO_STATUS.PrivateCall_INIT;
|
|||
|
}
|
|||
|
// start the tCheckStatus timer
|
|||
|
StartCheckStatusTimer();
|
|||
|
success = radioCon.SendPTTon();
|
|||
|
if (success)
|
|||
|
{
|
|||
|
this.LinxCallInfo = new LINX.LinxCall(linxSipID, radioSipID);
|
|||
|
callType = isGroupCall ? 1003 : 1002;
|
|||
|
}
|
|||
|
else
|
|||
|
SafeMobileLib.Utils.WriteLine($@"Decline the inivite from sip id {linxSipID} to radio {radioID}
|
|||
|
because base station {this.radioID} failed to send PTT", ConsoleColor.DarkRed);
|
|||
|
}
|
|||
|
return success;
|
|||
|
}
|
|||
|
|
|||
|
internal void LinxReceivesPTTFromRadio(LINX.LinxCall linxCall)
|
|||
|
{
|
|||
|
if (this.CALL_TYPE == 102)
|
|||
|
{
|
|||
|
// Stop the timer for private calls
|
|||
|
_timerPrivatePTTToLinx.Stop();
|
|||
|
}
|
|||
|
else if (this.CALL_TYPE == 103)
|
|||
|
{
|
|||
|
// Ensure that voice is being sent to LINX
|
|||
|
this.LinxCallInfo = linxCall;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private void _timerLinx_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
|
|||
|
{
|
|||
|
// If timer has elapsed then the dialog with linx has not been established on portable ptt button press
|
|||
|
// I will send dekey to the portable in this case
|
|||
|
if (RadioStatusProp == RADIO_STATUS.CallEvent)
|
|||
|
{
|
|||
|
RadioStatusProp = RADIO_STATUS.DKEY;
|
|||
|
StartCheckStatusTimer();
|
|||
|
radioCon.SendDeKey();
|
|||
|
RadioEndsPTTtoLinx?.Invoke(this, new EventArgs());
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private int GetRadioSipID(int radioID, bool isGroup)
|
|||
|
{
|
|||
|
int? radioSipID = RadioSipIDRequested?.Invoke(radioID, isGroup);
|
|||
|
return radioSipID ?? -1;
|
|||
|
}
|
|||
|
|
|||
|
private int? LinxIDForPrivateCall(int radioID)
|
|||
|
{
|
|||
|
int? linxID = LinxIDForPrivateCallRequested?.Invoke(radioID);
|
|||
|
return linxID;
|
|||
|
}
|
|||
|
|
|||
|
public void ResetLinxCallInfoValue()
|
|||
|
{
|
|||
|
this.LinxCallInfo = LINX.LinxCall.DefaultValue;
|
|||
|
}
|
|||
|
#endif
|
|||
|
#endregion
|
|||
|
|
|||
|
|
|||
|
#region EVENTS for Linx
|
|||
|
#if LINXB
|
|||
|
public event EventHandler LinxCallEstablished;
|
|||
|
public event EventHandler LinxCallFailed;
|
|||
|
public event EventHandler<LINX.CallLinxEventArgs> CallLinx;
|
|||
|
public event EventHandler<LINX.RadioVoiceToLinxEventArgs> RadioVoiceToLinx;
|
|||
|
public event EventHandler RadioEndsPTTtoLinx;
|
|||
|
|
|||
|
public delegate int? LinxIDForPrivateCallDel(int radioID);
|
|||
|
public event LinxIDForPrivateCallDel LinxIDForPrivateCallRequested;
|
|||
|
|
|||
|
public delegate int RadioSipIDRequestedDel(int radioID, bool isGroup);
|
|||
|
public event RadioSipIDRequestedDel RadioSipIDRequested;
|
|||
|
|
|||
|
|
|||
|
#endif
|
|||
|
#endregion
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
public enum RADIO_STATUS
|
|||
|
{
|
|||
|
OFF = 0x00,
|
|||
|
FREE = 0x01,
|
|||
|
ALLcall_INIT = 101,
|
|||
|
ALLcall_INPROGRES = 121,
|
|||
|
PrivateCall_INIT = 102,
|
|||
|
PrivateCall_INPROGRES = 122,
|
|||
|
GroupCall_INIT = 103,
|
|||
|
GroupCall_INPROGRES = 123,
|
|||
|
ChannelQuery = 104,
|
|||
|
CallEvent = 125,
|
|||
|
RemoteMonitor = 161,
|
|||
|
RemoteMonitor_INPROGRES = 162,
|
|||
|
DKEY = 160,
|
|||
|
EnableDisable = 150,
|
|||
|
HangTime = 108,
|
|||
|
}
|
|||
|
}
|