SafeNet/MotoTRBO_SOC/LocationThread.cs

756 lines
37 KiB
C#

using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using SafeNetLib;
using System.Collections;
namespace MotoTRBO_SOC
{
public class LocationThread
{
private static int port;
private byte[] data = new byte[1024];
private static UdpClient udpClient;
private static byte reqID_lastByte=0;
/* Poll Handler Section */
private Thread pollRequestHandlerThread;
private Int32 reqID_send = 0x21;
public static byte REQ_ID = 0xEE;
private readonly int READ_TIMEOUT = 8640; // (seconds)
public LocationThread(int locationPort)
{
port = locationPort;
pollRequestHandlerThread = new Thread(new ThreadStart(pollRequestHandler));
pollRequestHandlerThread.Start();
}
private void pollRequestHandler()
{
while (MotoTRBO_GW.running)
{
try
{
MotoTRBOcmdMsg msg = SN_Queues.locationQueue.GetItem(100);
if (msg != null)
{
//Console.WriteLine("SN_Queues.locationQueue.Count:" + SN_Queues.locationQueue.Count);
if (msg.m_cmd == (byte)MotoTRBOcmd.SEND_POLL)
{
// send poll request and add seq_ID to the poll request
ProcessCommand(msg);
// wait for 5 seconds before processing another poll request
Thread.Sleep(5000);
}
else
{
// do nothing for now
}
}
}
catch (Exception)
{
}
}
}
public void handleConnection()
{
Utils.ConsWrite(DebugMSG_Type.DB, "Location Thread - Initialized on port " + port);
try
{
if (udpClient == null)
{
udpClient = new UdpClient(port);
udpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
//udpClient.Client.Bind(new IPEndPoint(IPAddress.Any, port));
udpClient.Client.ReceiveTimeout = 1000 * READ_TIMEOUT;//200000;
if (OnUDPConnectionChanged != null)
OnUDPConnectionChanged(true);
Utils.WriteLine("Location udp client initiated", ConsoleColor.Green);
}
//UpdateLabelEvent("Registered for ARS messages");
}
catch (Exception ex)
{
if (ex.ToString().Contains(" Only one usage of each socket address"))
{
Console.ForegroundColor = ConsoleColor.Red;
Utils.ConsWrite(DebugMSG_Type.always, "UDP Port for Location is already in use. Please try again after fixing the error. \n" + ex.ToString());
Console.ForegroundColor = ConsoleColor.Gray;
//Thread.Sleep(500);
//MessageBox.Show("UDP Port for SMS is already in use. Please try again after fixing the error.", "SMS Error");
//System.Windows.Forms.Application.Exit();
}
else
{
Console.ForegroundColor = ConsoleColor.Red;
//Utils.ConsWrite(DebugMSG_Type.always, "Location UDP Exception: " + ex.ToString());
Console.ForegroundColor = ConsoleColor.Gray;
//MessageBox.Show("Could not create UDP Connection for SMS. Application will now close", "SMS Error");
//System.Windows.Forms.Application.Exit();
}
}
IPEndPoint remoteIpEndPoint = new IPEndPoint(IPAddress.Any, 0);
while (MotoTRBO_GW.running)
{
while (udpClient != null)
{
try
{
// update that the Thread is still running
MotoTRBO_GW.lastPositionThreadUpdate = DateTime.Now;
// Blocks until a message returns on this socket from a remote host.
Byte[] receivedBytes = udpClient.Receive(ref remoteIpEndPoint);
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();
Utils.ConsWrite(DebugMSG_Type.DB, "Location Thread received data from " + radioID);
//Utils.printBytesArray(receivedBytes);
//decode location
try
{
LocationDecoder locDecoder = new LocationDecoder(suid, receivedBytes, false);
if (locDecoder.result == (byte)Result_Codes_ENUM.SYNTAX_ERROR)
{
//SendTriggeredLocationSTOP(suid, REQ_ID);
}
else if (locDecoder.result == (byte)Result_Codes_ENUM.PROTOCOL_ELEMENT_NOT_SUPPORTED)
{
Utils.ConsWrite(DebugMSG_Type.DB, "PROTOCOL_ELEMENT_NOT_SUPPORTED " + (locDecoder.cell.isCSBK ? " [CSBK]" : "[LEV_OF_CONFIDENCE]"));
try
{
// portable station doesn't support CSBK messages
if (locDecoder.cell.isCSBK)
{
// stop current Triggered Location Request
SendTriggeredLocationSTOPCSBK(suid, REQ_ID);
// send Triggered Location Request which contains the level of confidence
if (SendTriggeredLocationRequest(suid, ((SUinfo)SN_Queues.ht_SUInfo[suid]).repInterval))
// raise the event
if (OnTriggeredLocationRequest != null)
OnTriggeredLocationRequest(suid, ((SUinfo)SN_Queues.ht_SUInfo[suid]).repInterval);
}
// portable stations doesn't support level of confidence
else
{
// stop current Triggered Location Request
SendTriggeredLocationSTOP(suid, REQ_ID);
Thread p = new Thread(delegate()
{
int coun = 0;
while (MotoTRBO_GW.running && (coun++) < 6)
{
Thread.Sleep(500);
}
// send Triggered Location Request which contains the level of confidence
if (SendPlainTriggeredLocationRequest(suid, ((SUinfo)SN_Queues.ht_SUInfo[suid]).repInterval))
if (OnTriggeredLocationRequest != null)
OnTriggeredLocationRequest(suid, ((SUinfo)SN_Queues.ht_SUInfo[suid]).repInterval);
});
p.Start();
}
}
catch (Exception)
{
}
}
else if (locDecoder.result == (byte)Result_Codes_ENUM.SUCCESS
|| locDecoder.result == (byte)Result_Codes_ENUM.QUERY_INFO_NOT_ATTAINABLE
|| locDecoder.result == (byte)Result_Codes_ENUM.QUERY_INFO_NOT_CURRENTLY_ATTAINABLE)
{
if (locDecoder.cell.lat != null)
{
// get the time difference between the GPS Position and the Global Time (which can be an internet time)
TimeSpan locationDifference = (DateTime.Now).Subtract(locDecoder.cell.location_time);
// if position in the future with more than 2 days
if (Math.Abs(locationDifference.TotalSeconds) > 172800)
{
Utils.WriteLine("POSITION DIFFERENCE IS " + locationDifference.Seconds, ConsoleColor.Red);
locDecoder.cell.location_time = DateTime.Now;
// skip this position
//continue;
}
String[] toSendString = new String[4];
toSendString[0] = DateTo70Format(locDecoder.cell.location_time).ToString();
// if speed was requested or not
toSendString[1] = locDecoder.cell.spd != null ? locDecoder.cell.spd.ToString() : "0";
toSendString[2] = locDecoder.cell.lat.ToString();
toSendString[3] = locDecoder.cell.lng.ToString();
locDecoder.cell.suid = suid;
try
{
// conver lat and long to double because the DB insert uses double values
locDecoder.cell.d_lat = Double.Parse(locDecoder.cell.lat);
locDecoder.cell.d_lng = Double.Parse(locDecoder.cell.lng);
if (locDecoder.cell.spd == null)
locDecoder.cell.spd = "0";
}
catch (Exception)
{
// could not parse lat and long as a double value
locDecoder.cell.d_lat = 0;
locDecoder.cell.d_lng = 0;
}
// position was reported as usual
if (locDecoder.cell.triggered)
{
//Utils.ConsWrite(DebugMSG_Type.DB, "»»» Position [" + Math.Round(Double.Parse(locDecoder.cell.lat), 4) + "," + Math.Round(Double.Parse(locDecoder.cell.lng), 4) + "] from " + locDecoder.cell.suid);
Utils.ConsWrite(DebugMSG_Type.DB, String.Format("»»» Position [{0:0.0000},{1:0.0000}] from {2}, speed: {3}, speed_vrt {4}", Math.Round(Double.Parse(locDecoder.cell.lat), 4),
Math.Round(Double.Parse(locDecoder.cell.lng), 4), locDecoder.cell.suid, locDecoder.cell.spd != null ? locDecoder.cell.spd : "null", locDecoder.cell.spd_v != null ? locDecoder.cell.spd_v : "null"));
SN_Queues.DBQueueLocation.PostItem(locDecoder.cell);
//ht_location_hash.Add(locDecoder.cell.suid, locDecoder.cell.location_time);
//LOGS.LOG(MotoTRBO_GW.cfg.gw_id + locDecoder.cell.suid + " Trig GPS<lat:" + locDecoder.cell.lat + "><lng:" + locDecoder.cell.lng + ">");
}
// position was generated by a poll request
else
{
Utils.ConsWrite(DebugMSG_Type.DB, String.Format("»»» Poll Res [{0:0.0000},{1:0.0000}] from {2} [{3}], speed :{4}, speed_vrt: {5}", Math.Round(Double.Parse(locDecoder.cell.lat), 4),
Math.Round(Double.Parse(locDecoder.cell.lng), 4), locDecoder.cell.suid, locDecoder.cell.seq_ID, locDecoder.cell.spd != null ? locDecoder.cell.spd : "null", locDecoder.cell.spd_v != null ? locDecoder.cell.spd_v : "null"));
//Utils.ConsWrite(DebugMSG_Type.DB, "Poll seq_ID : " + locDecoder.cell.seq_ID);
try
{
lock (SN_Queues.ht_POLL_List.SyncRoot)
{
foreach (DictionaryEntry item in SN_Queues.ht_POLL_List)
{
//if (((POLLmsg)item.Value).suid == locDecoder.cell.suid)
if (((POLLmsg)item.Value).requestID == locDecoder.cell.seqID)
{
((POLLmsg)item.Value).response = locDecoder.cell.location_time;
((POLLmsg)item.Value).lat = locDecoder.cell.lat;
((POLLmsg)item.Value).lng = locDecoder.cell.lng;
((POLLmsg)item.Value).speed = locDecoder.cell.spd;
SN_Queues.DBQueueLocation.PostItem(locDecoder.cell);
SN_Queues.recvPOLLQueue.PostItem((POLLmsg)item.Value);
//SN_Queues.ht_POLL_List.Remove(item);
//Utils.ConsWrite(DebugMSG_Type.DB, "ADDED POLL TO HASH");
break;
}
}
}
}
catch (Exception ex)
{
Utils.ConsWrite(DebugMSG_Type.always, "ERROR processing poll msg suid:" + locDecoder.cell.suid + " | " + ex.ToString());
}
//SN_Queues.DBQueueLocation.PostItem(locDecoder.cell);
}
// received poll as a response to ARS
if (!locDecoder.cell.triggered && locDecoder.cell.seq_ID.Length == 0)
;
else
// fire event for position received
if (OnLocationReceived != null)
OnLocationReceived(locDecoder.cell);
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
Thread.Sleep(3);
}
catch (Exception e)
{
if (e.ToString().Contains("A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond"))
{
// read timeout has expired. This is a normal behaviour in my case when the udp socket is supposed to have a timout of 5 seconds
}
else
{
Utils.ConsWrite(DebugMSG_Type.DB, "##### LocationThread Exception #########\n" + e.ToString());
udpClient = null;
}
// set udp client to null if I want to recreate the udp client
//udpClient = null;
}
}
if (OnUDPConnectionChanged != null)
OnUDPConnectionChanged(false);
int count = 0;
while (MotoTRBO_GW.running && count < 6)
{
Thread.Sleep(500);
count++;
}
try
{
// here the udpClient should be null so I have to recreate it
udpClient = new UdpClient(port);
udpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
//udpClient.Client.Bind(new IPEndPoint(IPAddress.Any, port));
udpClient.Client.ReceiveTimeout = 1000 * READ_TIMEOUT;
if (OnUDPConnectionChanged != null)
OnUDPConnectionChanged(true);
}
catch (Exception ex)
{
}
}
Utils.ConsWrite(DebugMSG_Type.DB, "##### LocationThread ENDED #########\n");
}
/// <summary>
/// Stop the Location UDP client
/// </summary>
public void Stop()
{
try
{
if (udpClient != null)
{
udpClient.Close();
udpClient = null;
}
}
catch (Exception) { }
}
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;
}
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);
}
/// <summary>
/// Request a field radio to send only GPS and Horizontal speed info at a specific interval
/// </summary>
/// <param name="SUID">Radio ID of the unit</param>
/// <param name="report_time">Time interval in seconds at which the radio has to report it's location</param>
public static bool SendPlainTriggeredLocationRequest(string SUID, int report_time)
{
reqID_lastByte++;
if (reqID_lastByte > 0xfe) reqID_lastByte = 0x00;
Byte[] sendBytes = { (byte)Document_Identifiers_ENUM.Triggered_Location_Request_NoCDT,
0x0B, // length in Bytes
(byte)Common_Element_Tokens_ENUM.request_id,
//0x04, 0x24, 0x68, 0xAC, 0xE0,
//0x04, 0x24, 0x68, 0xAC, 0xEE,//reqID_lastByte,
0x04, 0x00, 0x00, 0x00, REQ_ID,
(byte)Query_Request_Messages_Tokens_ENUM.ret_info1, // location = circle-2d
(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 (report_time < 0x80)
{
//sendBytes[10] = (byte)report_time;
sendBytes[12] = (byte)report_time;
}
else
{
sendBytes[1] += 1; // adjust length
int process = report_time; // MSB
process >>= 7;
process &= 0x007F;
process |= 0x0080;
sendBytes[12] = (byte)process;
sendBytes[13] = (byte)(report_time & 0x007F); //LSB
}
udpClient.Client.SendTo(sendBytes, new IPEndPoint(IPAddress.Parse(Utils.ID2IP("12", SUID)), port));
//Utils.WriteLine("Triggered location request sent to radio ID " + SUID);
Utils.ConsWrite(DebugMSG_Type.DB, "««« Triggered location request [" + report_time + " sec] for " + SUID);
//locationUdpClient.Close();
return true;
}
catch (Exception ex)
{
Utils.ConsWrite(DebugMSG_Type.DB, "Location Thread SendTriggeredLocationRequest exception: " + ex.ToString());
return false;
}
}
/// <summary>
/// Request a field radio to send GPS, H and V speed, Level of Confidence info at a specific interval
/// </summary>
/// <param name="SUID">Radio ID of the unit</param>
/// <param name="report_time">Time interval in seconds at which the radio has to report it's location</param>
public static bool SendTriggeredLocationRequest(string SUID, int report_time)
{
reqID_lastByte++;
if (reqID_lastByte > 0xfe) reqID_lastByte = 0x00;
Byte[] sendBytes = { (byte)Document_Identifiers_ENUM.Triggered_Location_Request_NoCDT,
0x0E, // length in Bytes
(byte)Common_Element_Tokens_ENUM.request_id,
//0x04, 0x24, 0x68, 0xAC, 0xEE,
0x04, 0x00, 0x00, 0x00, REQ_ID,
(byte)Query_Request_Messages_Tokens_ENUM.ret_info1, // location = circle-2d
(byte)Query_Request_Messages_Tokens_ENUM.request_speed_hor, // horizontal speed
(byte)Query_Request_Messages_Tokens_ENUM.request_speed_vrt, // vertical speed
//(byte)Query_Request_Messages_Tokens_ENUM.request_altitude,
//(byte)Query_Request_Messages_Tokens_ENUM.require_altitude_acc,
//(byte)0x0A,
(byte)Query_Request_Messages_Tokens_ENUM.request_lev_conf, // level of confidence
(byte)0x00,
(byte)Query_Request_Messages_Tokens_ENUM.periodic_trigger,
(byte)Query_Request_Messages_Tokens_ENUM.interval,
0x00, 0x00 //(byte)report_time// in seconds
};
try
{
if (report_time < 0x80)
{
//sendBytes[10] = (byte)report_time;
sendBytes[15] = (byte)report_time;
}
else
{
sendBytes[1] += 1; // adjust length
int process = report_time; // MSB
process >>= 7;
process &= 0x007F;
process |= 0x0080;
sendBytes[15] = (byte)process;
sendBytes[16] = (byte)(report_time & 0x007F); //LSB
}
udpClient.Client.SendTo(sendBytes, new IPEndPoint(IPAddress.Parse(Utils.ID2IP("12", SUID)), port));
Utils.ConsWrite(DebugMSG_Type.DB, "««« Triggered location request [" + report_time + " sec] for " + SUID);
return true;
}
catch (Exception ex)
{
Utils.ConsWrite(DebugMSG_Type.DB, "Location Thread SendTriggeredLocationRequest exception: " + ex.ToString());
return false;
}
}
/// <summary>
/// Request a field radio to send GPS, Horizontal speed info at a specific interval, in a CSBK representation
/// </summary>
/// <param name="SUID">Radio ID of the unit</param>
/// <param name="report_time">Time interval in seconds at which the radio has to report it's location</param>
public static bool SendTriggeredLocationRequestCSBK(string SUID, int report_time)
{
Byte[] sendBytes = { //0x05, 0x08, 0x22, 0x03, 0x00, 0x00, 0x01, 0x40, 0x01, 0x41
0x09, 0x0B, 0x22, 0x03, 0x00, 0x00, REQ_ID, 0x40, 0x01, 0x41, 0x34, 0x31, 0x1E
/*(byte)Document_Identifiers_ENUM.Triggered_Location_Request_NoCDT,
0x0D,
(byte)Common_Element_Tokens_ENUM.request_id,
0x03, 0x00, 0x00, 0x03, //reqID_lastByte,
0x52, (byte)Query_Request_Messages_Tokens_ENUM.require_speed_hor,
0x40, 0x01, 0x41, // start csbk
(byte)Query_Request_Messages_Tokens_ENUM.periodic_trigger,
(byte)Query_Request_Messages_Tokens_ENUM.interval,
0x0F*/
};
/*Byte[] sendBytes = { (byte)Document_Identifiers_ENUM.Triggered_Location_Request_NoCDT,
0x0F, // length in Bytes
(byte)Common_Element_Tokens_ENUM.request_id,
//0x04, 0x24, 0x68, 0xAC, 0xE0,
0x03, 0x00, 0x00, 0xEE,//reqID_lastByte,
0x51,
(byte)Query_Request_Messages_Tokens_ENUM.request_speed_hor,
// START OF impl_spec_data
(byte)Query_Request_Messages_Tokens_ENUM.impl_spec_data,
0x01, 0x41, // 0x01 - length, 0x41 - request CSBK and LRRP
(byte)Query_Request_Messages_Tokens_ENUM.periodic_trigger,
(byte)Query_Request_Messages_Tokens_ENUM.interval
};*/
try
{
/*
if (report_time < 0x80)
{
//sendBytes[10] = (byte)report_time;
sendBytes[13] = (byte)report_time;
}
else
{
sendBytes[1] += 1; // adjust length
int process = report_time; // MSB
process >>= 7;
process &= 0x007F;
process |= 0x0080;
sendBytes[13] = (byte)process;
sendBytes[14] = (byte)(report_time & 0x007F); //LSB
}
*/
udpClient.Client.SendTo(sendBytes, new IPEndPoint(IPAddress.Parse(Utils.ID2IP("12", SUID)), port));
//Utils.WriteLine("Triggered location request sent to radio ID " + SUID);
Utils.ConsWrite(DebugMSG_Type.DB, "««« Triggered location request [" + report_time + " sec] for " + SUID);
//Utils.printBytesArray(sendBytes);
//locationUdpClient.Close();
return true;
}
catch (Exception ex)
{
Utils.ConsWrite(DebugMSG_Type.DB, "Location Thread SendTriggeredLocationRequest exception: " + ex.ToString());
return false;
}
}
/// <summary>
/// Request the stop of a Triggered Location from a field radio
/// </summary>
/// <param name="SUID">The field radio ID which needs to stop sending location at a schedule time</param>
/// <param name="reqID">The triggered location ID that needs to be stopped [each field radio can have 4 Triggered Locations]</param>
public static void SendTriggeredLocationSTOP(string SUID, byte reqID)
{
// do not send location stop if not configured in the config file
if (!MotoTRBO_GW.cfg.locationStop)
return;
byte[] arr_radioID = Utils.ID2ByteARR("12", SUID);
Byte[] sendBytes = { (byte)Document_Identifiers_ENUM.Triggered_Location_Stop_Request_NoCDT,
0x06, // length in Bytes
(byte)Common_Element_Tokens_ENUM.request_id,
0x04, 0x00, 0x00, 0x00, reqID,
};
try{
udpClient.Client.SendTo(sendBytes, new IPEndPoint(IPAddress.Parse(Utils.ID2IP("12", SUID)), port));
Utils.ConsWrite(DebugMSG_Type.DB, "««« Triggered location STOP request for " + SUID);
}
catch (Exception ex)
{
Utils.ConsWrite(DebugMSG_Type.DB, "Location Thread SendTriggeredLocationSTOP exception: " + ex.ToString());
}
}
/// <summary>
/// Request the stop of a Triggered CSBK Location from a field radio
/// </summary>
/// <param name="SUID">The field radio ID which needs to stop sending location at a schedule time</param>
/// <param name="reqID">The triggered location ID that needs to be stopped [each field radio can have 4 Triggered Locations]</param>
public static void SendTriggeredLocationSTOPCSBK(string SUID, byte reqID)
{
// do not send location stop if not configured in the config file
if (!MotoTRBO_GW.cfg.locationStop)
return;
byte[] arr_radioID = Utils.ID2ByteARR("12", SUID);
Byte[] sendBytes = { (byte)Document_Identifiers_ENUM.Triggered_Location_Stop_Request_NoCDT,
0x05, // length in Bytes
(byte)Common_Element_Tokens_ENUM.request_id,
0x03, 0x00, 0x00, reqID,
};
try
{
udpClient.Client.SendTo(sendBytes, new IPEndPoint(IPAddress.Parse(Utils.ID2IP("12", SUID)), port));
Utils.ConsWrite(DebugMSG_Type.DB, "««« Triggered location STOP request for " + SUID);
}
catch (Exception ex)
{
Utils.ConsWrite(DebugMSG_Type.DB, "Location Thread SendTriggeredLocationSTOP exception: " + ex.ToString());
}
}
/// <summary>
/// Request a field radio to report immediate its location [also know as poll]
/// </summary>
/// <param name="SUID">The field radio ID which needs to send imeediate its location</param>
/// <param name="reqID">The triggered location ID for this poll request</param>
public static void SendPollRequest(string SUID, Int32 reqID_send)
{
//get reqid bytes
byte[] intBytes = BitConverter.GetBytes(reqID_send);
if (BitConverter.IsLittleEndian)
Array.Reverse(intBytes);
Byte[] sendBytes = { (byte)Document_Identifiers_ENUM.Immediate_Location_Request_NoCDT,
0x0A, // length in Bytes
(byte)Common_Element_Tokens_ENUM.request_id,
//0x04, 0x24, 0x68, 0xAC, 0xE0,
0x04, intBytes[0], intBytes[1], intBytes[2], intBytes[3],
(byte)Query_Request_Messages_Tokens_ENUM.ret_info1,
//(byte)Query_Request_Messages_Tokens_ENUM.require_altitude};
(byte)Query_Request_Messages_Tokens_ENUM.request_speed_hor,
(byte)Query_Request_Messages_Tokens_ENUM.request_lev_conf, // level of confidence
(byte)0x00,};
udpClient.Client.SendTo(sendBytes, new IPEndPoint(IPAddress.Parse(Utils.ID2IP("12", SUID)), port));
Utils.ConsWrite(DebugMSG_Type.DB, "««« POLL location request for " + SUID + " [" + reqID_send + "]");
}
void ProcessCommand(MotoTRBOcmdMsg p_msg)
{
try
{
reqID_send++;
if (reqID_send == Int32.MaxValue)
reqID_send = 1;
p_msg.m_seqID = reqID_send;
p_msg.m_time = DateTime.Now;
if (p_msg.m_cmd == (byte)MotoTRBOcmd.SEND_POLL)
{
SendPollRequest(p_msg.m_suid, reqID_send);
if(OnImmediateLocationRequest != null)
OnImmediateLocationRequest(p_msg.m_suid);
//Utils.ConsWrite(DebugMSG_Type.GPS, "Poll request sent for unit:" + p_msg.m_suid);
lock (SN_Queues.ht_POLL_List.SyncRoot)
{
foreach (DictionaryEntry item in SN_Queues.ht_POLL_List)
{
try
{
if (((POLLmsg)item.Value).suid == p_msg.m_suid && ((POLLmsg)item.Value).DBid.ToString() == p_msg.m_payload)
{
((POLLmsg)item.Value).sent = DateTime.Now.ToUniversalTime();
((POLLmsg)item.Value).requestID = reqID_send;
//Utils.ConsWrite(DebugMSG_Type.DB, "Poll request found in MotoTRBOGW.ht_POLL_List for unit:" + p_msg.m_suid);
//Utils.ConsWrite(DebugMSG_Type.DB, "reqID_send:" + reqID_send);
SN_Queues.sentPOLLQueue.PostItem((POLLmsg)item.Value);
break;
}
}
catch (Exception ex)
{
Utils.ConsWrite(DebugMSG_Type.always, "ERROR in foreach (DictionaryEntry item in SN_Queues.ht_POLL_List):");
Utils.ConsWrite(DebugMSG_Type.always, ex.Message);
}
}
}
}
}
catch (Exception e)
{
Utils.ConsWrite(DebugMSG_Type.always, "Could not send Location Request to unit");
Utils.ConsWrite(DebugMSG_Type.always, e.Message);
}
}
public Boolean isOnline()
{
return udpClient == null ? false : true;
}
public delegate void UDPConnectionChangedDelegate(bool isConnected);
public event UDPConnectionChangedDelegate OnUDPConnectionChanged;
public delegate void LocationReceivedDEl(htCell_t position);
public event LocationReceivedDEl OnLocationReceived;
public delegate void TriggeredLocationRequestDEl(String radioID, int reportingInterval);
public event TriggeredLocationRequestDEl OnTriggeredLocationRequest;
public delegate void ImmediateLocationRequestDEl(String radioID);
public event ImmediateLocationRequestDEl OnImmediateLocationRequest;
}
}