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 /// /// constructor /// /// hyera radio IP /// subnet ID /// base station IMEI 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, "<<<<<<<<<<<>>>>>>>>>"); 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"); 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 } }