SafeNet/Hytera_SOC/RadioHyt.cs
2021-02-24 13:50:23 +02:00

515 lines
19 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using HyteraWrapper;
using SafeNetLib;
using System.Threading;
using System.Collections;
namespace Hytera_SOC
{
class RadioHyt
{
private bool connected = false;
public bool Connected
{
get { return connected; }
set { connected = value; }
}
private bool firstStart = false;
private bool RRScon = false;
private bool TMcon = false;
private bool LPIcon = false;
private bool CCcon = false;
private GatewayRadio gw;
private string ip;
public string IP
{
get { return ip; }
set { ip = value; }
}
private UInt32 radioImei;
public UInt32 RadioImei
{
get { return radioImei; }
set { radioImei = value; }
}
private UInt32 uIP;
private byte subID;
private bool validParams;
private SMShandle smshandle = null;
public Thread listenPollThread = null;
private Hashtable location_hash = new Hashtable();
#region constructor + connect
/// <summary>
/// constructor
/// </summary>
/// <param name="p_ip">hyera radio IP</param>
/// <param name="p_subID">subnet ID</param>
/// <param name="p_bsID">base station IMEI</param>
public RadioHyt(string p_ip, byte p_subID, UInt32 p_bsID)
{
this.ip = p_ip;
this.subID = p_subID;
uIP = ConvertIPToLong(ip) + 1;
this.radioImei = p_bsID;
Utils.ConsWrite(DebugMSG_Type.always, "CONSTRUCTOR for " + ip + " subid:" + p_subID);
if (uIP != 0)
{
gw = new GatewayRadio();
validParams = true;
gw.OnRRS_CS += new GatewayRadio.OnRRS_CS_del(gw_OnRRS_CS);
gw.OnLP2_CS += new GatewayRadio.OnLP2_CS_del(gw_OnLP2_CS);
listenPollThread = new Thread(new ThreadStart(PollHandle));
listenPollThread.IsBackground = true;
}
else
{
Utils.ConsWrite(DebugMSG_Type.DEV, "Invalid IP: " + ip);
validParams = false;
}
}
public bool Connect()
{
if (validParams) //&&(!TMcon)
{
if (!firstStart)
{
Utils.ConsWrite(DebugMSG_Type.DEV, "<<<<<<<<<<<<Connecting to TM, RRS and LPI>>>>>>>>>>");
TMcon = ConnectTM(uIP, subID, RadioImei);
Thread.Sleep(500);
//gw.SendSMS(112, "GW started");
//Thread.Sleep(500);
RRScon = ConnectRRS(uIP, subID, RadioImei);
LPIcon = ConnectLPI(uIP, subID, RadioImei);
if (TMcon)
gw.SendSMS(101, "start" + DateTime.Now.ToString());
firstStart = true;
}
if (TMcon && RRScon && LPIcon)
{
connected = true;
Console.WriteLine("==================================");
Utils.ConsWrite(DebugMSG_Type.DEV, "Radio " + ip + " Connected to ARS, GPS and TextMessaging!!!!!");
Console.WriteLine("==================================");
if (smshandle != null)
{
smshandle.Stop();
smshandle = null;
}
gw.OnTM_CS += new GatewayRadio.OnTM_CS_del(gw_OnTM_CS);
smshandle = new SMShandle(gw);
listenPollThread.Start();
}
else
{
Utils.ConsWrite(DebugMSG_Type.DEV, "Connection with Radio " + ip + " ARS, GPS and TextMessaging FAILED!!!!");
}
}
else
{
Utils.ConsWrite(DebugMSG_Type.DEV, "INVALID params could not connect. IP" + ip);
}
return connected;
}
void gw_OnTM_CS(StringBuilder value)
{
Console.WriteLine("TM:" + value.ToString());
}
private bool ConnectTM(uint ip, byte subID, uint id)
{
bool ret = false;
try
{
ret = gw.connectTM(ip, subID, id);
if (ret) Utils.ConsWrite(DebugMSG_Type.DEV, "//// RadioID:" + id + " connected to TM \\\\");
else
{
Utils.ConsWrite(DebugMSG_Type.DEV, "//// RadioID:" + id + " FAILED to connected to TM \\\\");
}
}
catch (Exception ex)
{
Utils.ConsWrite(DebugMSG_Type.DEV, "Error connecting TM " + ex.ToString());
}
return ret;
}
private bool ConnectRRS(uint ip, byte subID, uint id)
{
bool ret = false;
try
{
ret = gw.connectRRS(ip, subID);
if (ret) Utils.ConsWrite(DebugMSG_Type.DEV, "//// RadioID:" + id + " connected to RRS \\\\");
else
{
Utils.ConsWrite(DebugMSG_Type.DEV, "//// RadioID:" + id + " FAILED to connected to RRS \\\\");
}
}
catch (Exception ex)
{
Utils.ConsWrite(DebugMSG_Type.DEV, "Error connecting RRS " + ex.ToString());
}
return ret;
}
private bool ConnectLPI(uint ip, byte subID, uint id)
{
bool ret = false;
try
{
ret = gw.connectLPI(ip, subID);
if (ret) Utils.ConsWrite(DebugMSG_Type.DEV, "//// RadioID:" + id + " connected to LPI \\\\");
else
{
Utils.ConsWrite(DebugMSG_Type.DEV, "//// RadioID:" + id + " FAILED to connected to LPI \\\\");
}
}
catch (Exception ex)
{
Utils.ConsWrite(DebugMSG_Type.DEV, "Error connecting LPI " + ex.ToString());
}
return ret;
}
#endregion
#region RRS & LP & CC callback's
void gw_OnRRS_CS(StringBuilder value, string suid, int poll)
{
//send ARS
byte[] buf = System.Text.Encoding.ASCII.GetBytes(value.ToString());
//send to messagebus
if (buf == null) return;
string msg = value.ToString();
string[] msgarr = msg.Split('#');
uint u_suid = uint.Parse(suid);
ARSmsg arsmsg = new ARSmsg();
if (msgarr.Length > 5)
{
arsmsg.SUID = msgarr[4];
arsmsg.status = msgarr[5];
Utils.ConsWrite(DebugMSG_Type.DEV, "Sending RRS TO DB info suid:" + msgarr[4] + " status:" + msgarr[5]);
//send ARS ACK
if (gw.SendRRSack(u_suid, 0xfffe))
{
Utils.ConsWrite(DebugMSG_Type.DEV, "Sending RRS ack to:" + u_suid + " exp interval:" + 0xfffe);
}
else
{
Utils.ConsWrite(DebugMSG_Type.DEV, "FAILED to send RRS ack to:" + u_suid + " exp interval:" + 0xfffe);
}
//insert in DB
InsertARSinQueue("" + msgarr[4], msgarr[5]);
//handle SMS
//resend all SMS waiting but check id the SMS is still in the list
if(arsmsg.status == "ON")
lock (SN_Queues.waitConfSMSList.SyncRoot)
{
ArrayList temp = new ArrayList();
foreach (SMSmsg sms_msg in SN_Queues.waitConfSMSList)
{
if (sms_msg.suid == arsmsg.SUID)
{
//SN_Queues.sendSMSQueue.PostItem(msg);
//no needed to add the sms to the queue again it will be added by the SMS thread when it is not found in waitConfList
}
else
temp.Add(sms_msg);
}
SN_Queues.waitConfSMSList = temp;
}
}
else//invalid RRS
{
return;
}
//start GPS if we received ON
if (arsmsg.status == "ON")
{
if(SN_Queues.ht_SUInfo.ContainsKey(u_suid.ToString()))
PerformeARSon(u_suid.ToString());
else
Utils.ConsWrite(DebugMSG_Type.ARS, "Suid:" + u_suid + " not found in SN_Queues.ht_SUInfo");
}
}
void gw_OnLP2_CS(uint radioID, byte[] payload, uint pSize, uint pGPSstartIDX, int poll)
{
int rID = Int32.Parse(radioID.ToString());
int size = Int32.Parse(pSize.ToString());
int gpsIDX = Int32.Parse(pGPSstartIDX.ToString());
try
{
GPSconvertor gps = new GPSconvertor(rID, payload,(int) pSize, gpsIDX,poll, Hytera_GW.cfg.gatewayID);
//send GPS to DB
string[] gps_arr = gps.GPSmsg_str.Split('#');
if (gps_arr.Length > 8)
{
int _int_date = Int32.Parse(gps_arr[5]);
DateTime gps_time = GetDTFromSeconds(_int_date);
htCell_t cell = new htCell_t();
cell.location_time = gps_time;
cell.suid = gps_arr[4];
cell.lat = gps_arr[7];
cell.lng = gps_arr[8];
cell.d_lat = double.Parse(gps_arr[7]);
cell.d_lng = double.Parse(gps_arr[8]);
cell.spd = gps_arr[6];
Console.WriteLine("Time BEFORE UTC conversion:" + gps_time.ToString("yyyy:MM:dd HH:mm:ss"));
LOGS.LOG("Unit <" + cell.suid + ">" + "Time BEFORE UTC conversion:" + gps_time.ToString("yyyy:MM:dd HH:mm:ss"));
//if poll response
if (poll == 1)
{
Utils.ConsWrite(DebugMSG_Type.DEV, "Got poll location from:" + cell.suid);
try
{
lock (SN_Queues.ht_POLL_List.SyncRoot)
{
foreach (DictionaryEntry item in SN_Queues.ht_POLL_List)
{
if (((POLLmsg)item.Value).suid == cell.suid)
{
((POLLmsg)item.Value).response = cell.location_time;
((POLLmsg)item.Value).lat = cell.lat;
((POLLmsg)item.Value).lng = cell.lng;
((POLLmsg)item.Value).speed = cell.spd;
SN_Queues.DBQueueLocation.PostItem(cell);
SN_Queues.recvPOLLQueue.PostItem((POLLmsg)item.Value);
LOGS.LOG(Hytera_GW.cfg.gatewayID + cell.suid + "Poll GPS<lat:" + cell.lat + "><lng:" + cell.lng + ">");
break;
}
}
}
}
catch (Exception ex)
{
Utils.ConsWrite(DebugMSG_Type.always, "ERROR processing poll msg suid:" + cell.suid);
}
return;
}
//Utils.ConsWrite(DebugMSG_Type.DEV, "Got triggered location from" + cell.suid);
if (location_hash.ContainsKey(cell.suid))
{
if (gps_time != ((DateTime)location_hash[cell.suid]))
{
//Console.WriteLine("SUID:" + cell.suid + "GPS time != last GPS time... Adding it to DB!!!");
cell.location_time = gps_time;
SN_Queues.DBQueueLocation.PostItem(cell);
location_hash.Remove(cell.suid);
location_hash.Add(cell.suid, gps_time);
}
else
{
Utils.ConsWrite(DebugMSG_Type.GPS, "SUID:" + cell.suid + " GPS time already in DB ...time:" + gps_time);
}
}//if (location_hash.ContainsKey(cell.suid))
else
{
Utils.ConsWrite(DebugMSG_Type.GPS, "SUID:" + cell.suid + " First GPS adding it to DB!!!");
cell.location_time = gps_time;
SN_Queues.DBQueueLocation.PostItem(cell);
location_hash.Add(cell.suid, gps_time);
}
}
Utils.ConsWrite(DebugMSG_Type.DEV, "TX:" + gps.GPSmsg_str);
}
catch (Exception ex)
{
Utils.ConsWrite(DebugMSG_Type.DEV, "Erorr on recive GPS data" + ex.ToString());
}
}
#endregion//end RRS & LP & TM callback's
#region POLL
public void PollHandle()
{
Utils.ConsWrite(DebugMSG_Type.DEV, "PollHandle started:" + DateTime.Now);
while (connected)
{
try
{
//MotoTRBOcmdMsg msg = MotoTRBOGW.locationQueue.GetItem(100);
MotoTRBOcmdMsg p_msg = SN_Queues.locationQueue.GetItem(-1);//block until message is in queue
if (p_msg.m_cmd == (byte)Hyt_cmd.SEND_POLL)
{
//SendPollLocationRequest(p_msg.m_suid, reqID_lastByte);
uint u_suid = Convert.ToUInt32(p_msg.m_suid);
gw.SendGPSpoll(u_suid);
Utils.ConsWrite(DebugMSG_Type.DEV, "Poll request sent for unit:" + p_msg.m_suid);
lock (SN_Queues.ht_POLL_List.SyncRoot)
{
foreach (DictionaryEntry item in SN_Queues.ht_POLL_List)
{
if (((POLLmsg)item.Value).suid == p_msg.m_suid && ((POLLmsg)item.Value).DBid.ToString() == p_msg.m_payload)
{
((POLLmsg)item.Value).sent = DateTime.Now.ToUniversalTime();
//((POLLmsg)item.Value).requestID = reqID_lastByte;
Utils.ConsWrite(DebugMSG_Type.DEV, "Poll request found in SN_Queues.ht_POLL_List for unit:" + p_msg.m_suid);
//Utils.ConsWrite(DebugMSG_Type.DEV, "reqID_lastByte:" + reqID_lastByte);
SN_Queues.sentPOLLQueue.PostItem((POLLmsg)item.Value);
break;
}
}
}
}
Thread.Sleep(2000);//minimum interval between SMS as per MotoTRBO specs
}
catch (Exception ex)
{
Utils.ConsWrite(DebugMSG_Type.always, "Exception in OC4JconnThread:HandleConnection(): \r\n\tData=" +
ex.Data + "\r\n\tSource=" +
ex.Source + "\r\n\tStackTrace=" +
ex.StackTrace + "\r\n\tMessage=" +
ex.Message + "\r\n\tInnerException=" +
ex.InnerException);
}
} // end while (true)
}
#endregion
#region AUX
public static UInt32 ConvertIPToLong(string ipAddress)
{
System.Net.IPAddress ip;
if (System.Net.IPAddress.TryParse(ipAddress, out ip))
{
byte[] bytes = ip.GetAddressBytes();
return (UInt32)(((UInt32)bytes[0] << 24) | (bytes[1] << 16) | (bytes[2] << 8) | bytes[3]);
}
else
return 0;
}
public Int32 ConvertGMTToLocal(Int32 param)
{
DateTime time = this.GetDTFromSeconds(param);
DateTime GMTTime = time.ToUniversalTime();
TimeSpan span = time - GMTTime;
long nOfSeconds = (long)span.TotalSeconds;
return (Int32)(nOfSeconds + param);
}
public System.DateTime GetDTFromSeconds(Int32 param)
{
DateTime dateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0);
dateTime = dateTime.AddSeconds((double)param);
return dateTime;
}
bool InsertARSinQueue(string p_radioID, string p_message)
{
try
{
ArsMSG ars = new ArsMSG();
ars.imei = p_radioID;
ars.msg = p_message;
SN_Queues.arsMsgQueue.PostItem(ars);
return true;
}
catch (Exception e)
{
Utils.ConsWrite(DebugMSG_Type.always, "Error inserting ARS in Queue");
Utils.ConsWrite(DebugMSG_Type.always, e.Message);
return false;
}
}
private void PerformeARSon(string SUID)
{
//add ars info to HT
((SUinfo)SN_Queues.ht_SUInfo[SUID]).arsCheckTime = DateTime.UtcNow;
((SUinfo)SN_Queues.ht_SUInfo[SUID]).ARSon = true;
//get reporting interval
int repInter = ((SUinfo)SN_Queues.ht_SUInfo[SUID]).repInterval;
Utils.ConsWrite(DebugMSG_Type.GPS, "Interval for SUID:" + SUID + " =" + repInter);
if (repInter != 0)
{
try
{
StartGPS(uint.Parse(SUID), repInter);
}
catch (Exception ex)
{
Utils.ConsWrite(DebugMSG_Type.always, "Erorr on recive GPS data" + ex.ToString());
}
}
else
{
Utils.ConsWrite(DebugMSG_Type.GPS, "SUID:" + SUID + " interval=0 , no GPS reporting needed.");
}
}
private void StartGPS(uint suid, int repInterval)
{
string str_suid = suid.ToString();
string tempGps1 = (/*repInterval*/"30").PadLeft(8, '0');
gw.SendGPSstart(suid, tempGps1);
Utils.ConsWrite(DebugMSG_Type.GPS, "GPS start sent for:" + suid + " interval:" + tempGps1);
}
#endregion
}
}