610 lines
29 KiB
C#
610 lines
29 KiB
C#
|
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 SafeMobileLib.MessageDecoders;
|
|||
|
|
|||
|
namespace MotoRepeater
|
|||
|
{
|
|||
|
|
|||
|
class LocationThread
|
|||
|
{
|
|||
|
private static UInt16 port;
|
|||
|
private byte[] data = new byte[1024];
|
|||
|
private static UdpClient udpClient;
|
|||
|
private static byte reqID_lastByte = 0;
|
|||
|
|
|||
|
public static byte REQ_ID = 0xEE;
|
|||
|
|
|||
|
private MotoRepeater_GW repeaterGw;
|
|||
|
|
|||
|
public LocationThread(UInt16 locationPort, MotoRepeater_GW repeaterGw)
|
|||
|
{
|
|||
|
port = locationPort;
|
|||
|
this.repeaterGw = repeaterGw;
|
|||
|
}
|
|||
|
|
|||
|
public void handleConnection()
|
|||
|
{
|
|||
|
Utils.WriteLine("♥♥♥ Location Thread Started on port " + port);
|
|||
|
|
|||
|
try
|
|||
|
{
|
|||
|
udpClient = new UdpClient(port);
|
|||
|
}
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
Utils.WriteLine("Location Thread Error Creating UDP Client: " + ex.ToString(), ConsoleColor.Red);
|
|||
|
}
|
|||
|
|
|||
|
IPEndPoint remoteIpEndPoint = new IPEndPoint(IPAddress.Any, port);
|
|||
|
|
|||
|
while (MotoRepeater_GW.isRunning)
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
//Utils.WriteLine("WAITING FOR INFO ON LOCATION");
|
|||
|
// 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.WriteLine("Location Thread received data from radio " + radioID);
|
|||
|
|
|||
|
|
|||
|
//put information on message bus
|
|||
|
try
|
|||
|
{
|
|||
|
LocationDecoder locDecoder = new LocationDecoder(suid, receivedBytes, true, false);
|
|||
|
|
|||
|
if (locDecoder == null)
|
|||
|
{
|
|||
|
Utils.WriteLine("NULL", ConsoleColor.Yellow);
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
if (locDecoder.result == (byte)Result_Codes_ENUM.SYNTAX_ERROR)
|
|||
|
{
|
|||
|
Utils.WriteLine("SYNTAX_ERROR", ConsoleColor.Yellow);
|
|||
|
}
|
|||
|
else if (locDecoder.result == (byte)Result_Codes_ENUM.PROTOCOL_ELEMENT_NOT_SUPPORTED)
|
|||
|
{
|
|||
|
int requestingInterval = repeaterGw.GetReportingInterval(suid);
|
|||
|
if(requestingInterval < 5)
|
|||
|
{
|
|||
|
Utils.WriteLine("Requesting interval for " + suid + " set to default value : 180 [found: "
|
|||
|
+ requestingInterval + "]", ConsoleColor.DarkMagenta);
|
|||
|
|
|||
|
requestingInterval = 180;
|
|||
|
}
|
|||
|
|
|||
|
Utils.WriteLine("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, requestingInterval))
|
|||
|
// raise the event
|
|||
|
if (OnTriggeredLocationRequest != null)
|
|||
|
OnTriggeredLocationRequest(suid, requestingInterval);
|
|||
|
|
|||
|
}
|
|||
|
// portable stations doesn't support level of confidence
|
|||
|
else
|
|||
|
{
|
|||
|
// stop current Triggered Location Request
|
|||
|
SendTriggeredLocationSTOP(suid, REQ_ID, false);
|
|||
|
Thread p = new Thread(delegate()
|
|||
|
{
|
|||
|
int coun = 0;
|
|||
|
while (MotoRepeater_GW.isRunning && (coun++) < 6)
|
|||
|
{
|
|||
|
|
|||
|
Thread.Sleep(500);
|
|||
|
}
|
|||
|
//https://stackoverflow.com/questions/13120904/mysql-tinyint1-vs-tinyint2-vs-tinyint3-vs-tinyint4
|
|||
|
// send Triggered Location Request which contains the level of confidence
|
|||
|
if (SendTriggeredLocationRequest(suid, requestingInterval))
|
|||
|
if (OnTriggeredLocationRequest != null)
|
|||
|
OnTriggeredLocationRequest(suid, requestingInterval);
|
|||
|
});
|
|||
|
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.result == (byte)Result_Codes_ENUM.QUERY_INFO_NOT_ATTAINABLE
|
|||
|
|| locDecoder.result == (byte)Result_Codes_ENUM.QUERY_INFO_NOT_CURRENTLY_ATTAINABLE)
|
|||
|
;
|
|||
|
//Utils.WriteLine(locDecoder.result + "");
|
|||
|
|
|||
|
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.AddSeconds(MotoRepeater_GW.timeDifference.TotalSeconds)).Subtract(locDecoder.cell.location_time);
|
|||
|
|
|||
|
|
|||
|
Utils.WriteLine("CRT Time is " + DateTime.UtcNow.AddSeconds(MotoRepeater_GW.timeDifference.TotalSeconds).ToString(), ConsoleColor.Cyan);
|
|||
|
Utils.WriteLine("Location Time is " + locDecoder.cell.location_time.ToString(), ConsoleColor.Cyan);
|
|||
|
Utils.WriteLine("Level of Conficence " + locDecoder.cell.level_confidence.ToString(), ConsoleColor.Cyan);
|
|||
|
|
|||
|
/*
|
|||
|
Console.ForegroundColor = ConsoleColor.Red;
|
|||
|
Console.WriteLine("Time GPS " + locDecoder.cell.location_time.ToString());
|
|||
|
Console.ForegroundColor = ConsoleColor.Yellow;
|
|||
|
Console.WriteLine("AppTime " + DateTime.UtcNow.ToString()); ;
|
|||
|
Console.WriteLine("POSITION DIFFERENCE IS " + locationDifference.Seconds);
|
|||
|
Console.ForegroundColor = ConsoleColor.Gray;
|
|||
|
*/
|
|||
|
|
|||
|
|
|||
|
// if position in the future with more than 2 days
|
|||
|
if (Math.Abs(locationDifference.TotalSeconds) > 172800)
|
|||
|
{
|
|||
|
// skip this position
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
String[] toSendString = new String[4];
|
|||
|
toSendString[0] = DateTo70Format(locDecoder.cell.location_time).ToString();
|
|||
|
toSendString[1] = locDecoder.cell.spd.ToString();
|
|||
|
toSendString[2] = locDecoder.cell.lat.ToString();
|
|||
|
toSendString[3] = locDecoder.cell.lng.ToString();
|
|||
|
|
|||
|
int opcode = 0;
|
|||
|
if (locDecoder.cell.triggered)
|
|||
|
{
|
|||
|
//SM.Debug("Location thread->location triggere response");
|
|||
|
opcode = 131;
|
|||
|
Utils.WriteLine(String.Format("»»» Position [{0:0.0000},{1:0.0000}] from {2}", Math.Round(Double.Parse(locDecoder.cell.lat), 4),
|
|||
|
Math.Round(Double.Parse(locDecoder.cell.lng), 4), suid));
|
|||
|
int speed = 0;
|
|||
|
int.TryParse(locDecoder.cell.spd, out speed);
|
|||
|
//Utils.WriteLine("POSITION TIME IS : " + locDecoder.cell.location_time.ToString());
|
|||
|
|
|||
|
LocationEventArgs e = new LocationEventArgs()
|
|||
|
{
|
|||
|
RadioID = Int64.Parse(suid),
|
|||
|
GPSTime = (Int64)locDecoder.cell.location_time.Subtract(new DateTime(1970, 1, 1, 0, 0, 0)).TotalSeconds,
|
|||
|
Speed = speed,
|
|||
|
Latitude = Math.Round(Double.Parse(locDecoder.cell.lat), 4),
|
|||
|
Longitude = Math.Round(Double.Parse(locDecoder.cell.lng), 4),
|
|||
|
Altitude = locDecoder.cell.altitude,
|
|||
|
LevelOfConfidence = locDecoder.cell.level_confidence,
|
|||
|
seqID = locDecoder.cell.seqID
|
|||
|
};
|
|||
|
|
|||
|
OnLocationReceived?.Invoke(e);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
Utils.WriteLine(String.Format("»»» Poll Res [{0:0.0000},{1:0.0000}] from {2} [{3}]", Math.Round(Double.Parse(locDecoder.cell.lat), 4),
|
|||
|
Math.Round(Double.Parse(locDecoder.cell.lng), 4), suid, locDecoder.cell.seq_ID));
|
|||
|
|
|||
|
//Utils.WriteLine("POLL SEQ ID " + locDecoder.cell.seq_ID + " | " + locDecoder.cell.seqID, ConsoleColor.Yellow);
|
|||
|
//SM.Debug("Location thread->location poll response");
|
|||
|
opcode = 231;
|
|||
|
|
|||
|
int speed = 0;
|
|||
|
int.TryParse(locDecoder.cell.spd, out speed);
|
|||
|
|
|||
|
LocationEventArgs e = new LocationEventArgs()
|
|||
|
{
|
|||
|
RadioID = Int64.Parse(suid),
|
|||
|
GPSTime = (Int64)locDecoder.cell.location_time.Subtract(new DateTime(1970, 1, 1, 0, 0, 0)).TotalSeconds,
|
|||
|
Speed = speed,
|
|||
|
Latitude = Math.Round(Double.Parse(locDecoder.cell.lat), 4),
|
|||
|
Longitude = Math.Round(Double.Parse(locDecoder.cell.lng), 4),
|
|||
|
Altitude = locDecoder.cell.altitude,
|
|||
|
LevelOfConfidence = locDecoder.cell.level_confidence,
|
|||
|
seqID = locDecoder.cell.seqID
|
|||
|
};
|
|||
|
|
|||
|
OnPollReceived?.Invoke(e);
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
|
|||
|
Byte[] toSendMulticast = Utils.createLocationMessage(131, suid, toSendString);
|
|||
|
udpMulticast.Send(toSendMulticast, toSendMulticast.Length);
|
|||
|
string str = System.Text.Encoding.ASCII.GetString(toSendMulticast, 0, toSendMulticast.Length);
|
|||
|
//SM.Debug("Location thread successfully sent data to message bus: \n" + str);
|
|||
|
Utils.WriteLine("TX MultiBus Location [" + str.Trim() + "]");
|
|||
|
|
|||
|
*/
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
Utils.WriteLine("Error at parsing location " + ex.ToString(), ConsoleColor.Red);
|
|||
|
Utils.WriteLine(Utils.PrintBytesArray(receivedBytes), ConsoleColor.Red);
|
|||
|
}
|
|||
|
|
|||
|
Thread.Sleep(100);
|
|||
|
}
|
|||
|
catch (Exception e)
|
|||
|
{
|
|||
|
Utils.WriteLine("••• LocationThread Exception " + e.ToString());
|
|||
|
if (MotoRepeater_GW.isRunning)
|
|||
|
{
|
|||
|
Utils.WriteLine("••• Location Thread is restarting...");
|
|||
|
try
|
|||
|
{
|
|||
|
/*
|
|||
|
udpClient = new UdpClient();
|
|||
|
udpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
|
|||
|
udpClient.Client.Bind(new IPEndPoint(IPAddress.Any, port));
|
|||
|
*/
|
|||
|
udpClient = new UdpClient(port);
|
|||
|
}
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
Utils.WriteLine("••• Location Thread Error Creating UDP Client: " + ex.ToString());
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
Utils.WriteLine("Location Thread is getting killed", ConsoleColor.Yellow);
|
|||
|
|
|||
|
// fire event
|
|||
|
OnLocationThreadKilled?.Invoke();
|
|||
|
}
|
|||
|
|
|||
|
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);
|
|||
|
}
|
|||
|
|
|||
|
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,
|
|||
|
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)Report_Messages_Tokens_ENUM.circle_2d, //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 (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.WriteLine("««« Triggered location request [" + report_time + " sec] for " + SUID);
|
|||
|
|
|||
|
return true;
|
|||
|
//locationUdpClient.Close();
|
|||
|
|
|||
|
}
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
Utils.WriteLine("Location Thread SendTriggeredLocationRequest exception: " + ex.ToString());
|
|||
|
}
|
|||
|
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
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, 0x01, 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, 0x01, //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,
|
|||
|
0x1E
|
|||
|
*/
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
/*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.WriteLine("««« Triggered location request [" + report_time + " sec] for " + SUID);
|
|||
|
|
|||
|
Utils.PrintBytesArray(sendBytes);
|
|||
|
|
|||
|
return true;
|
|||
|
//locationUdpClient.Close();
|
|||
|
|
|||
|
}
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
Utils.WriteLine("Location Thread SendTriggeredLocationRequest exception: " + ex.ToString());
|
|||
|
}
|
|||
|
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
#region location with LOC
|
|||
|
|
|||
|
public static bool SendTriggeredLocationRequestWithLOC(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_info2, // 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.WriteLine("««« Triggered location request with altitude [" + report_time + " sec] for " + SUID);
|
|||
|
|
|||
|
return true;
|
|||
|
}
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
Utils.WriteLine("Location Thread SendTriggeredLocationRequestWithLOC exception: " + ex.ToString(), ConsoleColor.Red);
|
|||
|
return false;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
#endregion
|
|||
|
|
|||
|
/*
|
|||
|
*
|
|||
|
*/
|
|||
|
public static void SendPollRequest(string SUID)
|
|||
|
{
|
|||
|
SendPollRequest(SUID, REQ_ID);
|
|||
|
}
|
|||
|
|
|||
|
public static void SendPollRequest(string SUID, byte reqID)
|
|||
|
{
|
|||
|
reqID_lastByte++;
|
|||
|
if (reqID_lastByte > 0xff) reqID_lastByte = 0x00;
|
|||
|
Byte[] sendBytes = { (byte)Document_Identifiers_ENUM.Immediate_Location_Request_NoCDT,
|
|||
|
0x08, // length in Bytes
|
|||
|
(byte)Common_Element_Tokens_ENUM.request_id,
|
|||
|
//0x04, 0x24, 0x68, 0xAC, 0xE0,
|
|||
|
0x04, 0x24, 0x68, 0xAC, reqID,
|
|||
|
|
|||
|
0x51,
|
|||
|
//(byte)Query_Request_Messages_Tokens_ENUM.require_altitude};
|
|||
|
(byte)Query_Request_Messages_Tokens_ENUM.request_speed_hor};
|
|||
|
|
|||
|
/* // improved poll request that I'm using in Safenet Conventional Gateway
|
|||
|
//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.WriteLine("»»» POLL location request for " + SUID + " [" + reqID + "]");
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/// <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, bool isCSBK)
|
|||
|
{
|
|||
|
if (!MotoRepeater_GW.cfg.SEND_LOCATION_STOP)
|
|||
|
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,
|
|||
|
};
|
|||
|
|
|||
|
if(isCSBK)
|
|||
|
{
|
|||
|
sendBytes = new Byte[] { (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.WriteLine("»»» Triggered location STOP request for " + SUID);
|
|||
|
|
|||
|
}
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
Utils.WriteLine("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)
|
|||
|
{
|
|||
|
if (!MotoRepeater_GW.cfg.SEND_LOCATION_STOP)
|
|||
|
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.WriteLine("««« Triggered location STOP request for " + SUID);
|
|||
|
|
|||
|
}
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
Utils.WriteLine("Location Thread SendTriggeredLocationSTOP exception: " + ex.ToString());
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
public void StopLocationThread()
|
|||
|
{
|
|||
|
if (udpClient != null)
|
|||
|
{
|
|||
|
udpClient.Close();
|
|||
|
}
|
|||
|
}
|
|||
|
public delegate void LocationThreadKilled();
|
|||
|
public event LocationThreadKilled OnLocationThreadKilled;
|
|||
|
|
|||
|
public delegate void LocationReceived(LocationEventArgs e);
|
|||
|
public event LocationReceived OnLocationReceived;
|
|||
|
|
|||
|
public delegate void PollReceived(LocationEventArgs e);
|
|||
|
public event PollReceived OnPollReceived;
|
|||
|
|
|||
|
public delegate void TriggeredLocationRequestDEl(String radioID, int reportingInterval);
|
|||
|
public event TriggeredLocationRequestDEl OnTriggeredLocationRequest;
|
|||
|
}
|
|||
|
}
|