using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Text; using System.Net; using System.Net.Sockets; using System.Threading; using System.Collections; using SafeMobileLib; using System.Linq; namespace CPlus_GW { class LocationThread { private static Int32 reqID_send = 0x01; private string reqID; private Int32 reqID_recv; public int port; //public MotoTRBOGW parent; private byte[] data = new byte[1024]; private static UdpClient udpClient; // ------------------------------------------------------------------- // Main // ------------------------------------------------------------------- private bool start_read = true; private UdpMulticast udpMulticast; private int ACCEPTED_LEVEL_OF_CONFIDENCE = 20; #region EVENTS public delegate void PollResponseReceived(Int64 radioID, DateTime locationTime, int speed, double latitude, double longitude, Int64 seqID); public event PollResponseReceived OnPollResponseReceived; public delegate void LocationReceived(Int64 radioID, DateTime locationTime, int speed, double latitude, double longitude); public event LocationReceived OnLocationReceived; #endregion public LocationThread() { Random rnd1 = new Random(); reqID_send = (byte)rnd1.Next(0xffffff); } public void HandleConnection() { //TestPacket(); //return; EndPoint reponseEndPoint = new IPEndPoint(0, 0); try { udpMulticast = new UdpMulticast(Program.cfg.multi_IP, Program.cfg.multi_port); SafeMobileLib.Utils.WriteLine($"Location thread successfully registered to multicast group [{Program.cfg.multi_IP}:{Program.cfg.multi_port}]", ConsoleColor.Cyan); //udpMulticast.OnNewDataRecv += UdpMulticast_OnNewDataRecv; //udpMulticast.OnNewDataRecv += new UdpMulticast.newData4Send(UdpMulticast_OnNewDataRecv); CPlusGW.TextQueue.PostItem("LocationThread started!!!"); //udpMulticast.StartListen(); } catch (Exception ex) { SafeMobileLib.Utils.WriteLine("LocationThread exception while joining the multicast group: " + ex.ToString(), ConsoleColor.Red); } while (true) { try { MotoTRBOcmdMsg msg = CPlusGW.locationQueue.GetItem(100); if (msg != null) { /* if(udpClient!=null) udpClient.Close(); udpClient = null; */ ProcessCommand(msg); start_read = true; } // read async if (start_read) { //SafeMobileLib.Utils.WriteLine("Location Thread waiting message..."); start_read = false; try { if (udpClient == null) { SafeMobileLib.Utils.WriteLine("Location udpClient is null. Recreating it on port " + Program.cfg.locPort_r, ConsoleColor.Yellow); //Program.cfg.locPort_r = 9191; RecreateAndBindUDPClient(); SafeMobileLib.Utils.WriteLine("ReBinding location udpClient", ConsoleColor.Yellow); } IPEndPoint remoteIpEndPoint = new IPEndPoint(IPAddress.Any, 0); //SafeMobileLib.Utils.WriteLine("Before start async"); // Blocks until a message returns on this socket from a remote host. udpClient.Client.BeginReceiveFrom(data, 0, data.Length, SocketFlags.None, ref reponseEndPoint, new AsyncCallback(AsyncRead), (object)this); //SafeMobileLib.Utils.WriteLine("After start async location udpClient"); Thread.Sleep(100); //Console.WriteLine("AsyncRead started for Location thread on port:" + MotoTRBOGW.cfg.locPort_r); } catch (Exception ex) { SafeMobileLib.Utils.WriteLine("HandleConnection(): exception " + ex, ConsoleColor.Red); } } else Thread.Sleep(100); } catch (Exception ex) { SafeMobileLib.Utils.WriteLine("Exception in LocationThread: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 AsyncRead(IAsyncResult result) { EndPoint remoteEndPoint = new IPEndPoint(0, 0); try { int? bytesRead = udpClient?.Client?.EndReceiveFrom(result, ref remoteEndPoint); //SafeMobileLib.Utils.WriteLine($"Location Thread read {bytesRead} bytes", ConsoleColor.Yellow); if (bytesRead > 1) { //Console.WriteLine("\n--------------------"); //Console.WriteLine("AsyncRead endded processing data!!!"); DecodePacket_Connect_plus(data); start_read = true; } else udpClient = null; if (bytesRead == null) { SafeMobileLib.Utils.WriteLine($"Location thread udpclient is {(udpClient == null ? "null" : "not null")}", ConsoleColor.Yellow); } } catch(Exception ex) { //string str = Encoding.ASCII.GetString(data, 0, data.Length); SafeMobileLib.Utils.WriteLine($"Location Thread AsyncRead exception: {ex.ToString()}", ConsoleColor.Red); } } public void DecodePacket_Connect_plus_SDVersion(Byte[] data) { int i = 0, pdata; htCell_t cell = new htCell_t(); cell.lat = ""; cell.lng = ""; cell.di = "0"; cell.location_time = DateTime.MinValue; cell.activity_time = DateTime.MinValue; switch (data[0]) { // ----------------------------------------------------------------------------------------------------------------------- case (byte)Document_Identifiers_ENUM.Triggered_Location_Stop_Answer_NoCDT: case (byte)Document_Identifiers_ENUM.Triggered_Location_Answer_NoCDT: /* if (data[0] == (byte)Document_Identifiers_ENUM.Triggered_Location_Stop_Answer_NoCDT) Console.WriteLine(Document_Identifiers_ENUM.Triggered_Location_Stop_Answer_NoCDT); else Console.WriteLine(Document_Identifiers_ENUM.Triggered_Location_Answer_NoCDT); */ pdata = (int)data[1]; //Console.WriteLine("Length =" + pdata + "(0x" + pdata.ToString("X") + ")"); for (i = 2; i < data[1] + 2; i++) { switch (data[i]) { case (byte)Common_Element_Tokens_ENUM.request_id: //Console.WriteLine(Common_Element_Tokens_ENUM.request_id + ": " + Byte2String(data, i + 1, 5)); i += 5; break; case (byte)Report_Messages_Tokens_ENUM.result: case (byte)Report_Messages_Tokens_ENUM.result2: //Console.WriteLine("Result: " + Byte2String(data, i + 1, 1)); if (data[i + 1] != 0) { Console.WriteLine("Error = " + ProcessError(data[i + 1])); } //Console.WriteLine("OpaqueData: " + Byte2String(data, i + 2, data[1] - i)); i = data[1] + 1; // exit break; case (byte)Report_Messages_Tokens_ENUM.result1: //Console.WriteLine("Result: OK"); break; case (byte)Report_Messages_Tokens_ENUM.SU_IPv4: string suid = ProcessSU_ID(data, i + 1).ToString(); cell.suid = suid; i += 4; //Console.Write("SUIDc: " + suid + " ### "); break; } } break; // ----------------------------------------------------------------------------------------------------------------------- case (byte)Document_Identifiers_ENUM.Triggered_Location_Report_NoCDT: case (byte)Document_Identifiers_ENUM.Immediate_Location_Report_NoCDT: { /* if (data[0] == (byte)Document_Identifiers_ENUM.Triggered_Location_Report_NoCDT) Console.WriteLine(Document_Identifiers_ENUM.Triggered_Location_Report_NoCDT); else Console.WriteLine(Document_Identifiers_ENUM.Immediate_Location_Report_NoCDT); */ pdata = (int)data[1]; Boolean parsingError = false; byte parsErrorBYte = (byte)Result_Codes_ENUM.SYNTAX_ERROR; DateTime gps_time = DateTime.MinValue; for (i = 2; i < data[1] + 2; i++) { switch (data[i]) { case (byte)Report_Messages_Tokens_ENUM.point_2d: cell.lat = ProcessLat(data, i + 1, 4).ToString(); cell.lng = ProcessLng(data, i + 1 + 4, 4).ToString(); if (gps_time == DateTime.MinValue) cell.location_time = DateTime.Now.ToUniversalTime(); /* Console.WriteLine("Point_2d: " + data[i].ToString("X")); Console.WriteLine("Lat: " + Byte2String(data, i + 1, 4) + " =" + cell.lat); Console.WriteLine("Lng: " + Byte2String(data, i + 1 + 4, 4) + " =" + cell.lng); */ i += 8; break; case (byte)Report_Messages_Tokens_ENUM.circle_2d: cell.lat = ProcessLat(data, i + 1, 4).ToString(); cell.lng = ProcessLng(data, i + 1 + 4, 4).ToString(); if (gps_time == DateTime.MinValue) cell.location_time = DateTime.Now.ToUniversalTime(); cell.radius = ProcessUFloat2B(data, i + 1 + 8); /* Console.WriteLine("Circle_2d: " + data[i].ToString("X")); Console.WriteLine("Lat: " + Byte2String(data, i + 1, 4) + " =" + cell.lat); Console.WriteLine("Lng: " + Byte2String(data, i + 1 + 4, 4) + " =" + cell.lng); Console.WriteLine("Rad: " + Byte2String(data, i + 1 + 8, 2) + " =" + cell.radius); */ i += 10; break; case (byte)Report_Messages_Tokens_ENUM.circle_3d: case (byte)Report_Messages_Tokens_ENUM.circle_3d1: cell.lat = ProcessLat(data, i + 1, 4).ToString(); cell.lng = ProcessLng(data, i + 1 + 4, 4).ToString(); if (gps_time == DateTime.MinValue) cell.location_time = DateTime.Now.ToUniversalTime(); cell.radius = ProcessUFloat2B(data, i + 1 + 8); /* Console.WriteLine("Circle_3d: " + data[i].ToString("X")); Console.WriteLine("Lat: " + Byte2String(data, i + 1, 4) + " =" + cell.lat); Console.WriteLine("Lng: " + Byte2String(data, i + 1 + 4, 4) + " =" + cell.lng); Console.WriteLine("Rad: " + Byte2String(data, i + 1 + 8, 2) + " =" + cell.radius); Console.WriteLine("Alt: " + Byte2String(data, i + 1 + 10, 2)); Console.WriteLine("Ala: " + Byte2String(data, i + 1 + 12, 2)); */ i += 14; break; case (byte)Report_Messages_Tokens_ENUM.speed_vrt: //!! not tested //Console.WriteLine(Report_Messages_Tokens_ENUM.speed_vrt + ": " + Byte2String(data, i + 1, 2)); i += 2; break; case (byte)Report_Messages_Tokens_ENUM.speed_hor: cell.spd = (ProcessUFloat2B(data, i + 1) * 3.6).ToString(); //Console.WriteLine(Report_Messages_Tokens_ENUM.speed_hor + ": " + Byte2String(data, i + 1, 2) + " =" + cell.spd); i += 2; break; case (byte)Common_Element_Tokens_ENUM.request_id: //Console.WriteLine(Common_Element_Tokens_ENUM.request_id + ": " + Byte2String(data, i + 1, 5)); i += 5; break; case (byte)Report_Messages_Tokens_ENUM.info_time: case (byte)Report_Messages_Tokens_ENUM.info_time1: gps_time = ProcessTime(data, i + 1, 5); //Console.WriteLine(Report_Messages_Tokens_ENUM.info_time + ": " + Byte2String(data, i + 1, 5) + " =" + gps_time); i += 5; break; // RESULTS case (byte)Report_Messages_Tokens_ENUM.result: case (byte)Report_Messages_Tokens_ENUM.result2: //Console.WriteLine("Result: " + Byte2String(data, i + 1, 1)); if (data[i + 1] != 0) { parsErrorBYte = data[i + 1]; if (data[i + 1] == (byte)Result_Codes_ENUM.QUERY_INFO_NOT_ATTAINABLE || data[i + 1] == (byte)Result_Codes_ENUM.QUERY_INFO_NOT_CURRENTLY_ATTAINABLE) { cell.lat = "0"; cell.lng = "0"; cell.spd = "0"; gps_time = DateTime.UtcNow; //Console.WriteLine("INFO got QUERY_INFO_NOT_ATTAINABLE ...adding values lat=0,lng=0,time =DateTime.UtcNow"); } else { SafeMobileLib.Utils.WriteLine("GPS returned with »» " + ProcessError(data[i + 1])); parsingError = true; } } //Console.WriteLine("OpaqueData: " + Byte2String(data, i + 2, data[1] - i)); i = data[1] + 1; // exit break; case (byte)Report_Messages_Tokens_ENUM.result1: //Console.WriteLine("Result: OK"); break; case (byte)Report_Messages_Tokens_ENUM.SU_IPv4: string suid = ProcessSU_ID(data, i + 1).ToString(); cell.suid = suid; //Console.Write("SUID: " +suid+" ### "); i += 4; break; default: Console.WriteLine("Unknown: 0x" + data[i].ToString("X")); break; } } if (!parsingError) { try { if (cell!= null && cell.suid != null) { cell.spd = cell.spd ?? "0"; cell.lat = cell.lat ?? "0"; cell.lng = cell.lng ?? "0"; double d = 0; if (!Double.TryParse(cell.spd, out d)) cell.spd = "0"; if (!Double.TryParse(cell.lat, out d)) cell.lat = "0"; if (!Double.TryParse(cell.lng, out d)) cell.lng = "0"; String[] toSendString = new String[4]; toSendString[0] = DateTo70Format(DateTime.UtcNow).ToString(); toSendString[1] = cell.spd; toSendString[2] = cell.lat; toSendString[3] = cell.lng; String consoleMessage = String.Format("Position [{0:0.0000},{1:0.0000}] from {2}", Math.Round(Double.Parse(cell.lat), 4), Math.Round(Double.Parse(cell.lng), 4), cell.suid); SafeMobileLib.Utils.WriteLine("»»» " + consoleMessage, ConsoleColor.Green); CPlusGW.TextQueue.PostItem(consoleMessage);//"GPS for unit:" + cell.suid + " LAT:" + cell.lat.ToString() + " LNG:" + cell.lng.ToString()); Byte[] toSendMulticast = createLocationMessage(131, cell.suid, toSendString); if (udpMulticast != null) udpMulticast.Send(toSendMulticast, toSendMulticast.Length); else SafeMobileLib.Utils.WriteLine("Unable to send position on multicast (it is null)", ConsoleColor.Red); //Console.WriteLine("SUID:" + cell.suid + " LAT:" + cell.lat.ToString() + " LNG:" + cell.lng.ToString()); //SM.Debug("Location thread successfully sent data to message bus"); } } catch (Exception ex) { SafeMobileLib.Utils.WriteLine("Decode Message error: " + ex.ToString(), ConsoleColor.Red); } } } break; // ----------------------------------------------------------------------------------------------------------------------- default: Console.WriteLine("UNDEFINED 0x" + data[0].ToString("X")); break; } } public void DecodePacket_Connect_plus(Byte[] data) { int i = 0, pdata; htCell_t cell = new htCell_t(); cell.lat = ""; cell.lng = ""; cell.di = "0"; cell.spd = "0"; cell.spd_v = "0"; cell.suid = ""; cell.location_time = DateTime.MinValue; cell.activity_time = DateTime.MinValue; cell.triggered = false; cell.level_confidence = -1; switch (data[0]) { // ----------------------------------------------------------------------------------------------------------------------- case (byte)Document_Identifiers_ENUM.Triggered_Location_Stop_Answer_NoCDT: case (byte)Document_Identifiers_ENUM.Triggered_Location_Answer_NoCDT: /* if (data[0] == (byte)Document_Identifiers_ENUM.Triggered_Location_Stop_Answer_NoCDT) SafeMobileLib.Utils.WriteLine(Document_Identifiers_ENUM.Triggered_Location_Stop_Answer_NoCDT + ""); else SafeMobileLib.Utils.WriteLine(Document_Identifiers_ENUM.Triggered_Location_Answer_NoCDT + ""); */ pdata = (int)data[1]; string result = ""; //Console.WriteLine("Length =" + pdata + "(0x" + pdata.ToString("X") + ")"); for (i = 2; i < data[1] + 2; i++) { switch (data[i]) { case (byte)Common_Element_Tokens_ENUM.request_id: //Console.WriteLine(Common_Element_Tokens_ENUM.request_id + ": " + Byte2String(data, i + 1, 5)); //Console.WriteLine(data[i + 5]); byte[] bytes = { data[i + 5], data[i + 4], data[i + 3], data[i + 2] }; reqID = Byte2String(data, i + 1, 5); reqID_recv = BitConverter.ToInt32(bytes, 0); cell.seq_ID = Byte2String(data, i + 2, data[i + 1]) + ""; cell.requestID = data[i + 5]; i += 5; break; case (byte)Report_Messages_Tokens_ENUM.result: case (byte)Report_Messages_Tokens_ENUM.result2: //Console.WriteLine("Result: " + Byte2String(data, i + 1, 1)); if (data[i + 1] != 0) { SafeMobileLib.Utils.WriteLine("GPS returned with » " + ProcessError(data[i + 1]), ConsoleType.GPS); result = ProcessError(data[i + 1]); } //Console.WriteLine("OpaqueData: " + Byte2String(data, i + 2, data[1] - i)); i = data[1] + 1; // exit break; case (byte)Report_Messages_Tokens_ENUM.result1: //Console.WriteLine("Result: OK"); result = "OK"; break; case (byte)Report_Messages_Tokens_ENUM.SU_IPv4: string suid = ProcessSU_ID(data, i + 1).ToString(); cell.suid = suid; i += 4; //Console.Write("SUIDc: " + suid + " ### "); break; } } /* LOGS.LOG("Debug: LOCK3"); //remove message from pending lock (ht_pendingMsg.SyncRoot) { try { if (reqID_recv != null && ht_pendingMsg.ContainsKey(reqID_recv)) { //LOGS.LOG(ConnectPlus_GW.cfg.gw_id + cell.suid + " removing from pending \t regID:" + reqID); ht_pendingMsg.Remove(reqID_recv); } } catch (Exception e) { LOGS.LOG("Error: cannot delete pending messages HashTable" + e.ToString()); } } LOGS.LOG("Debug: UN-LOCK3"); */ /* if (data[0] == (byte)Document_Identifiers_ENUM.Triggered_Location_Stop_Answer_NoCDT) SafeMobileLib.Utils.WriteLine(cell.suid + " Triggered_Location_Stop_Answer_NoCDT \t regID:" + reqID + " \t result:" + result); else SafeMobileLib.Utils.WriteLine(cell.suid + " Triggered_Location_Answer_NoCDT \t regID:" + reqID + " \t result:" + result);*/ break; // ----------------------------------------------------------------------------------------------------------------------- case (byte)Document_Identifiers_ENUM.Triggered_Location_Report_NoCDT: case (byte)Document_Identifiers_ENUM.Immediate_Location_Report_NoCDT: { /* if (data[0] == (byte)Document_Identifiers_ENUM.Triggered_Location_Report_NoCDT) Console.WriteLine(Document_Identifiers_ENUM.Triggered_Location_Report_NoCDT); else Console.WriteLine(Document_Identifiers_ENUM.Immediate_Location_Report_NoCDT); */ if (data[0] == (byte)Document_Identifiers_ENUM.Triggered_Location_Report_NoCDT) { cell.triggered = true; } else { //Utils.ConsWrite(DebugMSG_Type.DEV, "Got request id:" + cell.requestID); } pdata = (int)data[1]; Boolean parsingError = false; byte parsErrorBYte = (byte)Result_Codes_ENUM.SYNTAX_ERROR; DateTime gps_time = DateTime.MinValue; for (i = 2; i < data[1] + 2; i++) { switch (data[i]) { case (byte)Report_Messages_Tokens_ENUM.point_2d: cell.lat = ProcessLat(data, i + 1, 4).ToString(); cell.lng = ProcessLng(data, i + 1 + 4, 4).ToString(); cell.d_lat = ProcessLat(data, i + 1, 4); cell.d_lng = ProcessLng(data, i + 1 + 4, 4); if (gps_time == DateTime.MinValue) cell.location_time = DateTime.Now.ToUniversalTime(); /* Console.WriteLine("Point_2d: " + data[i].ToString("X")); Console.WriteLine("Lat: " + Byte2String(data, i + 1, 4) + " =" + cell.lat); Console.WriteLine("Lng: " + Byte2String(data, i + 1 + 4, 4) + " =" + cell.lng); */ i += 8; break; case (byte)Report_Messages_Tokens_ENUM.point_3d: //Console.WriteLine("### Point 3d ###"); cell.lat = ProcessLat(data, i + 1, 4).ToString(); cell.lng = ProcessLng(data, i + 1 + 4, 4).ToString(); cell.d_lat = ProcessLat(data, i + 1, 4); cell.d_lng = ProcessLng(data, i + 1 + 4, 4); if (gps_time == DateTime.MinValue) cell.location_time = DateTime.Now.ToUniversalTime(); i += 11; break; case (byte)Report_Messages_Tokens_ENUM.circle_2d: cell.lat = ProcessLat(data, i + 1, 4).ToString(); cell.lng = ProcessLng(data, i + 1 + 4, 4).ToString(); cell.d_lat = ProcessLat(data, i + 1, 4); cell.d_lng = ProcessLng(data, i + 1 + 4, 4); if (gps_time == DateTime.MinValue) cell.location_time = DateTime.Now.ToUniversalTime(); cell.radius = ProcessUFloat2B(data, i + 1 + 8); /* Console.WriteLine("Circle_2d: " + data[i].ToString("X")); Console.WriteLine("Lat: " + Byte2String(data, i + 1, 4) + " =" + cell.lat); Console.WriteLine("Lng: " + Byte2String(data, i + 1 + 4, 4) + " =" + cell.lng); Console.WriteLine("Rad: " + Byte2String(data, i + 1 + 8, 2) + " =" + cell.radius); */ i += 10; break; case (byte)Report_Messages_Tokens_ENUM.circle_3d: case (byte)Report_Messages_Tokens_ENUM.circle_3d1: cell.lat = ProcessLat(data, i + 1, 4).ToString(); cell.lng = ProcessLng(data, i + 1 + 4, 4).ToString(); cell.d_lat = ProcessLat(data, i + 1, 4); cell.d_lng = ProcessLng(data, i + 1 + 4, 4); if (gps_time == DateTime.MinValue) cell.location_time = DateTime.Now.ToUniversalTime(); cell.radius = ProcessUFloat2B(data, i + 1 + 8); /* Console.WriteLine("Circle_3d: " + data[i].ToString("X")); Console.WriteLine("Lat: " + Byte2String(data, i + 1, 4) + " =" + cell.lat); Console.WriteLine("Lng: " + Byte2String(data, i + 1 + 4, 4) + " =" + cell.lng); Console.WriteLine("Rad: " + Byte2String(data, i + 1 + 8, 2) + " =" + cell.radius); Console.WriteLine("Alt: " + Byte2String(data, i + 1 + 10, 2)); Console.WriteLine("Ala: " + Byte2String(data, i + 1 + 12, 2)); */ //if (!cell.triggered) Console.WriteLine("Lat: " + Byte2String(data, i + 1, 4) + " =" + cell.lat); //if (!cell.triggered) Console.WriteLine("Lng: " + Byte2String(data, i + 1 + 4, 4) + " =" + cell.lng); i += 14; break; case (byte)Report_Messages_Tokens_ENUM.speed_vrt: //!! not tested cell.spd_v = Math.Round((ProcessUFloat2B(data, i + 1) * 3.6)).ToString(); //Console.WriteLine(Report_Messages_Tokens_ENUM.speed_vrt + ": " + Byte2String(data, i + 1, 2) + " =" + cell.spd_v); i += 2; break; case (byte)Report_Messages_Tokens_ENUM.speed_hor: cell.spd = Math.Round((ProcessUFloat2B(data, i + 1) * 3.6)).ToString(); //Console.WriteLine(Report_Messages_Tokens_ENUM.speed_hor + ": " + Byte2String(data, i + 1, 2) + " =" + cell.spd); i += 2; break; case (byte)Report_Messages_Tokens_ENUM.lev_conf: //!! not tested cell.level_confidence = (int)data[i + 1]; //Console.WriteLine(Report_Messages_Tokens_ENUM.lev_conf + ": " + Byte2String(data, i + 1, 1) + " =" + cell.level_confidence) ; i += 1; break; case (byte)Common_Element_Tokens_ENUM.request_id: cell.seq_ID = Byte2String(data, i + 2, data[i + 1]) + ""; cell.requestID = data[i + 1 + data[i + 1]]; //if (!cell.triggered) Console.WriteLine(Common_Element_Tokens_ENUM.request_id + ": " + Byte2String(data, i + 1, 5)); i += 5; break; case (byte)Report_Messages_Tokens_ENUM.info_time: case (byte)Report_Messages_Tokens_ENUM.info_time1: gps_time = ProcessTime(data, i + 1, 5); //Console.WriteLine("INFO_TIME: " + Report_Messages_Tokens_ENUM.info_time + ": " + Byte2String(data, i + 1, 5) + " =" + gps_time); i += 5; break; case (byte)Report_Messages_Tokens_ENUM.SU_IPv4: string suid = ProcessSU_ID(data, i + 1).ToString(); cell.suid = suid; //Utils.ConsWrite(DebugMSG_Type.GPS, "SUID: " + suid + " ### "); //if (!cell.triggered) // Utils.ConsWrite(DebugMSG_Type.DEV, "SUID: " + suid + " ### "); i += 4; break; // RESULTS case (byte)Report_Messages_Tokens_ENUM.result: case (byte)Report_Messages_Tokens_ENUM.result2: //Console.WriteLine("Result: " + Byte2String(data, i + 1, 1)); if (data[i + 1] != 0) { parsErrorBYte = data[i + 1]; if (data[i + 1] == (byte)Result_Codes_ENUM.QUERY_INFO_NOT_ATTAINABLE || data[i + 1] == (byte)Result_Codes_ENUM.QUERY_INFO_NOT_CURRENTLY_ATTAINABLE) { cell.lat = "0"; cell.lng = "0"; cell.spd = "0"; gps_time = DateTime.UtcNow; //Console.WriteLine("INFO got QUERY_INFO_NOT_ATTAINABLE ...adding values lat=0,lng=0,time =DateTime.UtcNow"); } else { SafeMobileLib.Utils.WriteLine("GPS returned with »» " + ProcessError(data[i + 1]), ConsoleType.GPS); parsingError = true; } } //Console.WriteLine("OpaqueData: " + Byte2String(data, i + 2, data[1] - i)); i = data[1] + 1; // exit break; case (byte)Report_Messages_Tokens_ENUM.result1: //Console.WriteLine("Result: OK"); break; case (byte)Report_Messages_Tokens_ENUM.direction_hor: i += 1; break; default: SafeMobileLib.Utils.WriteLine("Unknown: 0x" + data[i].ToString("X"), ConsoleType.GPS); break; } } Vehicles veh = MainForm.vehicles.FirstOrDefault(d => d.Imei.Equals(cell.suid)); if (veh == null || !veh.Active) { SafeMobileLib.Utils.WriteLine($"Location received from unit {cell.suid} that is not defined in the admin", ConsoleColor.White); Thread.Sleep(100); break; } if (gps_time == DateTime.MinValue) SafeMobileLib.Utils.WriteLine("GPS gps_time == DateTime.MinValue", ConsoleType.GPS); else if (!parsingError || (((parsErrorBYte == (byte)Result_Codes_ENUM.QUERY_INFO_NOT_ATTAINABLE) || (parsErrorBYte == (byte)Result_Codes_ENUM.QUERY_INFO_NOT_CURRENTLY_ATTAINABLE)) && (!cell.triggered))) { //Utils.ConsWrite(DebugMSG_Type.DEV, "Got location from" + cell.suid); cell.location_time = DateTime.UtcNow; // check if the position fulfilled the requirements for LoC if (cell.level_confidence == -1) { // message didn't contained any level of confidence information } else if (cell.level_confidence < ACCEPTED_LEVEL_OF_CONFIDENCE) { cell.lat = "0"; cell.lng = "0"; cell.spd = "0"; cell.location_time = DateTime.UtcNow; } try { if (cell != null && cell.suid != null) { cell.spd = cell.spd ?? "0"; cell.lat = cell.lat ?? "0"; cell.lng = cell.lng ?? "0"; double d = 0; if (!Double.TryParse(cell.spd, out d)) cell.spd = "0"; if (!Double.TryParse(cell.lat, out d)) cell.lat = "0"; if (!Double.TryParse(cell.lng, out d)) cell.lng = "0"; String[] toSendString = new String[4]; toSendString[0] = DateTo70Format(DateTime.UtcNow).ToString(); toSendString[1] = cell.spd; toSendString[2] = cell.lat; toSendString[3] = cell.lng; String consoleMessage = String.Format((cell.triggered ? "Position " : "Poll response ") + "[{0:0.0000},{1:0.0000}] from {2}", Math.Round(Double.Parse(cell.lat), 4), Math.Round(Double.Parse(cell.lng), 4), cell.suid); SafeMobileLib.Utils.WriteLine("»»» " + consoleMessage, ConsoleColor.Green); // post message to be added in the UI CPlusGW.TextQueue.PostItem(consoleMessage); Byte[] toSendMulticast = SafeMobileLib.Utils.createLocationMessage(cell.triggered ? 131 : 231, cell.suid, toSendString); udpMulticast.Send(toSendMulticast, toSendMulticast.Length); } } catch (Exception ex) { SafeMobileLib.Utils.WriteLine("[Location Thread]: " + ex.ToString(), ConsoleColor.Red); } } else if (parsErrorBYte == (byte)Result_Codes_ENUM.PROTOCOL_ELEMENT_NOT_SUPPORTED) { // this is error is generated whenever a location request sent to a field radio contains // required information that are not supported by that station //SendTriggeredLocationSTOP(cell.suid, cell.requestID); // send Triggered Location Request which contains the level of confidence reqID_send++; if (reqID_send == Int32.MaxValue) reqID_send = 1; SafeMobileLib.Utils.WriteLine("PROTOCOL_ELEMENT_NOT_SUPPORTED for unit " + cell.suid, ConsoleColor.Magenta); //SendTriggeredLocationRequest(cell.suid, (uint)((SUinfo)SN_Queues.ht_SUInfo[cell.suid]).repInterval, reqID_send); } } break; // ----------------------------------------------------------------------------------------------------------------------- default: SafeMobileLib.Utils.WriteLine("UNDEFINED 0x" + data[0].ToString("X"), ConsoleType.GPS); break; } } void ProcessCommand(MotoTRBOcmdMsg p_msg) { reqID_send++; if (reqID_send == Int32.MaxValue) reqID_send = 1; try { if (p_msg.m_cmd == (byte)MotoTRBOcmd.SET_REPORT_INTERVAL) SendTriggeredLocationRequest(p_msg.m_suid, Convert.ToUInt32(p_msg.m_payload)); } catch (Exception e) { Console.WriteLine("Could not send Location Request to unit"); Console.WriteLine(e.Message); } } private static UdpClient sendUdpClient = new UdpClient(); public void SendTriggeredLocationRequest(string SUID, uint p_reportSec) { byte[] intBytes = BitConverter.GetBytes(reqID_send); if (BitConverter.IsLittleEndian) Array.Reverse(intBytes); byte[] arr_radioID = Utils.ID2ByteARR("12", SUID); Byte[] sendBytes = { (byte)Document_Identifiers_ENUM.Triggered_Location_Request_NoCDT, 0x10, // length in Bytes (byte)Common_Element_Tokens_ENUM.request_id, 0x04, intBytes[0], intBytes[1], intBytes[2], intBytes[3], //0x04, 0x24, 0x68, 0xAC, 0xE0, (byte)Query_Request_Messages_Tokens_ENUM.SU_IPv4, arr_radioID[0], arr_radioID[1], arr_radioID[2], arr_radioID[3], 0x51, (byte)Query_Request_Messages_Tokens_ENUM.request_speed_hor, (byte)Query_Request_Messages_Tokens_ENUM.periodic_trigger, (byte)Query_Request_Messages_Tokens_ENUM.interval, 0x00, 0x00 //(byte)report_time// in seconds }; try { if (sendUdpClient == null) { //SafeMobileLib.Utils.WriteLine("Creating udp client for sending Location request on port " + Program.cfg.locPort, ConsoleColor.Cyan); sendUdpClient = new UdpClient(Program.cfg.locPort); } int report_time = (int)p_reportSec; if (report_time < 0x80) { //sendBytes[10] = (byte)report_time; sendBytes[17] = (byte)report_time; } else { sendBytes[1] += 1; // adjust length int process = report_time; // MSB process >>= 7; process &= 0x007F; process |= 0x0080; sendBytes[17] = (byte)process; sendBytes[18] = (byte)(report_time & 0x007F); //LSB } SendOnUDP(sendBytes, sendBytes.Length); SafeMobileLib.Utils.WriteLine($"Triggered location request sent to radio ID {SUID} [{report_time} seconds]", ConsoleColor.White); /* //Print(sendBytes, sendBytes.Length, false); udpClient.Send(sendBytes, sendBytes.Length, new IPEndPoint(IPAddress.Parse(Program.cfg.ctrlIP), Program.cfg.locPort)); //udpClient.Send(sendBytes, new IPEndPoint(IPAddress.Parse(MotoTRBOGW.cfg.ctrlIP), MotoTRBOGW.cfg.locPort)); udpClient.Close(); udpClient = null;*/ } catch (Exception ex) { SafeMobileLib.Utils.WriteLine("Location Thread SendTriggeredLocationRequest exception: " + ex.ToString(), ConsoleColor.Red); } } private void RecreateAndBindUDPClient() { udpClient = new UdpClient(); udpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); udpClient.Client.Bind(new IPEndPoint(IPAddress.Any, Program.cfg.locPort_r)); } private static void RecreateSendingUdpClient() { if (sendUdpClient == null) { SafeMobileLib.Utils.WriteLine("Creating udp client for sending Location request on port " + Program.cfg.locPort, ConsoleColor.Cyan); sendUdpClient = new UdpClient(Program.cfg.locPort); } } private void UdpMulticast_OnNewDataRecv(byte[] data, int dataLen) { string str = Encoding.ASCII.GetString(data, 0, dataLen); try { SafeMobileLib.Utils.WriteLine("RECEIVED FROM LOCATION THREAD " + str); String[] tempArray = str.Trim().Split('#'); if (tempArray.Length > 3) if (tempArray[3].Equals("154")) { string SUID = tempArray[4]; String consoleMessage = String.Format($"Poll request received for unit {SUID}"); SafeMobileLib.Utils.WriteLine("»»» " + consoleMessage, ConsoleColor.White); CPlusGW.TextQueue.PostItem(consoleMessage); SendPollLocationRequest(SUID); } } catch (Exception ex) { SafeMobileLib.Utils.WriteLine("udpMulticast_OnNewDataRecv Exception: " + str, ConsoleColor.Red); } } /// /// Request a field radio to report immediate its location [also know as poll] /// /// The field radio ID which needs to send imeediate its location /// The triggered location ID for this poll request public static void SendPollLocationRequest(string SUID) { Int32 reqID = ++reqID_send; byte[] arr_radioID = Utils.ID2ByteARR("12", SUID); //get reqid bytes byte[] intBytes = BitConverter.GetBytes(reqID); if (BitConverter.IsLittleEndian) Array.Reverse(intBytes); Byte[] sendBytes = { (byte)Document_Identifiers_ENUM.Immediate_Location_Request_NoCDT, 0x0D, // length in Bytes (byte)Common_Element_Tokens_ENUM.request_id, 0x04, intBytes[0], intBytes[1], intBytes[2], intBytes[3], (byte)Query_Request_Messages_Tokens_ENUM.SU_IPv4, arr_radioID[0], arr_radioID[1], arr_radioID[2], arr_radioID[3], 0x51, (byte)Query_Request_Messages_Tokens_ENUM.request_speed_hor }; bool result = SendOnUDP(sendBytes, sendBytes.Length); string consoleMessage = String.Format("{0} POLL location request for {1} [{2}]", (result ? "««« Sent" : "ooo Not Sent "), SUID, reqID); SafeMobileLib.Utils.WriteLine(consoleMessage, ConsoleColor.DarkGreen); } /// /// Send a byte array on UDP /// /// The byte array which needs to be sent on UDP /// /// private static bool SendOnUDP(byte[] sendBytes, int length) { try { RecreateSendingUdpClient(); sendUdpClient.Send(sendBytes, length, new IPEndPoint(IPAddress.Parse(Program.cfg.ctrlIP), Program.cfg.locPort)); sendUdpClient.Close(); sendUdpClient = null; return true; } catch (Exception ex) { SafeMobileLib.Utils.WriteLine("[Location Thread] Send on UDP exception: " + ex.ToString(), ConsoleColor.Red); return false; } } // ------------------------------------------------------------------- // Aux functions // ------------------------------------------------------------------- static public string Byte2String(byte[] data) { string sdata = ""; int i; for (i = 0; i < data.Length; i++) { int ii; ii = (int)data[i]; sdata += "0x" + ii.ToString("X") + " "; } return sdata; } static public string Byte2String(byte[] data, int startIndex, int len) { string sdata = ""; int i; if (startIndex > data.Length) return ""; for (i = startIndex; i < startIndex + len && i < data.Length; i++) { int ii; ii = (int)data[i]; sdata += "0x" + ii.ToString("X") + " "; } return sdata; } static string ProcessError(Byte err) { switch (err) { case (byte)Result_Codes_ENUM.SUCCESS: return "" + Result_Codes_ENUM.SUCCESS; case (byte)Result_Codes_ENUM.UNSUPPORTED_VERSION: return "" + Result_Codes_ENUM.UNSUPPORTED_VERSION; case (byte)Result_Codes_ENUM.SYNTAX_ERROR: return "" + Result_Codes_ENUM.SYNTAX_ERROR; case (byte)Result_Codes_ENUM.PROTOCOL_ELEMENT_NOT_SUPPORTED: return "" + Result_Codes_ENUM.PROTOCOL_ELEMENT_NOT_SUPPORTED; case (byte)Result_Codes_ENUM.PROTOCOL_ELEMENT_VALUE_OUT_OF_RANGE: return "" + Result_Codes_ENUM.PROTOCOL_ELEMENT_VALUE_OUT_OF_RANGE; case (byte)Result_Codes_ENUM.QUERY_INFO_NOT_ATTAINABLE: return "" + Result_Codes_ENUM.QUERY_INFO_NOT_ATTAINABLE; case (byte)Result_Codes_ENUM.NO_SUCH_REQUEST: return "" + Result_Codes_ENUM.NO_SUCH_REQUEST; case (byte)Result_Codes_ENUM.DUPLICATE_REQUEST_ID: return "" + Result_Codes_ENUM.DUPLICATE_REQUEST_ID; } return "Unknown err"; } static public double ProcessUFloat2B(Byte[] data, int startIndex) { int aux = data[startIndex]; aux &= 0xff; int int_part = 0; int i=0; // get the int part while ((aux & 0x80) != 0) { //Console.Write("<" + aux.ToString("X") + ">"); int_part |= (aux ^ 0x80); int_part <<= 7; i++; aux = data[startIndex+i]; aux &= 0xff; //Console.Write("[" + int_part.ToString("X") + "]"); } //Console.Write("<" + aux.ToString("X") + ">"); int_part |= aux; //Console.Write("[" + int_part.ToString("X") + "]"); // ignore the float part i++; while ((data[startIndex + i] & 0x80) != 0) { //Console.Write("<" + data[startIndex + i] + ">"); i++; } //Console.WriteLine(); return (double)int_part; } static DateTime ProcessTime(Byte[] data, int startIndex, int len) { // (yyyy*2^26) + (MM*2^22) + (DD*2^17) + (hh*2^12) + (mm*2^6) + ss Byte B1 = data[startIndex]; Byte B2 = data[startIndex + 1]; Byte B3 = data[startIndex + 2]; Byte B4 = data[startIndex + 3]; Byte B5 = data[startIndex + 4]; int hh, mm, ss, YY, MM, DD; ss = B5 & 0x3F; // remove first 2b mm = B4 & 0x0F; mm <<= 2; mm |= ((B5 >> 6) & 0x03); hh = B3 & 0x01; hh <<= 4; hh |= ((B4 & 0xf0) >> 4); DD = B3 & 0x3E; DD >>= 1; MM = B2 & 0x03; MM <<= 2; MM |= ((B3 >> 6) & 0x03); YY = B1; YY <<= 6; YY |= ((B2 >> 2) & 0x3F); //Console.WriteLine("YY=" + YY.ToString("X")); //Console.WriteLine("MM=" + MM.ToString("X")); //Console.WriteLine("DD=" + DD.ToString("X")); //Console.WriteLine("hh=" + hh.ToString("X")); //Console.WriteLine("mm=" + mm.ToString("X")); //Console.WriteLine("ss=" + ss.ToString("X")); //Console.WriteLine("GPSTime : " + YY + "/" + MM + "/" + DD + " " + hh + ":" + mm + ":" + ss); return new DateTime(YY, MM, DD, hh, mm, ss, DateTimeKind.Utc); } static double ProcessLat(Byte[] data, int startIndex, int len) { bool sign = false; if ((data[startIndex] & 0x80) != 0) { sign = true; } ulong l = (ulong)data[startIndex]; if (sign) l ^= 0x80; // remove the sign l <<= 8; l |= (ulong)data[startIndex + 1]; l <<= 8; l |= (ulong)data[startIndex + 2]; l <<= 8; l |= (ulong)data[startIndex + 3]; //Console.WriteLine("lat ulong=0x" + l.ToString("X")); double ld = (double)l; ld *= 90; ld /= 1024; ld /= 1024; ld /= 1024; ld /= 2; if (sign) ld *= -1; return ld; } static double ProcessLng(Byte[] data, int startIndex, int len) { bool sign = false; if ((data[startIndex] & 0x80) != 0) { sign = true; } //Console.WriteLine("data[]=" + data[startIndex].ToString("X") + " sign=" + sign); ulong l = (ulong)data[startIndex]; if (sign) l ^= 0x80; // remove the sign l <<= 8; l |= (ulong)data[startIndex + 1]; l <<= 8; l |= (ulong)data[startIndex + 2]; l <<= 8; l |= (ulong)data[startIndex + 3]; //Console.WriteLine("lng ulong=0x" + l.ToString("X")); double ld = (double)l; ld *= 360; ld /= 1024; ld /= 1024; ld /= 1024; ld /= 4; if (sign) { ld = 180 - ld; ld *= -1; } return ld; } private int ProcessSU_ID(Byte[] data, int startIndex) { Byte B1 = data[startIndex]; Byte B2 = data[startIndex + 1]; Byte B3 = data[startIndex + 2]; Byte B4 = data[startIndex + 3]; int radioID = B4 + B3 * 256 + B2 * 256 * 256; return radioID; } private static 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("--------------------------------------------------------------------------- "); } public static Byte[] createLocationMessage(int opCode, string suid, String[] dataString) { string msg = ""; msg = "#1." + GetSecondsLocalFromDT(DateTime.Now).ToString() + DateTime.Now.Millisecond.ToString() + "#" + opCode + "#" + suid + "#"; msg = msg + dataString[0] + "#" + dataString[1] + "#" + dataString[2] + "#" + dataString[3]; int totalSize = 5 + msg.Length; string sizeMsg = String.Format("#{0:000}", totalSize); msg = sizeMsg + msg; Byte[] toSendMulticast = new Byte[totalSize]; System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding(); Byte[] toSendMulticastPartial = encoding.GetBytes(msg); for (int i = 0; i < toSendMulticastPartial.Length; i++) { toSendMulticast[i] = toSendMulticastPartial[i]; } toSendMulticast[totalSize - 1] = 35;//'#' return toSendMulticast; } public static Int32 GetSecondsLocalFromDT(DateTime param) { System.DateTime datetime = param; long nOfSeconds; System.DateTime dt70 = new DateTime(1970, 1, 1, 0, 0, 0, 0); System.DateTime dttmp1 = new DateTime(1970, 1, 1, 0, 0, 0, 0); System.DateTime dttmp2; dttmp2 = dttmp1.ToLocalTime(); TimeSpan span2 = dttmp2 - dttmp1; TimeSpan span = datetime - dt70; //nOfSeconds = (long)span.TotalSeconds - (long)span2.TotalSeconds -3600; //mai scot o ora - 3600 if (System.TimeZone.CurrentTimeZone.IsDaylightSavingTime(param)) nOfSeconds = (long)span.TotalSeconds - (long)span2.TotalSeconds - 3600; //mai scot o ora - 3600 else nOfSeconds = (long)span.TotalSeconds - (long)span2.TotalSeconds; return ((Int32)nOfSeconds); } private uint DateTo70Format(DateTime param) { long nOfSeconds; //Console.WriteLine("DateTo70Format param=" + param); System.DateTime dt70 = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); TimeSpan span = param - dt70; nOfSeconds = (long)span.TotalSeconds; return ((uint)nOfSeconds); } } class LocationThread3 { public UInt16 port; //public MotoTRBOGW parent; private byte[] data = new byte[1024]; private static UdpClient udpClient; // ------------------------------------------------------------------- // Main // ------------------------------------------------------------------- private bool start_read = true; public void HandleConnection() { //TestPacket(); //return; EndPoint reponseEndPoint = new IPEndPoint(0, 0); while (true) { try { MotoTRBOcmdMsg msg = CPlusGW.locationQueue.GetItem(100); if (msg != null) { if (udpClient != null) udpClient.Close(); udpClient = null; ProcessCommand(msg); start_read = true; } // read async if (start_read) { start_read = false; try { if (udpClient == null) { udpClient = new UdpClient(); udpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); udpClient.Client.Bind(new IPEndPoint(IPAddress.Any, Program.cfg.locPort_r)); } IPEndPoint remoteIpEndPoint = new IPEndPoint(IPAddress.Any, 0); // Blocks until a message returns on this socket from a remote host. Byte[] receivedBytes = udpClient.Receive(ref remoteIpEndPoint); //Console.WriteLine("Received form Location thread on port:" + MotoTRBOGW.cfg.locPort_r); Print(receivedBytes, receivedBytes.Length, true); if (receivedBytes.Length > 1) { DecodePacket_Connect_plus(receivedBytes); start_read = true; } Thread.Sleep(100); } catch (Exception ex) { SafeMobileLib.Utils.WriteLine("HandleConnection(): exception " + ex, ConsoleColor.Red); } } else Thread.Sleep(100); } catch (Exception ex) { SafeMobileLib.Utils.WriteLine("Exception in LocationThread: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) } public void DecodePacket_Connect_plus(Byte[] data) { int i = 0, pdata; htCell_t cell = new htCell_t(); cell.lat = ""; cell.lng = ""; cell.di = "0"; cell.location_time = DateTime.MinValue; cell.activity_time = DateTime.MinValue; switch (data[0]) { // ----------------------------------------------------------------------------------------------------------------------- case (byte)Document_Identifiers_ENUM.Triggered_Location_Stop_Answer_NoCDT: case (byte)Document_Identifiers_ENUM.Triggered_Location_Answer_NoCDT: /* if (data[0] == (byte)Document_Identifiers_ENUM.Triggered_Location_Stop_Answer_NoCDT) Console.WriteLine(Document_Identifiers_ENUM.Triggered_Location_Stop_Answer_NoCDT); else Console.WriteLine(Document_Identifiers_ENUM.Triggered_Location_Answer_NoCDT); */ pdata = (int)data[1]; //Console.WriteLine("Length =" + pdata + "(0x" + pdata.ToString("X") + ")"); for (i = 2; i < data[1] + 2; i++) { switch (data[i]) { case (byte)Common_Element_Tokens_ENUM.request_id: //Console.WriteLine(Common_Element_Tokens_ENUM.request_id + ": " + Byte2String(data, i + 1, 5)); i += 5; break; case (byte)Report_Messages_Tokens_ENUM.result: case (byte)Report_Messages_Tokens_ENUM.result2: //Console.WriteLine("Result: " + Byte2String(data, i + 1, 1)); if (data[i + 1] != 0) { Console.WriteLine("Error = " + ProcessError(data[i + 1])); } //Console.WriteLine("OpaqueData: " + Byte2String(data, i + 2, data[1] - i)); i = data[1] + 1; // exit break; case (byte)Report_Messages_Tokens_ENUM.result1: //Console.WriteLine("Result: OK"); break; case (byte)Report_Messages_Tokens_ENUM.SU_IPv4: string suid = ProcessSU_ID(data, i + 1).ToString(); cell.suid = suid; i += 4; Console.Write("SUIDe: " + suid + " ## "); break; } } break; // ----------------------------------------------------------------------------------------------------------------------- case (byte)Document_Identifiers_ENUM.Triggered_Location_Report_NoCDT: case (byte)Document_Identifiers_ENUM.Immediate_Location_Report_NoCDT: { /* if (data[0] == (byte)Document_Identifiers_ENUM.Triggered_Location_Report_NoCDT) Console.WriteLine(Document_Identifiers_ENUM.Triggered_Location_Report_NoCDT); else Console.WriteLine(Document_Identifiers_ENUM.Immediate_Location_Report_NoCDT); */ pdata = (int)data[1]; Boolean parsingError = false; DateTime gps_time = DateTime.MinValue; for (i = 2; i < data[1] + 2; i++) { switch (data[i]) { case (byte)Report_Messages_Tokens_ENUM.point_2d: cell.lat = ProcessLat(data, i + 1, 4).ToString(); cell.lng = ProcessLng(data, i + 1 + 4, 4).ToString(); if (gps_time == DateTime.MinValue) cell.location_time = DateTime.Now.ToUniversalTime(); /* Console.WriteLine("Point_2d: " + data[i].ToString("X")); Console.WriteLine("Lat: " + Byte2String(data, i + 1, 4) + " =" + cell.lat); Console.WriteLine("Lng: " + Byte2String(data, i + 1 + 4, 4) + " =" + cell.lng); */ i += 8; break; case (byte)Report_Messages_Tokens_ENUM.circle_2d: cell.lat = ProcessLat(data, i + 1, 4).ToString(); cell.lng = ProcessLng(data, i + 1 + 4, 4).ToString(); if (gps_time == DateTime.MinValue) cell.location_time = DateTime.Now.ToUniversalTime(); cell.radius = ProcessUFloat2B(data, i + 1 + 8); /* Console.WriteLine("Circle_2d: " + data[i].ToString("X")); Console.WriteLine("Lat: " + Byte2String(data, i + 1, 4) + " =" + cell.lat); Console.WriteLine("Lng: " + Byte2String(data, i + 1 + 4, 4) + " =" + cell.lng); Console.WriteLine("Rad: " + Byte2String(data, i + 1 + 8, 2) + " =" + cell.radius); */ i += 10; break; case (byte)Report_Messages_Tokens_ENUM.circle_3d: case (byte)Report_Messages_Tokens_ENUM.circle_3d1: cell.lat = ProcessLat(data, i + 1, 4).ToString(); cell.lng = ProcessLng(data, i + 1 + 4, 4).ToString(); if (gps_time == DateTime.MinValue) cell.location_time = DateTime.Now.ToUniversalTime(); cell.radius = ProcessUFloat2B(data, i + 1 + 8); /* Console.WriteLine("Circle_3d: " + data[i].ToString("X")); Console.WriteLine("Lat: " + Byte2String(data, i + 1, 4) + " =" + cell.lat); Console.WriteLine("Lng: " + Byte2String(data, i + 1 + 4, 4) + " =" + cell.lng); Console.WriteLine("Rad: " + Byte2String(data, i + 1 + 8, 2) + " =" + cell.radius); Console.WriteLine("Alt: " + Byte2String(data, i + 1 + 10, 2)); Console.WriteLine("Ala: " + Byte2String(data, i + 1 + 12, 2)); */ i += 14; break; case (byte)Report_Messages_Tokens_ENUM.speed_vrt: //!! not tested //Console.WriteLine(Report_Messages_Tokens_ENUM.speed_vrt + ": " + Byte2String(data, i + 1, 2)); i += 2; break; case (byte)Report_Messages_Tokens_ENUM.speed_hor: cell.spd = (ProcessUFloat2B(data, i + 1) * 3.6).ToString(); //Console.WriteLine(Report_Messages_Tokens_ENUM.speed_hor + ": " + Byte2String(data, i + 1, 2) + " =" + cell.spd); i += 2; break; case (byte)Common_Element_Tokens_ENUM.request_id: //Console.WriteLine(Common_Element_Tokens_ENUM.request_id + ": " + Byte2String(data, i + 1, 5)); i += 5; break; case (byte)Report_Messages_Tokens_ENUM.info_time: case (byte)Report_Messages_Tokens_ENUM.info_time1: gps_time = ProcessTime(data, i + 1, 5); //Console.WriteLine(Report_Messages_Tokens_ENUM.info_time + ": " + Byte2String(data, i + 1, 5) + " =" + gps_time); i += 5; break; // RESULTS case (byte)Report_Messages_Tokens_ENUM.result: case (byte)Report_Messages_Tokens_ENUM.result2: //Console.WriteLine("Result: " + Byte2String(data, i + 1, 1)); if (data[i + 1] != 0) { Console.WriteLine("Error = " + ProcessError(data[i + 1])); parsingError = true; } //Console.WriteLine("OpaqueData: " + Byte2String(data, i + 2, data[1] - i)); i = data[1] + 1; // exit break; case (byte)Report_Messages_Tokens_ENUM.result1: //Console.WriteLine("Result: OK"); break; case (byte)Report_Messages_Tokens_ENUM.SU_IPv4: string suid = ProcessSU_ID(data, i + 1).ToString(); cell.suid = suid; Console.Write("SUIDa: " + suid + " ## "); i += 4; break; default: Console.WriteLine("Unknown: 0x" + data[i].ToString("X")); break; } } if (!parsingError) { cell.location_time = gps_time; CPlusGW.DBQueueLocation.PostItem(cell); } } break; // ----------------------------------------------------------------------------------------------------------------------- default: Console.WriteLine("UNDEFINED 0x" + data[0].ToString("X")); break; } } void ProcessCommand(MotoTRBOcmdMsg p_msg) { try { if (p_msg.m_cmd == (byte)MotoTRBOcmd.SET_REPORT_INTERVAL) SendTriggeredLocationRequest(p_msg.m_suid, Convert.ToUInt32(p_msg.m_payload)); } catch (Exception e) { Console.WriteLine("Could not send Location Request to unit"); Console.WriteLine(e.Message); } } public void SendTriggeredLocationRequest(string SUID, uint p_reportSec) { byte[] arr_radioID = Utils.ID2ByteARR("12", SUID); Byte[] sendBytes = { (byte)Document_Identifiers_ENUM.Triggered_Location_Request_NoCDT, 0x10, // length in Bytes (byte)Common_Element_Tokens_ENUM.request_id, 0x04, 0x24, 0x68, 0xAC, 0xE0, (byte)Query_Request_Messages_Tokens_ENUM.SU_IPv4, arr_radioID[0], arr_radioID[1], arr_radioID[2], arr_radioID[3], 0x51, (byte)Query_Request_Messages_Tokens_ENUM.request_speed_hor, (byte)Query_Request_Messages_Tokens_ENUM.periodic_trigger, (byte)Query_Request_Messages_Tokens_ENUM.interval, 0x00, 0x00 //(byte)report_time// in seconds }; try { UdpClient udpClient = new UdpClient(Program.cfg.locPort); udpClient.Connect(Program.cfg.ctrlIP, Program.cfg.locPort); int report_time = (int)p_reportSec; if (report_time < 0x80) { //sendBytes[10] = (byte)report_time; sendBytes[17] = (byte)report_time; } else { sendBytes[1] += 1; // adjust length int process = report_time; // MSB process >>= 7; process &= 0x007F; process |= 0x0080; sendBytes[17] = (byte)process; sendBytes[18] = (byte)(report_time & 0x007F); //LSB } Print(sendBytes, sendBytes.Length, false); udpClient.Client.SendTo(sendBytes, new IPEndPoint(IPAddress.Parse(Program.cfg.ctrlIP), Program.cfg.locPort)); Console.WriteLine("Triggered location request sent to radio ID " + SUID); udpClient.Close(); } catch (Exception ex) { Console.WriteLine("Location Thread SendTriggeredLocationRequest exception: " + ex.ToString()); } } // ------------------------------------------------------------------- // Aux functions // ------------------------------------------------------------------- static public string Byte2String(byte[] data) { string sdata = ""; int i; for (i = 0; i < data.Length; i++) { int ii; ii = (int)data[i]; sdata += "0x" + ii.ToString("X") + " "; } return sdata; } static public string Byte2String(byte[] data, int startIndex, int len) { string sdata = ""; int i; if (startIndex > data.Length) return ""; for (i = startIndex; i < startIndex + len && i < data.Length; i++) { int ii; ii = (int)data[i]; sdata += "0x" + ii.ToString("X") + " "; } return sdata; } static string ProcessError(Byte err) { switch (err) { case (byte)Result_Codes_ENUM.SUCCESS: return "" + Result_Codes_ENUM.SUCCESS; case (byte)Result_Codes_ENUM.UNSUPPORTED_VERSION: return "" + Result_Codes_ENUM.UNSUPPORTED_VERSION; case (byte)Result_Codes_ENUM.SYNTAX_ERROR: return "" + Result_Codes_ENUM.SYNTAX_ERROR; case (byte)Result_Codes_ENUM.PROTOCOL_ELEMENT_NOT_SUPPORTED: return "" + Result_Codes_ENUM.PROTOCOL_ELEMENT_NOT_SUPPORTED; case (byte)Result_Codes_ENUM.PROTOCOL_ELEMENT_VALUE_OUT_OF_RANGE: return "" + Result_Codes_ENUM.PROTOCOL_ELEMENT_VALUE_OUT_OF_RANGE; case (byte)Result_Codes_ENUM.QUERY_INFO_NOT_ATTAINABLE: return "" + Result_Codes_ENUM.QUERY_INFO_NOT_ATTAINABLE; case (byte)Result_Codes_ENUM.NO_SUCH_REQUEST: return "" + Result_Codes_ENUM.NO_SUCH_REQUEST; case (byte)Result_Codes_ENUM.DUPLICATE_REQUEST_ID: return "" + Result_Codes_ENUM.DUPLICATE_REQUEST_ID; } return "Unknown err"; } static public double ProcessUFloat2B(Byte[] data, int startIndex) { int aux = data[startIndex]; aux &= 0xff; int int_part = 0; int i = 0; // get the int part while ((aux & 0x80) != 0) { //Console.Write("<" + aux.ToString("X") + ">"); int_part |= (aux ^ 0x80); int_part <<= 7; i++; aux = data[startIndex + i]; aux &= 0xff; //Console.Write("[" + int_part.ToString("X") + "]"); } //Console.Write("<" + aux.ToString("X") + ">"); int_part |= aux; //Console.Write("[" + int_part.ToString("X") + "]"); // ignore the float part i++; while ((data[startIndex + i] & 0x80) != 0) { //Console.Write("<" + data[startIndex + i] + ">"); i++; } //Console.WriteLine(); return (double)int_part; } static DateTime ProcessTime(Byte[] data, int startIndex, int len) { // (yyyy*2^26) + (MM*2^22) + (DD*2^17) + (hh*2^12) + (mm*2^6) + ss Byte B1 = data[startIndex]; Byte B2 = data[startIndex + 1]; Byte B3 = data[startIndex + 2]; Byte B4 = data[startIndex + 3]; Byte B5 = data[startIndex + 4]; int hh, mm, ss, YY, MM, DD; ss = B5 & 0x3F; // remove first 2b mm = B4 & 0x0F; mm <<= 2; mm |= ((B5 >> 6) & 0x03); hh = B3 & 0x01; hh <<= 4; hh |= ((B4 & 0xf0) >> 4); DD = B3 & 0x3E; DD >>= 1; MM = B2 & 0x03; MM <<= 2; MM |= ((B3 >> 6) & 0x03); YY = B1; YY <<= 6; YY |= ((B2 >> 2) & 0x3F); //Console.WriteLine("YY=" + YY.ToString("X")); //Console.WriteLine("MM=" + MM.ToString("X")); //Console.WriteLine("DD=" + DD.ToString("X")); //Console.WriteLine("hh=" + hh.ToString("X")); //Console.WriteLine("mm=" + mm.ToString("X")); //Console.WriteLine("ss=" + ss.ToString("X")); //SafeMobileLib.Utils.WriteLine("GPSTime : " + YY + "/" + MM + "/" + DD + " " + hh + ":" + mm + ":" + ss); return new DateTime(YY, MM, DD, hh, mm, ss, DateTimeKind.Utc); } static double ProcessLat(Byte[] data, int startIndex, int len) { bool sign = false; if ((data[startIndex] & 0x80) != 0) { sign = true; } ulong l = (ulong)data[startIndex]; if (sign) l ^= 0x80; // remove the sign l <<= 8; l |= (ulong)data[startIndex + 1]; l <<= 8; l |= (ulong)data[startIndex + 2]; l <<= 8; l |= (ulong)data[startIndex + 3]; //Console.WriteLine("lat ulong=0x" + l.ToString("X")); double ld = (double)l; ld *= 90; ld /= 1024; ld /= 1024; ld /= 1024; ld /= 2; if (sign) ld *= -1; return ld; } static double ProcessLng(Byte[] data, int startIndex, int len) { bool sign = false; if ((data[startIndex] & 0x80) != 0) { sign = true; } //Console.WriteLine("data[]=" + data[startIndex].ToString("X") + " sign=" + sign); ulong l = (ulong)data[startIndex]; if (sign) l ^= 0x80; // remove the sign l <<= 8; l |= (ulong)data[startIndex + 1]; l <<= 8; l |= (ulong)data[startIndex + 2]; l <<= 8; l |= (ulong)data[startIndex + 3]; //Console.WriteLine("lng ulong=0x" + l.ToString("X")); double ld = (double)l; ld *= 360; ld /= 1024; ld /= 1024; ld /= 1024; ld /= 4; if (sign) { ld = 180 - ld; ld *= -1; } return ld; } private int ProcessSU_ID(Byte[] data, int startIndex) { Byte B1 = data[startIndex]; Byte B2 = data[startIndex + 1]; Byte B3 = data[startIndex + 2]; Byte B4 = data[startIndex + 3]; int radioID = B4 + B3 * 256 + B2 * 256 * 256; return radioID; } private static 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("--------------------------------------------------------------------------- "); } } }