using System; using System.Net; using System.Net.Sockets; using System.Text; using MotoTRBO_GW; using System.Threading; using SafeMobileLib; namespace MotoTrbo_GW { public class ARSThread { private Int32 port; private Boolean capacityPlus; private String trboLocalIP = ""; private String trboRemoteIP = ""; private String trboID = ""; private UdpMulticast udpMulticast; public static DBvehiclesManager vehiclesManager; private UdpClient udpClient=null; private String mIP; private Int32 mPort; public ARSThread(GatewayID_IP trboID_IP, Int32 arsPort, Boolean capPlus, String multicastIP, String multicastPort) { vehiclesManager = new DBvehiclesManager(Main.DBServer, Main.DBSchema, Main.DBUser, Main.DBPass, Main.DBPort); port = arsPort; capacityPlus = capPlus; SafeMobileLib.Utils.WriteLine("trboID_IP.localIP:" + trboID_IP.localIP + " trboID_IP.remoteIP:" + trboID_IP.remoteIP); trboLocalIP = trboID_IP.localIP; trboRemoteIP = trboID_IP.remoteIP; trboID = trboID_IP.ID; mIP = multicastIP; try { mPort = Convert.ToInt32(multicastPort); } catch (Exception ex) { SafeMobileLib.Utils.WriteLine("Erorr conver port:"+ex.ToString()); } } public void handleConnection() { SafeMobileLib.Utils.WriteLine("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"); SafeMobileLib.Utils.WriteLine("ARS Thread - Initialized on port " + port + " for " + trboLocalIP); try { IPEndPoint ie; if (!capacityPlus) { IPAddress ipAddress = IPAddress.Parse(trboLocalIP); ie = new IPEndPoint(ipAddress, port); } else { ie = new IPEndPoint(IPAddress.Any, port); } udpClient = new UdpClient(ie); //Console.ReadKey(); } catch (Exception ex) { SafeMobileLib.Utils.WriteLine("\ntrboLocalIP:" + trboLocalIP); SafeMobileLib.Utils.WriteLine("ARSThread handleConnection exception INIT udpclient: " + ex.ToString(), ConsoleColor.Red); return; } SafeMobileLib.Utils.WriteLine(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"); try { udpMulticast = new UdpMulticast(mIP,mPort); udpMulticast.OnNewDataRecv += new UdpMulticast.newData4Send(udpMulticast_OnNewDataRecv); SafeMobileLib.Utils.WriteLine("ARS thread successfully registered to multicast group"); udpMulticast.StartListen(Main.LocalIP); } catch (Exception ex) { SafeMobileLib.Utils.WriteLine("ARS Thread exception while joining the multicast group: " + ex.ToString()); } IPEndPoint remoteIpEndPoint = new IPEndPoint(IPAddress.Any, 0); SafeMobileLib.Utils.WriteLine("ARS Thread - Waiting for ARS"); while (true) { try { //SafeMobileLib.Utils.WriteLine(" ARS step 1"); // Blocks until a message returns on this socket from a remote host. Byte[] receivedBytes = udpClient.Receive(ref remoteIpEndPoint); //SafeMobileLib.Utils.WriteLine(" ARS step 2"); char[] separator = { '.' }; string[] su = remoteIpEndPoint.Address.ToString().Split(separator); uint radioID = (Convert.ToUInt32(su[1])) * 256 * 256 + (Convert.ToUInt32(su[2])) * 256 + Convert.ToUInt32(su[3]); string suid = radioID.ToString(); //SafeMobileLib.Utils.WriteLine(" ARS step 3"); header_T reth = DecodePacket(receivedBytes); SafeMobileLib.Utils.WriteLine($"Reth event: >>>>>>>>>>>>>>>> {reth.events.ToString()}", ConsoleColor.Cyan); //SafeMobileLib.Utils.WriteLine(" ARS step 4"); if (reth.events == header_event.Initial_Event || reth.events == header_event.Refresh_Event) { //register route if (!capacityPlus) { SafeMobileLib.Utils.WriteLine("ARSThread received ARS from field unit with ID " + suid + " on gateway radio with IP " + trboLocalIP, ConsoleColor.Magenta); if (RouteManager.NetworkIDs_Hash.ContainsKey(trboRemoteIP)) { RoutingUtils.addRoute(suid, trboRemoteIP, RouteManager.NetworkIDs_Hash[trboRemoteIP].ToString()); } else { SafeMobileLib.Utils.WriteLine("RouteManager.NetworkIDs_Hash does not contain a key for " + trboRemoteIP); } //RoutingUtils.displayRoutes(); } // Sends ACK Byte[] sendBytes = { 0x00, 0x02, 0xBF, 0x00 }; int i = udpClient.Send(sendBytes, sendBytes.Length, remoteIpEndPoint.Address.ToString(), remoteIpEndPoint.Port); SafeMobileLib.Utils.WriteLine("ARS ACK sent to " + remoteIpEndPoint.Address.ToString() + ":" + remoteIpEndPoint.Port.ToString()); } if (reth.pdu_type == 0x00) { int report_time = vehiclesManager.getReportingInterval(radioID.ToString()); LocationThread.SendTriggeredLocationRequest(suid, report_time); } //SafeMobileLib.Utils.WriteLine("ARS Thread received data from radio " + radioID + ": "); //Utils.printBytesArray(receivedBytes); //put information on message bus byte[] arsStatus = new byte[] {(byte)'O',(byte)'N'}; bool isOn = true; switch (reth.pdu_type) { case 0x00: arsStatus = arsStatus = new byte[] { (byte)'O', (byte)'N' }; isOn = true; break; case 0x01: arsStatus = arsStatus = new byte[] { (byte)'O', (byte)'F', (byte)'F' }; isOn = false; break; default: break; } if (reth.pdu_type == 0x00 || reth.pdu_type == 0x01) { string sequenceID = ""; // trigger ARS received event Int64 suId = 0; Int64.TryParse(suid, out suId); OnArsReceived?.Invoke(suId, isOn); Byte[] toSendMulticast = Utils.createMulticastMessage(130, suid, arsStatus, out sequenceID); udpMulticast.Send(toSendMulticast, toSendMulticast.Length); //SafeMobileLib.Utils.WriteLine("ARS thread successfully sent data to message bus"); } //send Subscriber system location string seqID = "0.0"; //build string string fullSource = Main.GWID.ToString() + "#" + trboRemoteIP + "#" + suid; if (capacityPlus) fullSource = Main.GWID.ToString() + "#" + Main.masterRadioIP + "#" + suid; string test = "#139#" + fullSource + "#"; String cmdok = "#" + seqID + test; Int32 tmp = cmdok.Length + 1; tmp += tmp.ToString().Length; cmdok = "#" + tmp.ToString() + cmdok; System.Text.Encoding enc = System.Text.Encoding.ASCII; byte[] buf = enc.GetBytes(cmdok); //send to messagebus udpMulticast.Send(buf, buf.Length); Thread.Sleep(100); } catch (Exception e) { SafeMobileLib.Utils.WriteLine("##### ARSThread Exception #########\n" + e.ToString(), ConsoleColor.Red); Thread.Sleep(15000); //break; } } } void udpMulticast_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("154")) { Int64 gwid_recv = Convert.ToInt64((tempArray[4].Split('.'))[0]); if (gwid_recv == Main.GWID) { //SafeMobileLib.Utils.WriteLine("ARSThread received from multicast bus: " + str.Trim()); string SUID = (tempArray[4].Split('.'))[2]; //QuerryUnit(SUID); } } } } catch (Exception ex) { SafeMobileLib.Utils.WriteLine(ex.ToString()); } } struct header_T { public bool ext, ack, priority, cntl; public byte pdu_type; public SafeMobileLib.header_event events; public byte encoding; } //todo: delete when commands are coming on multicast bus header_T DecodePacket(Byte[] data) { int i, pdata; pdata = (int)data[0]; pdata <<= 8; pdata |= (int)data[1]; // ---------------------------------------- // parse header // ---------------------------------------- header_T header = new header_T(); header.ext = false; if ((data[2] & 0x80) != 0) header.ext = true; header.ack = false; if ((data[2] & 0x40) != 0) header.ack = true; header.priority = false; if ((data[2] & 0x20) != 0) header.priority = true; header.cntl = false; if ((data[2] & 0x10) != 0) header.cntl = true; header.pdu_type = (byte)(data[2] & 0x0F); switch (header.pdu_type) { case 0x00: SafeMobileLib.Utils.WriteLine("ARS Registration"); break; case 0x0F: SafeMobileLib.Utils.WriteLine("Query ACK"); break; case 0x01: SafeMobileLib.Utils.WriteLine("Deregistration message"); break; default: SafeMobileLib.Utils.WriteLine("Unknown ARS message"); break; } i = 3; if (i >= pdata + 2) { //SafeMobileLib.Utils.WriteLine("--------------------"); return header; } if (header.ext) { // read second header octet byte evt = data[i]; evt &= 0x70; evt >>= 5; switch (evt) { case 0: header.events = header_event.Unqualified_Event; break; case 1: header.events = header_event.Initial_Event; break; case 2: header.events = header_event.Refresh_Event; break; default: header.events = header_event.UNKNOWN; break; } header.events = (header_event)evt; header.encoding = (byte)(data[i] & 0x0f); i++; } if (i >= pdata + 2) { return header; } // ---------------------------------------- // parse address len // ---------------------------------------- int addr_len = data[i]; i++; if (i >= pdata + 2) { return header; } i -= 2; return header; } private void QuerryUnit(string SUID) { Byte[] sendBytes = { 0x00, 0x01, // length in Bytes 0x74 // querry }; udpClient.Client.SendTo(sendBytes, new IPEndPoint(IPAddress.Parse(Utils.ID2IP("12", SUID)), port)); SafeMobileLib.Utils.WriteLine("POLL ARS request sent to radio ID " + SUID); } public delegate void ARSReceived(Int64 radioID, bool isON); public event ARSReceived OnArsReceived; } }