515 lines
19 KiB
C#
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
|
|
}
|
|
}
|