using System; using System.Collections.Generic; using System.Text; using System.Net; using System.Net.Sockets; using System.Threading; using SafeMobileLib; namespace CPlus_GW { class SendSMSThread { private byte WAIT_SMS_SEC = 5; // max no of seconds to wait for SMS ack int remoteSMSport; private UdpMulticast udpMulticastBusConnection = null; public SendSMSThread(int p_remoteSMSport) { remoteSMSport = p_remoteSMSport; } public void HandleConnection() { try { udpMulticastBusConnection = new UdpMulticast(Program.cfg.multi_IP, Program.cfg.multi_port); udpMulticastBusConnection.OnNewDataRecv += new UdpMulticast.newData4Send(udpMulticastBusConnection_OnNewDataRecv); udpMulticastBusConnection.StartListen(); SafeMobileLib.Utils.WriteLine("SMSSendThread successfully registered to multicast group"); } catch (Exception ex) { SafeMobileLib.Utils.WriteLine("SMSSendThread exception while joining the multicast group: " + ex.ToString(), ConsoleColor.Red); } while (true) { try { //MotoTRBOcmdMsg msg = MotoTRBOGW.locationQueue.GetItem(100); SMSmsg msg = CPlusGW.sendSMSQueue.GetItem(-1);//block until message is in queue SendSMSmsg(msg); if (msg.req_conf) { SafeMobileLib.Utils.WriteLine("Requesting Receive Confirmation"); lock (CPlusGW.waitConfSMSList.SyncRoot) { msg.seq_no = this.sms_seq_id - 1;//-1 because was alraedy incremented for next id CPlusGW.waitConfSMSList.Add(msg); } } Thread.Sleep(1200);//minimum interval between SMS as per MotoTRBO specs } catch (Exception ex) { SafeMobileLib.Utils.WriteLine("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, ConsoleColor.Red); } } // end while (true) } void udpMulticastBusConnection_OnNewDataRecv(byte[] data, int dataLen) { try { string str = System.Text.Encoding.ASCII.GetString(data, 0, dataLen); String[] tempArray = str.Trim().Split('#'); if (tempArray.Length > 3) if (tempArray[3].Equals("142") || tempArray[3].Equals("143")) { //Console.WriteLine("SMSSendThread received from multicast bus: " + str.Trim()); int sched_timeGMT = 0; if (tempArray.Length > 6) sched_timeGMT = Convert.ToInt32(tempArray[6]); //Console.WriteLine("SMS sched time={0} and current time ={1}",sched_timeGMT, DBmanager.DateTo70Format(DateTime.Now.ToUniversalTime())); if (sched_timeGMT <= DateTime.Now.ToUniversalTime().DateTo70Format()) { SMSmsg msg = new SMSmsg(); msg.conf = true; msg.suid = tempArray[4]; msg.msg = tempArray[5]; //in this version DMmsg_id is replaced with seqID msg.DBmsg_id = tempArray[2]; //check to see if we already sent the message lock (CPlusGW.waitConfSMSList.SyncRoot) { int index = -1; int count = 0; foreach (SMSmsg msgTmp in CPlusGW.waitConfSMSList) { if (msg.DBmsg_id == msgTmp.DBmsg_id) { index = count; break; } count++; } if (index == -1)//we didn't found the message { SafeMobileLib.Utils.WriteLine("Message added to sendSMSQueue"); CPlusGW.sendSMSQueue.PostItem(msg); } } } } else if (tempArray[3].Equals("154")) { string SUID = (tempArray[4].Split('.'))[2]; ; String consoleMessage = String.Format($"Poll request received for unit {SUID}"); SafeMobileLib.Utils.WriteLine("»»» " + consoleMessage, ConsoleColor.White); CPlusGW.TextQueue.PostItem(consoleMessage); LocationThread.SendPollLocationRequest(SUID); } } catch (Exception ex) { SM.Debug(ex.ToString()); } } //TODO: remove send SMS from arsthread or create a send SMS object ... public bool SendSMSmsg(SMSmsg p_msg) { try { SendSMS_with_addrs("10000.4@tserv", p_msg.msg, p_msg.conf); return true; } catch (Exception exc) { Console.WriteLine(exc.ToString()); } return false; } public void SendSMS_with_addrs(string address, string msg, bool conf) { SafeMobileLib.Utils.WriteLine("Sending SMS to:" + address + " msg:" + msg + $" on {Program.cfg.ctrlIP}:{Program.cfg.smsPort}", ConsoleColor.Yellow); try { Byte[] sendBytes = PackSMS_with_addrs(address, msg, conf); //Console.WriteLine("Send SMS to SU " + SUID + (conf ? " with confirmation" : " without confirmation") ); CPlusGW.smsUDPclient.Send(sendBytes, sendBytes.Length, Program.cfg.ctrlIP, Program.cfg.smsPort); } catch (Exception exc) { Console.WriteLine(exc.ToString()); } } public static void Send_Reg_msg(string address) { SafeMobileLib.Utils.WriteLine("Sending TMS Service Availability to: " + address + " [" + Program.cfg.ctrlIP + ":" + Program.cfg.smsPort + "]"); try { Byte[] sendBytes = Pack_TMS(address); //Console.WriteLine("Send SMS to SU " + SUID + " with confirmation"); CPlusGW.smsUDPclient.Send(sendBytes, sendBytes.Length, Program.cfg.ctrlIP, Program.cfg.smsPort); } catch (Exception exc) { Console.WriteLine(exc.ToString()); } } byte[] PackSMS_with_addrs(string addrs, string msg_body, bool confirm) { int msg_len = msg_body.Length; int addrs_len = addrs.Length; if (msg_len > MAX_SMS_SIZE) { msg_len = MAX_SMS_SIZE; SafeMobileLib.Utils.WriteLine("Warning: SMS truncated to " + msg_len + " characters"); } if (msg_len > msg_body.Length) { msg_body = msg_body.Remove(MAX_SMS_SIZE); } // compute the len int len = msg_len + addrs_len; len *= 2; // each character is encoded on 2B len += 4; // this is for the headers Byte[] data = new Byte[len + 2]; //+2 for the msg size int msb = (len & 0xff00) >> 8; data[0] = (byte)(msb & 0x00ff); data[1] = (byte)(len & 0x00ff); // put the headers if (confirm) { data[2] = 0xe0; // first header } else { data[2] = 0xa0; // first header } data[3] = (byte)(addrs_len * 2); // addr size for (int i = 0; i < addrs_len; i++) { data[4 + i * 2] = (byte)addrs[i]; data[4 + i * 2 + 1] = 0; } byte lsb_id = (byte)(sms_seq_id & 0x1f); data[4 + addrs_len * 2] = (byte)(0x80 | lsb_id); byte msb_id = (byte)(sms_seq_id & 0x60); // keep bits 6:5 data[5 + addrs_len * 2] = (byte)(msb_id | 0x04); for (int i = 0; i < msg_len; i++) { data[6 + i * 2 + addrs_len * 2] = (byte)msg_body[i]; data[6 + i * 2 + 1 + addrs_len * 2] = 0; } sms_seq_id++; //Console.WriteLine("SMS packed: " + Utils.Byte2String(data, 0, data[1] + 2) + "\n\rSMS_SeQ_ID = " + sms_seq_id); return data; } static byte[] Pack_TMS(string addrs) { int msg_len = 0; int addrs_len = addrs.Length; // compute the len int len = msg_len + addrs_len; len *= 2; // each character is encoded on 2B len += 3; // this is for the headers Byte[] data = new Byte[len + 2]; //+2 for the msg size int msb = (len & 0xff00) >> 8; data[0] = (byte)(msb & 0x00ff); data[1] = (byte)(len & 0x00ff); // put the headers data[2] = 0xD0; // first header data[3] = (byte)(addrs_len * 2); // addr size for (int i = 0; i < addrs_len; i++) { data[4 + i * 2] = (byte)addrs[i]; data[4 + i * 2 + 1] = 0; } //second header data[4 + addrs_len * 2] = 0x00; //Console.WriteLine("SMS packed: " + Utils.Byte2String(data, 0, data[1] + 2) + "\n\rSMS_SeQ_ID = " + sms_seq_id); return data; } int MAX_SMS_SIZE = 120; int MAX_ID_VAL = 100; int sms_seq_id = 1; Byte[] PackSMS(string msg_body, bool confirm) { /* Byte[] sendBytes = { 0x00 , 0x0E , // len 0xE0 , // header 1 0x00 , // addr size 0x88 , 0x04 , // header 2,3 0x41 , 0x00 , 0x64 , 0x00 , 0x67, 0x00 , 0x6A , 0x00, 0x6D , 0x00 //data }; */ int msg_len = msg_body.Length; if (msg_len > MAX_SMS_SIZE) { msg_len = MAX_SMS_SIZE; SafeMobileLib.Utils.WriteLine("Warning: SMS truncked to " + msg_len); } if (sms_seq_id > MAX_ID_VAL) sms_seq_id = 1; if (msg_len > msg_body.Length) { msg_body = msg_body.Remove(MAX_SMS_SIZE); } // compute the len int len = msg_len; len *= 2; // each character is encoded on 2B len += 4; // this is for the headers Byte[] data = new Byte[len + 2]; //+2 for the msg size int msb = (len & 0xff00) >> 8; data[0] = (byte)(msb & 0x00ff); data[1] = (byte)(len & 0x00ff); // put the headers if (confirm) { data[2] = 0xe0; // first header } else { data[2] = 0xa0; // first header } data[3] = 0x00; // addr size byte lsb_id = (byte)(sms_seq_id & 0x1f); data[4] = (byte)(0x80 | lsb_id); byte msb_id = (byte)(sms_seq_id & 0x60); // keep bits 6:5 data[5] = (byte)(msb_id | 0x04); for (int i = 0; i < msg_len; i++) { data[6 + i * 2] = (byte)msg_body[i]; data[6 + i * 2 + 1] = 0; } sms_seq_id++; //Console.WriteLine("SMS packed: " + LocationThread.Byte2String(data, 0, data[1] + 2) + "\n\rSMS_SeQ_ID = " + sms_seq_id); return data; } } }