using System; using System.Collections.Generic; using System.Text; using System.Threading; using System.Net.Sockets; using System.Net; using MySql.Data.MySqlClient; using System.Collections; using SafeNetLib; using System.Diagnostics; namespace ConnectPlus_SOC { class WatcherServerThread { private TcpClient client; private IPEndPoint serverEndPoint; private Thread listenThread; private Thread intervalThread; private Thread checkThread; private Thread subscribThread; private System.Threading.Timer tResendSub; private System.Threading.Timer tResendGPS; public static DateTime lastPingTime = DateTime.Now; private NetworkStream clientStream; byte[] message; private string p_ctrIP; private int port; string connString; string gwID; string report; int totalUsers; public DateTime dt_lastSUB; public static bool connDown = false; private System.Timers.Timer checkForTime; private int timerCount = 0; public WatcherServerThread(string _ctrlIP, int port, string p_connString, string p_gwID, string p_report) { Utils.ConsWrite(DebugMSG_Type.CTRL, "WatcherServerThread Constructor"); message = new byte[128]; p_ctrIP = _ctrlIP; this.port = port; totalUsers = 0; connString = p_connString; gwID = p_gwID; report = p_report; checkForTime = new System.Timers.Timer(180 * 60 * 1000); checkForTime.Elapsed += delegate(object sender, System.Timers.ElapsedEventArgs e) { Utils.WriteLine("Three hours elapsed, must check subscription again. [" + (++timerCount) + "]", ConsoleColor.Cyan ); SubscribeALL(1234); }; checkForTime.Enabled = true; } public void Stop() { if (clientStream != null) { clientStream.Close(); } if (listenThread.IsAlive) { listenThread.Abort(); } if (intervalThread.IsAlive) { intervalThread.Abort(); } if (checkForTime != null) checkForTime.Stop(); } public void Start() { try { IPAddress ctrIP = null; if (!IPAddress.TryParse(ConnectPlus_GW.cfg.ctrlIP, out ctrIP)) { ctrIP = Dns.GetHostAddresses(ConnectPlus_GW.cfg.ctrlIP)[0]; Utils.ConsWrite(DebugMSG_Type.always, "Host name : " + ConnectPlus_GW.cfg.ctrlIP + " IP:" + ctrIP.ToString()); } if (ctrIP == null) { Utils.ConsWrite(DebugMSG_Type.always, "Location Thread invalid host address for: " + ConnectPlus_GW.cfg.ctrlIP); } client = new TcpClient(); serverEndPoint = new IPEndPoint(ctrIP, port); //client.Connect(serverEndPoint); client.Connect(ConnectPlus_GW.cfg.ctrlIP, port); Utils.ConsWrite(DebugMSG_Type.CTRL, "WatcherServerThread connected on " + ConnectPlus_GW.cfg.ctrlIP + ":" + port); clientStream = client.GetStream(); if (clientStream != null) { //set read timeout to 35 seconds, according to Motorola Connect Plus PN_Watcher specifications clientStream.ReadTimeout = 35000; connDown = false; } else { connDown = true; Utils.ConsWrite(DebugMSG_Type.always, "WatcherServerThread -> clientStream==null"); } } catch (Exception ex) { //Utils.ConsWrite(DebugMSG_Type.always, "Erorr WatcherServerThread connecting to " + ConnectPlus_GW.cfg.ctrlIP + " \n" + ex.ToString()); Utils.WriteLine("Error connecting to the controller " + ConnectPlus_GW.cfg.ctrlIP + Environment.NewLine + ex.ToString(), ConsoleColor.Red); connDown = true; } listenThread = new Thread(new ThreadStart(HandleClientComm)); listenThread.IsBackground = true; listenThread.Start(); Utils.ConsWrite(DebugMSG_Type.CTRL, "============ WatcherServerThread Listenning ============"); intervalThread = new Thread(new ThreadStart(HandleInterval)); intervalThread.IsBackground = true; intervalThread.Start(); checkThread = new Thread(new ThreadStart(CheckLastPing)); checkThread.IsBackground = true; checkThread.Start(); subscribThread = new Thread(new ParameterizedThreadStart(SubscribeALLinDB_del)); subscribThread.IsBackground = true; tResendSub = new System.Threading.Timer(ResendSUB, null, new TimeSpan(1, 0, 0), new TimeSpan(1, 0, 0)); tResendGPS = new System.Threading.Timer(ResendGPS, null, new TimeSpan(0, 1, 0), new TimeSpan(0, 1, 0)); new Thread(delegate() { Thread.Sleep(30000); while (true) { Console.ForegroundColor = ConsoleColor.Red; Console.Write("WRITING FAKE SUBSCRIBE MESSAGE"); Console.ForegroundColor = ConsoleColor.Gray; byte[] bytesToSend = new byte[72] {0x04, 0x01, 0x00, 0x03, 0x01, 0x02, 0x0a, 0x08, 0x31, 0x00, 0x30, 0x00, 0x38, 0x00, 0x39, 0x00, 0x02, 0x02, 0x32, 0x00, 0x0e, 0x02, 0x32, 0x00, 0x04, 0x01, 0x00, 0x03, 0x01, 0x02, 0x0a, 0x08, 0x31, 0x00, 0x30, 0x00, 0x38, 0x00, 0x36, 0x00, 0x02, 0x02, 0x32, 0x00, 0x0e, 0x02, 0x32, 0x00, 0x04, 0x01, 0x00, 0x03, 0x01, 0x02, 0x0a, 0x08, 0x31, 0x00, 0x30, 0x00, 0x38, 0x00, 0x34, 0x00, 0x02, 0x02, 0x32, 0x00, 0x0e, 0x02, 0x32, 0x00}; Decode(bytesToSend, 72); Thread.Sleep(15000); } });//.Start(); } public void RestartTCP() { Utils.ConsWrite(DebugMSG_Type.always, "\n\n\n\n RESTART TCP \n\n\n\n"); try { IPAddress ctrIP = null; if (!IPAddress.TryParse(ConnectPlus_GW.cfg.ctrlIP, out ctrIP)) { ctrIP = Dns.GetHostAddresses(ConnectPlus_GW.cfg.ctrlIP)[0]; Utils.ConsWrite(DebugMSG_Type.always, "Host name : " + ConnectPlus_GW.cfg.ctrlIP + " IP:" + ctrIP.ToString()); } if (ctrIP == null) { Utils.ConsWrite(DebugMSG_Type.always, "Reconnecting to controlle invalid host address for: " + ConnectPlus_GW.cfg.ctrlIP); } //add gateway status!! GWstatus gws = new GWstatus(); gws.gw_id = gwID; gws.status = 0; SN_Queues.gwstatusQueue.PostItem(gws); LOGS.LOG("Reconnecting to controller ip:" + p_ctrIP + " port:" + port.ToString()); Utils.ConsWrite(DebugMSG_Type.CTRL, "Reconnecting to controller ip:"+p_ctrIP+" port:"+ port.ToString()); if (client != null) { if (client.Connected) client.Close(); client = null; } if (clientStream != null) { try { clientStream.Close(); clientStream.Dispose(); } catch (Exception ex) { Console.ForegroundColor = ConsoleColor.Red; Utils.ConsWrite(DebugMSG_Type.always, "ClientStream Exception ex: " + ex.ToString()); Console.ForegroundColor = ConsoleColor.Gray; } } client = new TcpClient(); serverEndPoint = new IPEndPoint(ctrIP, port); //client.Connect(serverEndPoint); client.Connect(ConnectPlus_GW.cfg.ctrlIP, port); Utils.ConsWrite(DebugMSG_Type.CTRL, "WatcherServerThread connected on " + port); LOGS.LOG("WatcherServerThread connected on " + port); clientStream = client.GetStream(); if (clientStream != null) { //set read timeout to 35 seconds, according to Motorola Connect Plus PN_Watcher specifications clientStream.ReadTimeout = 35 * 1000; //resend subscribe all Thread.Sleep(100); SubscribeALL(1234); //SubscribeALLinDB(1234); dt_lastSUB = DateTime.UtcNow; connDown = false; } else { connDown = true; Thread.Sleep(500); Utils.ConsWrite(DebugMSG_Type.always, "WatcherServerThread -> clientStream==null"); } } catch (Exception ex) { Utils.ConsWrite(DebugMSG_Type.always, "Restart FAILED!!!!\n " + ex.ToString()); } } //IF THE UNIT IS NOT IN ht_SUInfo dont process the message private void HandleClientComm() { Thread.Sleep(500); while (ConnectPlus_GW.isRunning) { try { // wait until the client Stream is ready if (clientStream == null || connDown) { RestartTCP(); continue; } clientStream.ReadTimeout = 30 * 1000; //Console.WriteLine("Waiting for stuff..."); //read LEN first byte[] msgLen = new byte[2]; int result = clientStream.Read(msgLen, 0, msgLen.Length); int msgLength = msgLen[0] * 265 + msgLen[1]; message = new byte[msgLength]; result = clientStream.Read(message, 0, msgLength); /* Console.ForegroundColor = ConsoleColor.Cyan; Utils.printBytesArray(message); Console.ForegroundColor = ConsoleColor.Gray; */ //Console.Write(DateTime.Now + "-> "); //if we got PING send Pong if (message[0] == 0xff) { LOGS.LOG("PING received"); lastPingTime = DateTime.Now; ConnectPlus_GW.lastActivityTime = DateTime.Now; //Print(message, result, true, "PING"); Utils.ConsWrite(DebugMSG_Type.always, "########### PING received ##########################"); //add to GW status queue for DB entry GWstatus gws = new GWstatus(); gws.gw_id = gwID; gws.status = 1; gws.message = "PING RECEIVED [" + String.Format("{0:HH:mm:ss}", lastPingTime) + "]"; SN_Queues.gwstatusQueue.PostItem(gws); Thread.Sleep(500); PONG(); } else { //Print(message, result, true); List responses = Decode(message, result); foreach (NotifyRespons resp in responses) { if (resp.Error) { Utils.ConsWrite(DebugMSG_Type.DEV, "Response error suid:" + resp.SUID); } if (resp.DialogID != 1234) { Utils.ConsWrite(DebugMSG_Type.DEV, "Got one time resp from suid:" + resp.SUID); } //test if unit is in DB if (SN_Queues.ht_SUInfo != null) { if (!SN_Queues.ht_SUInfo.ContainsKey(resp.SUID)) { LOGS.LOG("Unit :" + resp.SUID + " NOT assigned to GWID:" + gwID); Utils.WriteLine("Unit :" + resp.SUID + " NOT assigned to GWID:" + gwID, ConsoleColor.DarkGray); //Utils.ConsWrite(DebugMSG_Type.ARS, "Unit :" + resp.SUID + " NOT assigned to GWID:" + gwID); continue; } } totalUsers++; if (resp.Active) { //Utils.ConsWrite(DebugMSG_Type.CTRL, "SU " + resp.SUID + " ON ### Total users: " + totalUsers); int repInter = Convert.ToInt32(report); //get reporting interval repInter = ((SUinfo)SN_Queues.ht_SUInfo[resp.SUID]).repInterval; /* Utils.ConsWrite(DebugMSG_Type.GPS, "Interval for SUID:" + resp.SUID + " =" + repInter); if (resp.DialogID != 1234) Utils.ConsWrite(DebugMSG_Type.DEV, "new Interval for SUID:" + resp.SUID + " =" + repInter); */ //create location message!! MotoTRBOcmdMsg msg = new MotoTRBOcmdMsg(); msg.m_cmd = (byte)MotoTRBOcmd.SET_REPORT_INTERVAL; msg.m_suid = resp.SUID; msg.m_payload = repInter.ToString(); if (repInter != 0) { Utils.WriteLine(String.Format("Unit {0} has interval set to {1} sec", resp.SUID, repInter), ConsoleColor.Yellow); SN_Queues.locationQueue.PostItem(msg); //Utils.ConsWrite(DebugMSG_Type.DEV, "Interval for SUID:" + resp.SUID + " =" + repInter); } else { Utils.WriteLine(String.Format("Unit {0} has no interval set", resp.SUID), ConsoleColor.Yellow); //Utils.ConsWrite(DebugMSG_Type.GPS, "SUID:" + resp.SUID + " interval=0 , no GPS reporting needed."); } //send sms reg msq SendSMSThread.Send_Reg_msg(resp.SUID + ".1"); } //poll ars //LOGS.LOG("Received ARS " + (resp.Active ? "ON" : "OFF") + " from one time request. unit:" + resp.SUID); //if previous ars state was OFF mark unit as ON if (((SUinfo)SN_Queues.ht_SUInfo[resp.SUID]).ARSon != resp.Active) { InsertARSinQueue(resp.SUID, resp.Active ? "ON" : "OFF"); LOGS.LOG("Adding ARS " + (resp.Active ? "ON" : "OFF") + " prev state was OFF:" + resp.SUID); } Utils.ConsWrite(DebugMSG_Type.CTRL, "»»» ARS " + (resp.Active ? "ON" : "OFF") + " for " + resp.SUID); //add ars info to HT ((SUinfo)SN_Queues.ht_SUInfo[resp.SUID]).arsCheckTime = DateTime.UtcNow; ((SUinfo)SN_Queues.ht_SUInfo[resp.SUID]).GPSlasttime = DateTime.UtcNow; ((SUinfo)SN_Queues.ht_SUInfo[resp.SUID]).ARSon = resp.Active; } } } catch (System.IO.IOException ex) { Utils.ConsWrite(DebugMSG_Type.always, "I/O exception!!"); Utils.ConsWrite(DebugMSG_Type.always, ex.ToString()); Thread.Sleep(500); connDown = true; } catch (Exception ex) { Utils.ConsWrite(DebugMSG_Type.always, ex.ToString()); int coun = 0; while ((coun++) < 60 && ConnectPlus_GW.isRunning) { Thread.Sleep(500); } connDown = true; } int tcpResetCount = 0; while (connDown == true && ConnectPlus_GW.isRunning) { if ((tcpResetCount++) % 120 == 0) { Utils.ConsWrite(DebugMSG_Type.always, "\n\n\n\n connDown== true Restarting TCP \n\n\n\n"); RestartTCP(); tcpResetCount = 0; } else if (tcpResetCount % 20 == 0) Utils.WriteLine("WatchServer - TCP Connection is down", ConsoleColor.Red); Thread.Sleep(500); } //Thread.Sleep(100); } } /// /// Event Handler triggered each time a new radio is added in the system or when the reporting interval /// had changed /// private void HandleInterval() { // wait until the units are loaded and then clear the new interval queue // because the first time I do not need to send the SubscribeOneTime while (!ConnectPlus_GW.unitsLoaded) { Thread.Sleep(500); } SN_Queues.NewIntervalQueue.Clear(); while (true) { string suid = ""; int dialogID = -1; try { //test if we have a change in reporting interval SUinfo info = SN_Queues.NewIntervalQueue.GetItem(100); if (info != null) { Utils.ConsWrite(DebugMSG_Type.always, "Sending SubscribeOneTime to:" + info.suid); dialogID = 0x1111; //SubscribeALL(dialogID); SubscribeOneTime(dialogID, info.suid); // send triggered location request for this unit if (info.repInterval > 0) { //create location message!! MotoTRBOcmdMsg msg = new MotoTRBOcmdMsg(); msg.m_cmd = (byte)MotoTRBOcmd.SET_REPORT_INTERVAL; msg.m_suid = info.suid; msg.m_payload = info.repInterval.ToString(); SN_Queues.locationQueue.PostItem(msg); } } } catch (Exception ex) { Utils.ConsWrite(DebugMSG_Type.always, "Error HandleInterval for suid:" + suid + " dialogID:" + dialogID); } } } private void CheckLastPing() { lastPingTime = DateTime.Now; String processName = Process.GetCurrentProcess().ProcessName; Process[] pname = Process.GetProcessesByName(processName); while (pname.Length > 0) { Thread.Sleep(5000); Utils.ConsWrite(DebugMSG_Type.CTRL, "Curent time:" + DateTime.Now.ToString("HH:mm:ss") + " LastActivityTime:" + ConnectPlus_GW.lastActivityTime.ToString("HH:mm:ss") + "[Units: " + SN_Queues.ht_SUInfo.Count + "]"); //test if we have a change in reporting interval TimeSpan ts = DateTime.Now.Subtract(ConnectPlus_GW.lastActivityTime); /* if (ts.TotalSeconds > 600) { Console.ForegroundColor = ConsoleColor.Red; Utils.ConsWrite(DebugMSG_Type.CTRL, "Last ping was >30 sec forcing TCP restart."); Console.ForegroundColor = ConsoleColor.Gray; LOGS.LOG("<<>>Curent time:" + DateTime.Now.ToString("HH:mm:ss") + " LastPing:" + ConnectPlus_GW.lastActivityTime.ToString("HH:mm:ss")); //RestartTCP(); } */ // check if the process is still running pname = Process.GetProcessesByName(processName); } } private void ResendSUB(Object state) { // This method is executed by a thread pool thread try { if (DateTime.UtcNow.DayOfYear > dt_lastSUB.DayOfYear) { if (DateTime.UtcNow.Hour > 5) { SubscribeALL(1234); //SubscribeALLinDB(1234); LOGS.LOG("<<>>Curent time:" + DateTime.UtcNow.ToString() + " LastPing:" + dt_lastSUB.ToString()); dt_lastSUB = DateTime.UtcNow; Utils.ConsWrite(DebugMSG_Type.CTRL, "Resending SubscribeALL."); } } } catch (Exception ex) { Utils.ConsWrite(DebugMSG_Type.always, "Error on ResendSUB:" + ex.ToString()); } } int countGPSrefresh = 0; private void ResendGPS(Object state) { // This method is executed by a thread pool thread try { countGPSrefresh++; if (countGPSrefresh > 1024) countGPSrefresh = 0; Utils.ConsWrite(DebugMSG_Type.CTRL, "ResendGPS check starded."); Hashtable temp = (Hashtable)SN_Queues.ht_SUInfo.Clone(); foreach (DictionaryEntry de in temp) { SUinfo info = (SUinfo)de.Value; DateTime lastARStime = info.arsCheckTime; if (info.ARSon == false) continue; /* TimeSpan difference = DateTime.UtcNow - info.GPSlasttime; //check if more then "ConnectPlus_GW.cfg.GPS_refresh" time has passed since last ARS //if ((DateTime.UtcNow.Subtract(new TimeSpan(ConnectPlus_GW.cfg.GPS_refresh, 0, 0))).Gre > lastARStime) if (difference.Hours >= ConnectPlus_GW.cfg.GPS_refresh) { Utils.ConsWrite(DebugMSG_Type.CTRL, "Sending SubscribeOneTime to:" + info.suid); LOGS.LOG("<<>>Curent time:" + DateTime.UtcNow.ToString() + " ||||| Last GPS refresh:" + info.GPSlasttime.ToString()); int dialogID = 0x1111; //SubscribeALL(dialogID); SubscribeOneTime(dialogID, info.suid); } else { //Utils.ConsWrite(DebugMSG_Type.CTRL, "Unit:" + info.suid + " GPS not expired yet!"); if((countGPSrefresh % 30)==0) LOGS.LOG("<<>>Curent time:" + DateTime.UtcNow.ToString() + " ||||| Last GPS refresh:" + info.arsCheckTime.ToString()); } */ } } catch (Exception ex) { Utils.ConsWrite(DebugMSG_Type.always, "Error on ResendSUB:" + ex.ToString()); } } public delegate void MessageRecv(NotifyRespons resp); public event MessageRecv OnMessageRecv; public enum SubscribeTag { DeviceID = 0xA, IPv4Address = 0xD, PresenceState = 0xE, Expires = 0x01, Event = 0x02, SubscriptionState = 0x03, TCPPortNumber = 0x06 }; private List Decode(byte[] data, int recv) { List notifyResponses = new List(); //Console.WriteLine("Got notify message"); /* NotifyRespons nResp = new NotifyRespons(); nResp.Active = false; nResp.DialogID = 0; nResp.Error = true; nResp.SUID = "0"; * */ //int msgLength = data[0] * 265 + data[1]; //length doesent match... return error //if (msgLength != recv-2) { Console.WriteLine("Received length({0}) doesent match with message length({1})..returning errror!!!",recv-2,msgLength); return nResp; } //test if we got at least msgLen, msgID,dialogID,subscription state if (recv < 6) { Utils.ConsWrite(DebugMSG_Type.always, "Incorect message.Message does not have the minimum size of 6bytes. actual length=" + recv); Utils.ConsWrite(DebugMSG_Type.always, "!!!!!!!!!!!!subscription state TLV missing!!!!!!!!!!!"); return notifyResponses; } int pos = 0; NotifyRespons response = null; bool found0x2 = false, found0x3 = false, found0xA = false, found0xE = false; while (pos <= data.Length) { // add message if finished was reached if (pos == data.Length) { notifyResponses.Add(response); break; } // complet notify response if(found0x2 && found0x3 && found0xA && found0xE) { found0x2 = false; found0x3 = false; found0xA = false; found0xE = false; notifyResponses.Add(response); } // get messageID and dialogID only if not waiting for one of this // following Tag types if (found0x2 == false && found0x3 == false && found0xA == false && found0xE == false) { // get messageID int messageID = data[pos++]; if (messageID != 4) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("Incorect msgID:{0}. MsgID must be 4(reliable notify message)", messageID); Console.ForegroundColor = ConsoleColor.Gray; return notifyResponses; } else { // found a valid notify response response = new NotifyRespons(); response.Active = false; response.DialogID = 0; response.Error = true; response.SUID = "0"; int dialogID = data[pos++] * 256 + data[pos++]; response.DialogID = dialogID; } } int tag = data[pos++]; //Console.WriteLine("TAG is " + tag); // break if last byte is a tag if (pos >= data.Length) break; int length = data[pos++]; //Console.WriteLine("LENGTH is " + length); switch (tag) { case (byte)SubscribeTag.Event: { byte[] value_arr = new byte[length]; Array.Copy(data, pos, value_arr, 0, length); string event_string = Encoding.Unicode.GetString(value_arr); // jump over value field pos = pos + length; found0x2 = true; //Console.WriteLine("Found Event"); break; } case (byte)SubscribeTag.SubscriptionState: { byte value = data[pos++]; switch (value) { case (byte)SubscriptionState.Accepted: //Console.WriteLine("Subscription State:" + SubscriptionState.Accepted + " value:" + value); break; case (byte)SubscriptionState.RefreshAccepted: //Console.WriteLine("Subscription State:" + SubscriptionState.RefreshAccepted + " value:" + value); break; case (byte)SubscriptionState.Rejected: //Console.WriteLine("Subscription State:" + SubscriptionState.Rejected + " value:" + value); break; case (byte)SubscriptionState.Terminated: //Console.WriteLine("Subscription State:" + SubscriptionState.Terminated + " value:" + value); break; default: Utils.ConsWrite(DebugMSG_Type.CTRL, "Unknown subscription state:" + value); break; } found0x3 = true; //Console.WriteLine("Found SubscriptionState"); break; } case (byte)SubscribeTag.DeviceID: { byte[] value_arr = new byte[length]; Array.Copy(data, pos, value_arr, 0, length); string suid = Encoding.Unicode.GetString(value_arr); response.SUID = suid; //Console.WriteLine("Entity(SUID):" + suid); //jump to next tlv pos = pos + length; response.Error = false; found0xA = true; //Console.WriteLine("Found DeviceID "); break; } case (byte)SubscribeTag.PresenceState: { byte[] value_arr = new byte[length]; Array.Copy(data, pos, value_arr, 0, length); string presence = Encoding.Unicode.GetString(value_arr); switch (presence) { case "0": //Console.WriteLine("Presence state TLV: unknown value:" + presence); break; case "1": response.Active = true; //Console.WriteLine("Presence state TLV: present value:" + presence); break; case "2": response.Active = false; //Console.WriteLine("Presence state TLV: absent value:" + presence); break; } //jump to next tlv pos = pos + length; found0xE = true; //Console.WriteLine("Found PresenceState"); break; } } } return notifyResponses; } public Boolean Send(byte[] data, int len) { if (clientStream != null) { clientStream.Write(data, 0, len); clientStream.Flush(); return true; } return false; } #region Subscribe messages and PONG message /// /// Send the subcribe message to the controler /// /// unique dialog ID /// ID of radio subscriber that is being watched /// time to live of the subscription public void Subscribe(int dialogID, int ID, byte expiresTime) { Utils.ConsWrite(DebugMSG_Type.DEV, "DialogID:" + dialogID); byte[] tempID = convertInt2ByteLE(ID); byte[] msg = new byte[18 + tempID.Length]; //length msg[0] = 0x00; msg[1] = Convert.ToByte(0x10 + tempID.Length); // message ID msg[2] = 0x03; // Dialog ID byte[] tempDialogID = BitConverter.GetBytes(dialogID); msg[3] = tempDialogID[1]; msg[4] = tempDialogID[0]; //Message BODY //The Expires TLV Field msg[5] = 0x01; msg[6] = 0x01; msg[7] = expiresTime; //The TCPPort TLV Field msg[8] = 0x06; msg[9] = 0x02; byte[] tempPort = BitConverter.GetBytes(0x3344); msg[10] = tempPort[1]; msg[11] = tempPort[0]; //The Entities TLV Field msg[12] = 0x0a; msg[13] = Convert.ToByte(tempID.Length); // ID for (int i = 0; i < tempID.Length; i++) { msg[14 + i] = tempID[i]; } //The Events TLV Field msg[14 + tempID.Length] = 0x02; msg[14 + tempID.Length + 1] = 0x02; msg[14 + tempID.Length + 2] = 0x31; msg[14 + tempID.Length + 3] = 0x00; Send(msg, msg.Length); //Console.WriteLine("-----------Sent Subscribe to the controller-----"); //Print(msg, msg.Length, false); } public void SubscribeALL(int dialogID) { byte[] msg = new byte[23]; //length msg[0] = 0x00; msg[1] = 0x15; // message ID msg[2] = 0x03; // Dialog ID byte[] tempDialogID = BitConverter.GetBytes(dialogID); msg[3] = tempDialogID[1]; msg[4] = tempDialogID[0]; //Message BODY //The Expires TLV Field (94608000 sec ~= 3 years) msg[5] = 0x01; msg[6] = 0x04; msg[7] = 0xff; msg[8] = 0xff; msg[9] = 0xff; msg[10] = 0xff; //The Entities TLV Field msg[11] = 0x0a; msg[12] = 0x02; // ID:all msg[13] = 0x2A; msg[14] = 0x00; //The Events TLV Field msg[15] = 0x02; msg[16] = 0x06; msg[17] = (byte)'1'; msg[18] = 0x00; msg[19] = (byte)','; msg[20] = 0x00; msg[21] = (byte)'2'; msg[22] = 0x00; if (Send(msg, msg.Length)) Utils.WriteLine("Sent Subscribe ALL to the controller", ConsoleColor.Gray); else Utils.WriteLine("Failed to send Subscribe ALL to the controller", ConsoleColor.Gray); //Print(msg, msg.Length, false); } /// /// Query the controller for the status of a particular field unit /// /// The unique identifier for this request /// The field radio Id for which the status is required public void SubscribeOneTime(int dialogID, string suid)// TLV expire =0 { //Utils.ConsWrite(DebugMSG_Type.DEV, "DialogID:" + dialogID); char[] suidARR = suid.ToCharArray(); byte[] msg = new byte[18 + suidARR.Length*2]; //length msg[0] = 0x00; msg[1] = (byte)(16 + suidARR.Length * 2); // message ID msg[2] = 0x03; // Dialog ID byte[] tempDialogID = BitConverter.GetBytes(dialogID); msg[3] = tempDialogID[1]; msg[4] = tempDialogID[0]; //Message BODY //The Expires TLV Field msg[5] = 0x01; msg[6] = 0x01; msg[7] = 0x00;//one time //The Entities TLV Field msg[8] = 0x0a; msg[9] = (byte)(suidARR.Length*2); for (int i = 0; i < suidARR.Length; i++) { byte b = (byte)suidARR[i]; //Console.WriteLine(b); msg[10 + i * 2] = b; msg[10 + i * 2 + 1] = 0x00; } //The Events TLV Field msg[10 + suidARR.Length * 2] = 0x02; msg[10 + suidARR.Length * 2 + 1] = 0x06; msg[10 + suidARR.Length * 2 + 2] = (byte)'1'; msg[10 + suidARR.Length * 2 + 3] = 0x00; msg[10 + suidARR.Length * 2 + 4] = (byte)','; msg[10 + suidARR.Length * 2 + 5] = 0x00; msg[10 + suidARR.Length * 2 + 6] = (byte)'2'; msg[10 + suidARR.Length * 2 + 7] = 0x00; Send(msg, msg.Length); //Console.WriteLine("-----------Sent Subscribe ALL to the controller-----"); //Print(msg, msg.Length, false); } /// /// Reliable Subscribe message for all the field radios from the controller /// public void SubscribeALL() { byte[] msg = new byte[20]; //length msg[0] = 0x00; msg[1] = 0x12; // message ID msg[2] = 0x03; // Dialog ID msg[3] = 0x33; msg[4] = 0x44; //Message BODY //The Expires TLV Field msg[5] = 0x01; msg[6] = 0x01; msg[7] = 0xff; //The TCPPort TLV Field msg[8] = 0x06; msg[9] = 0x02; byte[] temp = BitConverter.GetBytes(0x3344); msg[10] = temp[1]; msg[11] = temp[0]; //The Entities TLV Field msg[12] = 0x0a; msg[13] = 0x02; // ID:all msg[14] = 0x2a; msg[15] = 0x00; //The Events TLV Field msg[16] = 0x02; msg[17] = 0x02; msg[18] = 0x2a; msg[19] = 0x00; if (Send(msg, msg.Length)) Utils.WriteLine("Sent Subscribe ALL to the controller", ConsoleColor.Gray); else Utils.WriteLine("Failed to send Subscribe ALL to the controller", ConsoleColor.Gray); //Print(msg, msg.Length, false); } public void SubscribeList(int dialogID, List suids)// TLV expire =0 { //Utils.ConsWrite(DebugMSG_Type.DEV, "DialogID:" + dialogID); //create arr string: suid1,suid2,....,suidn string strSUIDS=""; for (int i = 0; i < suids.Count; i++) { if (i != (suids.Count - 1)) { strSUIDS += suids[i] + ","; } else { strSUIDS += suids[i]; } } Utils.ConsWrite(DebugMSG_Type.ARS, "suids string:" + strSUIDS); char[] suidARR = strSUIDS.ToCharArray(); byte[] msg = new byte[15 + suidARR.Length * 2]; //length msg[0] = 0x00; msg[1] = (byte)(13 + suidARR.Length * 2); // message ID msg[2] = 0x03; // Dialog ID byte[] tempDialogID = BitConverter.GetBytes(dialogID); msg[3] = tempDialogID[1]; msg[4] = tempDialogID[0]; //Message BODY //The Expires TLV Field //msg[5] = 0x01; //msg[6] = 0x01; //msg[7] = 0x00;//one time //The Entities TLV Field msg[5] = 0x0a; msg[6] = (byte)(suidARR.Length * 2); for (int i = 0; i < suidARR.Length; i++) { byte b = (byte)suidARR[i]; //Console.WriteLine(b); msg[7 + i * 2] = b; msg[7 + i * 2 + 1] = 0x00; } //The Events TLV Field msg[7 + suidARR.Length * 2] = 0x02; msg[7 + suidARR.Length * 2 + 1] = 0x06; msg[7 + suidARR.Length * 2 + 2] = (byte)'1'; msg[7 + suidARR.Length * 2 + 3] = 0x00; msg[7 + suidARR.Length * 2 + 4] = (byte)','; msg[7 + suidARR.Length * 2 + 5] = 0x00; msg[7 + suidARR.Length * 2 + 6] = (byte)'2'; msg[7 + suidARR.Length * 2 + 7] = 0x00; Send(msg, msg.Length); //Console.WriteLine("-----------Sent Subscribe ALL to the controller-----"); //Print(msg, msg.Length, false); } public void SubscribeALLinDB(int dialogID) { //start subscription thread subscribThread.Start(dialogID); } private void SubscribeALLinDB_del(object dialogID) { //wait for su info to be retrived from DB while(SN_Queues.ht_SUInfo.Count < 1) { Utils.ConsWrite(DebugMSG_Type.ARS, "SubscribeALLinDB waiting for SU info from DB sleeping 500ms " + "<------> or no unit present in DB for gwid:" + gwID); Thread.Sleep(500); } List suids = null; if (SN_Queues.ht_SUInfo != null) { suids = new List(); foreach (DictionaryEntry de in SN_Queues.ht_SUInfo) { suids.Add(((SUinfo)de.Value).suid); } } if(suids != null) SubscribeList((int)dialogID, suids); } //send PONG back to controller public void PONG() { byte[] msg = new byte[12]; //length msg[0] = 0x00; msg[1] = 0x0a; // message ID msg[2] = 0xff; // body length msg[3] = 0x08; //PONG -utf16 LE string //P msg[4] = 0x50; msg[5] = 0x00; //O msg[6] = 0x4f; msg[7] = 0x00; //N msg[8] = 0x4e; msg[9] = 0x00; //G msg[10] = 0x47; msg[11] = 0x00; Send(msg, msg.Length); Utils.ConsWrite(DebugMSG_Type.always,"-----------Sent PONG to the controller-----"); //Print(msg, msg.Length, false, "PONG:"); } 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; } } #endregion #region AUX methods private void Print(byte[] data, int length, bool inOut) { //Console.Clear(); Console.WriteLine("--------------------------------------------------------------------------- " + length); Console.Write("Data (" + ((inOut) ? "RECEIVED" : "SENT") + "): "); for (int i = 0; i < length; i++) Console.Write(" 0x" + data[i].ToString("X2")); Console.WriteLine(""); Console.WriteLine("--------------------------------------------------------------------------- "); } private static byte[] convertInt2ByteLE(int id) { Byte[] retBytes = Encoding.Unicode.GetBytes(id.ToString()); return retBytes; } private int ConvertByteArr2Int(byte[] arr) { byte[] worker = new byte[4]; arr.CopyTo(worker, 0); return BitConverter.ToInt32(worker, 0); } #endregion } public class NotifyRespons { private string suid; public string SUID { get { return suid; } set { suid = value; } } private bool active; public bool Active { get { return active; } set { active = value; } } private int dialogID; public int DialogID { get { return dialogID; } set { dialogID = value; } } private bool error; public bool Error { get { return error; } set { error = value; } } } public enum SubscriptionState { Rejected = 1, Accepted = 2, Terminated = 3, RefreshAccepted = 4 } }