946 lines
43 KiB
C#
946 lines
43 KiB
C#
using System;
|
|
using System.Net;
|
|
using System.Net.Sockets;
|
|
using System.Threading;
|
|
using MotoRepeater;
|
|
using SafeNetLib;
|
|
|
|
namespace MotoTRBO_SOC
|
|
{
|
|
public class TallysmanReceiveThread
|
|
{
|
|
private static UdpClient udpClient;
|
|
private ushort Port = 0;
|
|
//private GeneralLocationManager locManager;
|
|
|
|
private readonly int READ_TIMEOUT = 8640;
|
|
|
|
public TallysmanReceiveThread(ushort port)
|
|
{
|
|
Port = port;
|
|
Port = 4010;
|
|
//locManager = new GeneralLocationManager(mIP, mPort);
|
|
}
|
|
|
|
public void handleConnection()
|
|
{
|
|
Utils.WriteLine("♥♥♥ Tallysman Receive Thread Started on port " + Port, ConsoleColor.Cyan);
|
|
|
|
udpClient = null;
|
|
try
|
|
{
|
|
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;
|
|
Utils.WriteLine("Tallysman udp client initiated", ConsoleColor.Green);
|
|
|
|
if (OnUDPConnectionChanged == null)
|
|
OnUDPConnectionChanged(true);
|
|
|
|
|
|
//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 Tallysman 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, "Tallysman 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
|
|
{
|
|
// 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();
|
|
int seqNo = receivedBytes[0] * 256 + receivedBytes[1];
|
|
String seqID = TallysmanConfirm.getFromConfirmationQueue(seqNo);
|
|
|
|
Utils.WriteLine("TallysmanReceiveThread received data from radio " + radioID + " [" + seqID + "]", ConsoleColor.Red);
|
|
//Utils.printBytesArray(receivedBytes);
|
|
// process the message
|
|
Byte toreturn = ProcessPacket2(receivedBytes, receivedBytes.Length, radioID.ToString().Trim());
|
|
|
|
/*
|
|
//put information on message bus
|
|
Byte[] toSendMulticast = Utils.createMulticastMessage(233, suid, receivedBytes);
|
|
udpMulticast.Send(toSendMulticast, toSendMulticast.Length);
|
|
Utils.WriteLine("TallysmanReceiveThread successfully sent data to message bus");
|
|
*/
|
|
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, "##### TallysmanThread Exception #########\n" + e.ToString());
|
|
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)
|
|
{
|
|
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Stop the Location UDP client
|
|
/// </summary>
|
|
public void Stop()
|
|
{
|
|
try
|
|
{
|
|
if (udpClient != null)
|
|
{
|
|
udpClient.Close();
|
|
udpClient = null;
|
|
}
|
|
}
|
|
catch (Exception) { }
|
|
}
|
|
|
|
public Byte ProcessPacket2(byte[] data, int len, String imei)
|
|
{
|
|
#region variable declaration
|
|
Byte numberofMessByte = 0;
|
|
String pLat = "0.0", pLong = "0.0";
|
|
Int64 itime70 = 0;
|
|
double iSpeed = 0;
|
|
int altitude = 0;
|
|
#region fields for safenet db
|
|
int bearing = -1;
|
|
int levelOfConfidence = -1;
|
|
int accuracy_horizontal = -1;
|
|
int accuracy_vertical = -1;
|
|
int odometer = -1;
|
|
int vio_status = -1;
|
|
int vio_changed = -1;
|
|
float rssi = -1;
|
|
int vital_id = -1;
|
|
int runtime, idletime = -1;
|
|
int eventTimeSec = -1;
|
|
long eventField = -1;
|
|
string firmware_version = string.Empty;
|
|
double average_speed = 0;
|
|
DateTime eventTime = DateTime.Now;
|
|
DateTime positionTime = DateTime.Now;
|
|
#endregion
|
|
|
|
#region correction length variables
|
|
int start_parse = 0;
|
|
int delta = 0;
|
|
int sum = 0;
|
|
#endregion
|
|
|
|
int[] v = new int[19];
|
|
|
|
int protocol, version, messageLength, messageType,
|
|
TransactionId, UnackedCount, LocationReportLength,
|
|
LogId, EventId;
|
|
|
|
Int32 step = 0;
|
|
#endregion
|
|
|
|
//first 2 bytes are Protocol and Version 0xFA 0x08
|
|
protocol = data[step++];
|
|
version = data[step++];
|
|
#region Message Length
|
|
string sByteMessLength = string.Empty;
|
|
do
|
|
{
|
|
for (int j = 6; j >= 0; j--)
|
|
{
|
|
sByteMessLength += ((int)GetBitsAsByte(data[step], j, 1)).ToString();
|
|
}
|
|
}
|
|
while (GetBitsAsByte(data[step++], 7, 1) == 1);
|
|
messageLength = (int)(Convert.ToInt32(sByteMessLength, 2));
|
|
#endregion
|
|
#region Message Type
|
|
messageType = data[step++];
|
|
#endregion
|
|
#region Transaction ID
|
|
string sBytetrid = string.Empty;
|
|
do
|
|
{
|
|
for (int j = 6; j >= 0; j--)
|
|
{
|
|
sBytetrid += ((int)GetBitsAsByte(data[step], j, 1)).ToString();
|
|
}
|
|
}
|
|
while (GetBitsAsByte(data[step++], 7, 1) == 1);
|
|
TransactionId = (int)(Convert.ToInt32(sBytetrid, 2));
|
|
#endregion
|
|
#region Unacked Count
|
|
string sByteUnkCount = string.Empty;
|
|
do
|
|
{
|
|
for (int j = 6; j >= 0; j--)
|
|
{
|
|
sByteUnkCount += ((int)GetBitsAsByte(data[step], j, 1)).ToString();
|
|
}
|
|
}
|
|
while (GetBitsAsByte(data[step++], 7, 1) == 1);
|
|
UnackedCount = (int)(Convert.ToInt32(sByteUnkCount, 2));
|
|
#endregion
|
|
#region BUNDLE/NORMAL PARSER
|
|
do
|
|
{
|
|
#region Reset Variables
|
|
pLat = pLong = "0.0";
|
|
itime70 = 0;
|
|
iSpeed = 0;
|
|
altitude = 0;
|
|
//fields for safenet db
|
|
bearing = -1;
|
|
levelOfConfidence = -1;
|
|
accuracy_horizontal = -1;
|
|
accuracy_vertical = -1;
|
|
odometer = -1;
|
|
vio_status = -1;
|
|
vio_changed = -1;
|
|
rssi = -1;
|
|
vital_id = -1;
|
|
runtime = idletime = -1;
|
|
eventTimeSec = -1;
|
|
eventField = -1;
|
|
firmware_version = string.Empty;
|
|
average_speed = 0;
|
|
eventTime = DateTime.Now;
|
|
positionTime = DateTime.Now;
|
|
#endregion
|
|
|
|
#region Location Report Length
|
|
string sByteLocRepLength = string.Empty;
|
|
do
|
|
{
|
|
for (int j = 6; j >= 0; j--)
|
|
{
|
|
sByteLocRepLength += ((int)GetBitsAsByte(data[step], j, 1)).ToString();
|
|
}
|
|
}
|
|
while (GetBitsAsByte(data[step++], 7, 1) == 1);
|
|
LocationReportLength = (int)(Convert.ToInt32(sByteLocRepLength, 2));
|
|
start_parse = step;
|
|
#endregion
|
|
//0x82 constant
|
|
step++;
|
|
#region Log ID
|
|
string sByteLogId = string.Empty;
|
|
do
|
|
{
|
|
for (int j = 6; j >= 0; j--)
|
|
{
|
|
sByteLogId += ((int)GetBitsAsByte(data[step], j, 1)).ToString();
|
|
}
|
|
}
|
|
while (GetBitsAsByte(data[step++], 7, 1) == 1);
|
|
LogId = (int)(Convert.ToInt32(sByteLogId, 2));
|
|
#endregion
|
|
#region Event ID
|
|
string sByteEventID = string.Empty;
|
|
do
|
|
{
|
|
for (int j = 6; j >= 0; j--)
|
|
{
|
|
sByteEventID += ((int)GetBitsAsByte(data[step], j, 1)).ToString();
|
|
}
|
|
}
|
|
while (GetBitsAsByte(data[step++], 7, 1) == 1);
|
|
EventId = (int)(Convert.ToInt32(sByteEventID, 2));
|
|
#endregion
|
|
#region Report Form parser
|
|
int count = 0;
|
|
do
|
|
{
|
|
for (int i = 0; i < 7; i++)
|
|
{
|
|
v[count++] = (int)GetBitsAsByte(data[step], i, 1);
|
|
if (count == 19) break;
|
|
}
|
|
}
|
|
while (GetBitsAsByte(data[step++], 7, 1) == 1);
|
|
#endregion
|
|
#region Parse data based on report form's bits
|
|
for (int i = 0; i <= 18; i++)
|
|
{
|
|
if (v[i] == 1)
|
|
{
|
|
switch (i)
|
|
{
|
|
//Property: Type, Form Flag + Name, Fixed/Variable Length, Length(bytes)
|
|
#region Type: Latitude and Longitude, F0 - latitude and longitude, Fixed Length 8 bytes total
|
|
case (int)FS.F0:
|
|
{
|
|
//process LAT
|
|
bool sign = false;
|
|
string hexLatitude = string.Empty;
|
|
if ((data[step] & 0x80) != 0)
|
|
{
|
|
hexLatitude = (data[step++] - 128).ToString("X2");
|
|
sign = true;
|
|
}
|
|
else hexLatitude += data[step++].ToString("X2");
|
|
|
|
for (int j = 0; j < 3; j++)
|
|
{
|
|
hexLatitude += data[step++].ToString("X2");
|
|
}
|
|
long decAgainLatiude = int.Parse(hexLatitude, System.Globalization.NumberStyles.HexNumber);
|
|
double dlat = decAgainLatiude * 90 / (double)Math.Pow(2, 31);
|
|
if (sign) dlat *= -1;
|
|
pLat = Convert.ToString(dlat);
|
|
|
|
//process LONG
|
|
string hexLongitude = string.Empty;
|
|
if ((data[step] & 0x80) != 0)
|
|
{
|
|
hexLongitude = "FFFFFFFF" + (data[step++]).ToString("X2");
|
|
}
|
|
else hexLongitude += data[step++].ToString("X2");
|
|
|
|
for (int j = 0; j < 3; j++)
|
|
{
|
|
hexLongitude += data[step++].ToString("X2");
|
|
}
|
|
long decAgainLongitude = Int64.Parse(hexLongitude, System.Globalization.NumberStyles.HexNumber);
|
|
double dlong = decAgainLongitude * 360 / (double)Math.Pow(2, 32);
|
|
pLong = Convert.ToString(dlong);
|
|
}
|
|
break;
|
|
#endregion
|
|
#region Type: Timestamp, F1 - gps fix time, Fixed Length 5 bytes
|
|
case (int)FS.F1:
|
|
{
|
|
string hexGPS = string.Empty;
|
|
for (int j = 0; j < 5; j++)
|
|
{
|
|
hexGPS += data[step++].ToString("X2");
|
|
}
|
|
decimal decAgainGPS = Int64.Parse(hexGPS, System.Globalization.NumberStyles.HexNumber);
|
|
int year = (int)Decimal.Truncate(decAgainGPS / (decimal)Math.Pow(2, 26));
|
|
decimal modYear = decAgainGPS % (decimal)Math.Pow(2, 26);
|
|
int month = (int)Decimal.Truncate(modYear / (decimal)Math.Pow(2, 22));
|
|
decimal modMonth = modYear % (decimal)Math.Pow(2, 22);
|
|
int day = (int)Decimal.Truncate(modMonth / (decimal)Math.Pow(2, 17));
|
|
decimal modDay = modMonth % (decimal)Math.Pow(2, 17);
|
|
int hour = (int)Decimal.Truncate(modDay / (decimal)Math.Pow(2, 12));
|
|
decimal modHour = modDay % (decimal)Math.Pow(2, 12);
|
|
int minute = (int)Decimal.Truncate(modHour / (decimal)Math.Pow(2, 6));
|
|
int second = (int)(modHour % (decimal)Math.Pow(2, 6));
|
|
|
|
Utils.WriteLine("Tallysman GPS Time : " + hour + ":" + minute + ":" + second, ConsoleColor.Red);
|
|
positionTime = new DateTime(year, month, day, hour, minute, second);
|
|
positionTime = positionTime.ToLocalTime();
|
|
itime70 = (long)positionTime.Subtract(new DateTime(1970, 1, 1, 0, 0, 0)).TotalSeconds;
|
|
}
|
|
break;
|
|
#endregion
|
|
#region Type: Speed, F2 - horizontal speed, F8 - vertical speed, F14 - average speed, Variable Length 1->3 bytes
|
|
case (int)FS.F2:
|
|
case (int)FS.F8:
|
|
case (int)FS.F14:
|
|
{
|
|
double speed = 0;
|
|
string sByte = string.Empty;
|
|
do
|
|
{
|
|
for (int j = 6; j >= 0; j--)
|
|
{
|
|
sByte += ((int)GetBitsAsByte(data[step], j, 1)).ToString();
|
|
}
|
|
}
|
|
while (GetBitsAsByte(data[step++], 7, 1) == 1);
|
|
if (i == (int)FS.F2)
|
|
{
|
|
//meteres per second
|
|
speed = (double)(Convert.ToInt32(sByte, 2)) / 10;
|
|
//transform to km per hour
|
|
speed *= (double)3.6;
|
|
speed = (int)Math.Round(speed);
|
|
}
|
|
switch (i)
|
|
{
|
|
case (int)FS.F2:
|
|
iSpeed = speed;
|
|
break;
|
|
case (int)FS.F8:
|
|
break;
|
|
case (int)FS.F14:
|
|
average_speed = speed;
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
#endregion
|
|
#region Type: Sintvar, F4 - altitude, Variable Length 1->3 bytes
|
|
case (int)FS.F4:
|
|
{
|
|
string sByte = string.Empty;
|
|
bool sign = false;
|
|
do
|
|
{
|
|
for (int j = 6; j >= 0; j--)
|
|
{
|
|
if (GetBitsAsByte(data[step], 7, 1) == 1 && GetBitsAsByte(data[step], j, 1) == 1 && j == 6)
|
|
sign = true;
|
|
else
|
|
sByte += ((int)GetBitsAsByte(data[step], j, 1)).ToString();
|
|
}
|
|
}
|
|
while (GetBitsAsByte(data[step++], 7, 1) == 1);
|
|
altitude = (int)(Convert.ToInt32(sByte, 2));
|
|
if (sign) altitude *= -1;
|
|
}
|
|
break;
|
|
#endregion
|
|
#region Type: Uint8, F5 - confidence level, Fixed Length 1 byte
|
|
case (int)FS.F5:
|
|
levelOfConfidence = data[step++];
|
|
break;
|
|
#endregion
|
|
#region Type: Uint16, F10 - odometer, F17 - RSSI radio signal strength in dBm
|
|
case (int)FS.F10:
|
|
// Odometer on 2 bytes - ignoring
|
|
step += 2;
|
|
break;
|
|
case (int)FS.F17:
|
|
// msb - most significant bit, lsb - least significant bit
|
|
int msb = data[step++];
|
|
int lsb = data[step++];
|
|
rssi = (msb + (lsb * 1000 + 128) / 256000);
|
|
break;
|
|
#endregion
|
|
#region Type: Uint16 F12 - VIO current / VIO changed 4 bytes 2 for current, 2 for changed
|
|
case (int)FS.F12:
|
|
//step += 4;
|
|
{
|
|
//2 bytes for current VIO
|
|
//Hardware VIO 1 Sprite Protocol page 67/68
|
|
int currentVIO = data[step++];
|
|
vio_status = currentVIO;
|
|
//Hardware VIO 2
|
|
step++;
|
|
//2 bytes for changed VIO
|
|
vio_changed = data[step++];
|
|
step++;
|
|
|
|
// raise telemetry event
|
|
if (OnTelemetryReceived != null)
|
|
{
|
|
OnTelemetryReceived(new TelemetryReceivedEventArgs()
|
|
{
|
|
RadioID = imei,
|
|
GPIO = currentVIO + ""
|
|
});
|
|
}
|
|
}
|
|
break;
|
|
#endregion
|
|
#region Type: RTM + ITM
|
|
// F11 - Run time/idle time
|
|
case (int)FS.F11:
|
|
{
|
|
string sByte = string.Empty;
|
|
#region runtime
|
|
//Indicates the run time in minutes. The run time is the current value of a timer that
|
|
//continuously increments whenever a specified input is detected (e.g. ignition-on). The
|
|
//ignition line from the vehicle must be wired to the Sprite.
|
|
do
|
|
{
|
|
for (int j = 6; j >= 0; j--)
|
|
{
|
|
sByte += ((int)GetBitsAsByte(data[step], j, 1)).ToString();
|
|
}
|
|
}
|
|
while (GetBitsAsByte(data[step++], 7, 1) == 1);
|
|
runtime = (int)(Convert.ToInt32(sByte, 2));
|
|
#endregion
|
|
#region idletime
|
|
//Indicates the idle time in minutes. The idle time is the current value of a timer that
|
|
//continuously increments whenever a specified input is detected (e.g. ignition-on) and
|
|
//the unit is not moving (i.e. stopped). The ignition line from the vehicle must be wired to
|
|
//the Sprite.
|
|
sByte = string.Empty;
|
|
do
|
|
{
|
|
for (int j = 6; j >= 0; j--)
|
|
{
|
|
sByte += ((int)GetBitsAsByte(data[step], j, 1)).ToString();
|
|
}
|
|
}
|
|
while (GetBitsAsByte(data[step++], 7, 1) == 1);
|
|
idletime = (int)(Convert.ToInt32(sByte, 2));
|
|
#endregion
|
|
}
|
|
break;
|
|
#endregion
|
|
#region Type: Uintvar, F3, F6, F7, F9, F13, F18
|
|
// F3 - bearing, F6 - horizontal accuracy, F7 - vertical accuracy, F9 - odometer,
|
|
// F13 - event time, F18 - vital ID
|
|
case (int)FS.F3:
|
|
case (int)FS.F6:
|
|
case (int)FS.F7:
|
|
case (int)FS.F9:
|
|
case (int)FS.F13:
|
|
case (int)FS.F18:
|
|
{
|
|
string sByte = string.Empty;
|
|
do
|
|
{
|
|
for (int j = 6; j >= 0; j--)
|
|
{
|
|
sByte += ((int)GetBitsAsByte(data[step], j, 1)).ToString();
|
|
}
|
|
}
|
|
while (GetBitsAsByte(data[step++], 7, 1) == 1);
|
|
switch (i)
|
|
{
|
|
case (int)FS.F3:
|
|
bearing = (int)(Convert.ToInt32(sByte, 2));
|
|
break;
|
|
case (int)FS.F6:
|
|
accuracy_horizontal = (int)(Convert.ToInt32(sByte, 2));
|
|
break;
|
|
case (int)FS.F7:
|
|
accuracy_vertical = (int)(Convert.ToInt32(sByte, 2));
|
|
break;
|
|
case (int)FS.F9:
|
|
odometer = (int)(Convert.ToInt32(sByte, 2));
|
|
break;
|
|
case (int)FS.F13:
|
|
// The number of seconds that have passed since the GPS fix time for the report.
|
|
// If the GPS fix is old, then the GPS fix time will not be the time that the report was generated.
|
|
// This field, in combination with the GPS fix time field, allows the time of the event to be calculated.
|
|
// The GPS fix time should always be requested if the Event time is requested.
|
|
eventTimeSec = (int)(Convert.ToInt32(sByte, 2));
|
|
// add seconds to the position time
|
|
eventTime = positionTime.AddSeconds(eventTimeSec);
|
|
break;
|
|
case (int)FS.F18:
|
|
vital_id = (int)(Convert.ToInt32(sByte, 2));
|
|
break;
|
|
}
|
|
|
|
}
|
|
break;
|
|
#endregion
|
|
#region 4 bytes FS: F15 - event field
|
|
for (int j = 0; j < 3; j++)
|
|
{
|
|
eventField <<= 8;
|
|
eventField |= (Int64)data[step];
|
|
//Console.Write(" 0x" + data[step].ToString("X2"));
|
|
step++;
|
|
}
|
|
#endregion
|
|
#region 6 bytes FS: F16-firmware version, configuration version, configuration update count
|
|
case (int)FS.F16:
|
|
int major_version = data[step++];
|
|
int minor_version = data[step++];
|
|
int micro_version = data[step++];
|
|
firmware_version = string.Format("{0}.{1}.{2}", major_version, minor_version, micro_version);
|
|
step += 3;
|
|
break;
|
|
#endregion
|
|
}
|
|
}
|
|
}
|
|
#endregion
|
|
// check if position is from the inside
|
|
if (levelOfConfidence == 0)
|
|
{
|
|
pLat = "0";
|
|
pLong = "0";
|
|
itime70 = (long)((DateTime.Now).Subtract(new DateTime(1970, 1, 1, 0, 0, 0)).TotalSeconds);
|
|
positionTime = DateTime.Now;
|
|
}
|
|
|
|
|
|
// get the time difference between the GPS Position and the Global Time (which can be an internet time)
|
|
TimeSpan locationDifference = (DateTime.Now).Subtract(positionTime);
|
|
|
|
// if position in the future with more than 2 days
|
|
if (Math.Abs(locationDifference.TotalSeconds) > 172800)
|
|
{
|
|
Utils.WriteLine("Tallysman POSITION DIFFERENCE IS " + locationDifference.Seconds, ConsoleColor.Red);
|
|
positionTime = DateTime.Now;
|
|
itime70 = (long)((DateTime.Now).Subtract(new DateTime(1970, 1, 1, 0, 0, 0)).TotalSeconds);
|
|
}
|
|
|
|
double lat = 0;
|
|
double lng = 0;
|
|
Double.TryParse(pLat, out lat);
|
|
Double.TryParse(pLong, out lng);
|
|
Int64 radioID = 0;
|
|
Int64.TryParse(imei, out radioID);
|
|
|
|
if (OnLocationReceived != null)
|
|
{
|
|
OnLocationReceived(new LocationEventArgs()
|
|
{
|
|
RadioID = radioID,
|
|
GPSTime = itime70,
|
|
Speed = iSpeed,
|
|
Latitude = lat,
|
|
Longitude = lng,
|
|
Altitude = altitude,
|
|
LevelOfConfidence = levelOfConfidence
|
|
});
|
|
}
|
|
|
|
|
|
// trigger the event for when any tallysman event is received
|
|
if (OnTallysmanEventReceived != null)
|
|
{
|
|
OnTallysmanEventReceived(new TallysmanEventArgs()
|
|
{
|
|
Id = LogId,
|
|
EventType = TallysmanEventArgs.TallysmanEventType.GetEventType(EventId),
|
|
LevelOfConfidence = levelOfConfidence,
|
|
Latitude = lat,
|
|
Longitude = lng,
|
|
Altitude = altitude,
|
|
Speed = iSpeed,
|
|
AverageSpeed = average_speed,
|
|
HorizontalAccuracy = accuracy_horizontal,
|
|
VerticalAccuracy = accuracy_vertical,
|
|
Bearing = bearing,
|
|
FirmwareVersion = firmware_version,
|
|
Odometer = odometer,
|
|
RadioID = radioID,
|
|
RSSI = rssi,
|
|
IdleTime = idletime,
|
|
RunTime = runtime,
|
|
GPSFixTime = itime70,
|
|
EventTime = eventTime,
|
|
VioChanged = vio_changed,
|
|
VioStatus = vio_status,
|
|
VitalId = vital_id
|
|
});
|
|
}
|
|
|
|
|
|
sum = LocationReportLength + start_parse;
|
|
delta = sum - step;
|
|
step += delta;
|
|
}
|
|
while (len > step + 1);
|
|
#endregion
|
|
return numberofMessByte;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
/// Gets a specific group of bits as a byte values. This process is created appling a
|
|
/// custom mask and then shifting the remaining bits to right
|
|
/// </summary>
|
|
/// <param name="b">The byte from which the bits will be extracted</param>
|
|
/// <param name="offset">The number of bits which will be skipped from right[LST]. O for no offset</param>
|
|
/// <param name="count">Number of bits which are required</param>
|
|
/// <returns>The byte value of the required bits. This values is generated shifting the bits towards LST</returns>
|
|
public static byte GetBitsAsByte(byte b, int offset, int count)
|
|
{
|
|
return (byte)((b >> offset) & ((1 << count) - 1));
|
|
}
|
|
|
|
public enum FS
|
|
{
|
|
F0 = 0, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10,
|
|
F11, F12, F13, F14, F15, F16, F17, F18
|
|
}
|
|
|
|
|
|
|
|
public delegate void UDPConnectionChangedDelegate(bool isConnected);
|
|
public event UDPConnectionChangedDelegate OnUDPConnectionChanged;
|
|
|
|
|
|
|
|
public delegate void LocationReceived(LocationEventArgs e);
|
|
public event LocationReceived OnLocationReceived;
|
|
|
|
public delegate void TelemetryReceived(TelemetryReceivedEventArgs e);
|
|
public event TelemetryReceived OnTelemetryReceived;
|
|
|
|
public delegate void TallysmanEventReceived(TallysmanEventArgs e);
|
|
public event TallysmanEventReceived OnTallysmanEventReceived;
|
|
|
|
|
|
|
|
|
|
public class TelemetryReceivedEventArgs : EventArgs
|
|
{
|
|
public String RadioID { get; set; }
|
|
public String GPIO { get; set; }
|
|
public String Type { get; set; }
|
|
public Int64 seqID { get; set; }
|
|
|
|
public TelemetryReceivedEventArgs()
|
|
{
|
|
RadioID = "";
|
|
GPIO = "";
|
|
Type = "";
|
|
seqID = 0;
|
|
}
|
|
}
|
|
|
|
public class LocationEventArgs : EventArgs
|
|
{
|
|
public Int64 RadioID { get; set; }
|
|
public Int64 GPSTime { get; set; }
|
|
public Double Speed { get; set; }
|
|
public Double Latitude { get; set; }
|
|
public Double Longitude { get; set; }
|
|
public Double Altitude { get; set; }
|
|
public Double LevelOfConfidence { get; set; }
|
|
public Int64 seqID { get; set; }
|
|
|
|
public LocationEventArgs()
|
|
{
|
|
RadioID = 0;
|
|
GPSTime = Utils.DateTo70Format(DateTime.UtcNow);
|
|
Speed = 0;
|
|
Latitude = 0;
|
|
Longitude = 0;
|
|
Altitude = 0;
|
|
seqID = 0;
|
|
|
|
}
|
|
}
|
|
|
|
public class TallysmanEventArgs : EventArgs
|
|
{
|
|
|
|
public sealed class TallysmanEventType
|
|
{
|
|
|
|
private readonly String name;
|
|
private readonly int value;
|
|
|
|
|
|
public static readonly TallysmanEventType IMMEDIATE = new TallysmanEventType(1, "IMMEDIATE");
|
|
public static readonly TallysmanEventType PTT = new TallysmanEventType(2, "PTT");
|
|
public static readonly TallysmanEventType TURN = new TallysmanEventType(3, "TURN");
|
|
public static readonly TallysmanEventType SPEEDING = new TallysmanEventType(4, "SPEEDING");
|
|
public static readonly TallysmanEventType IGNITION_ON = new TallysmanEventType(5, "IGNITION_ON");
|
|
public static readonly TallysmanEventType IGNITION_OFF = new TallysmanEventType(6, "IGNITION_OFF");
|
|
public static readonly TallysmanEventType RADIO_ON = new TallysmanEventType(7, "RADIO_ON");
|
|
public static readonly TallysmanEventType RADIO_OFF = new TallysmanEventType(8, "RADIO_OFF");
|
|
public static readonly TallysmanEventType STOPPED = new TallysmanEventType(9, "STOPPED");
|
|
public static readonly TallysmanEventType MOVING = new TallysmanEventType(10, "MOVING");
|
|
public static readonly TallysmanEventType GPS_FIX = new TallysmanEventType(11, "GPS_FIX");
|
|
public static readonly TallysmanEventType GPS_NO_FIX = new TallysmanEventType(12, "GPS_NO_FIX");
|
|
public static readonly TallysmanEventType DISTANCE = new TallysmanEventType(13, "DISTANCE");
|
|
public static readonly TallysmanEventType VIO = new TallysmanEventType(14, "VIO");
|
|
public static readonly TallysmanEventType PERIODIC = new TallysmanEventType(15, "PERIODIC");
|
|
public static readonly TallysmanEventType CIRCLE_WAYPOINT_IN = new TallysmanEventType(16, "CIRCLE_WAYPOINT_IN");
|
|
public static readonly TallysmanEventType EMERGENCY = new TallysmanEventType(17, "EMERGENCY");
|
|
public static readonly TallysmanEventType CHANNEL_CHANGED = new TallysmanEventType(18, "CHANNEL_CHANGED");
|
|
public static readonly TallysmanEventType TRACKING = new TallysmanEventType(19, "TRACKING");
|
|
public static readonly TallysmanEventType SAFE_AREA = new TallysmanEventType(20, "SAFE_AREA");
|
|
public static readonly TallysmanEventType RSSI = new TallysmanEventType(21, "RSSI");
|
|
public static readonly TallysmanEventType USER_INPUT = new TallysmanEventType(22, "USER_INPUT");
|
|
public static readonly TallysmanEventType POLYGON_WAYPOINT_IN = new TallysmanEventType(23, "POLYGON_WAYPOINT_IN");
|
|
public static readonly TallysmanEventType POLYGON_WAYPOINT_OUT = new TallysmanEventType(24, "POLYGON_WAYPOINT_OUT");
|
|
public static readonly TallysmanEventType CIRCLE_WAYPOINT_OUT = new TallysmanEventType(25, "CIRCLE_WAYPOINT_OUT");
|
|
public static readonly TallysmanEventType BUS_STOP = new TallysmanEventType(26, "BUS_STOP");
|
|
|
|
private TallysmanEventType(int value, String name)
|
|
{
|
|
this.name = name;
|
|
this.value = value;
|
|
}
|
|
|
|
public static TallysmanEventType GetEventType(int type)
|
|
{
|
|
switch (type)
|
|
{
|
|
case 1: return IMMEDIATE;
|
|
case 2: return PTT;
|
|
case 3: return TURN;
|
|
case 4: return SPEEDING;
|
|
case 5: return IGNITION_ON;
|
|
case 6: return IGNITION_OFF;
|
|
case 7: return RADIO_ON;
|
|
case 8: return RADIO_OFF;
|
|
case 9: return STOPPED;
|
|
case 10: return MOVING;
|
|
case 11: return GPS_FIX;
|
|
case 12: return GPS_NO_FIX;
|
|
case 13: return DISTANCE;
|
|
case 14: return VIO;
|
|
case 15: return PERIODIC;
|
|
case 16: return CIRCLE_WAYPOINT_IN;
|
|
case 17: return EMERGENCY;
|
|
case 18: return CHANNEL_CHANGED;
|
|
case 19: return TRACKING;
|
|
case 20: return SAFE_AREA;
|
|
case 21: return RSSI;
|
|
case 22: return USER_INPUT;
|
|
case 23: return POLYGON_WAYPOINT_IN;
|
|
case 24: return POLYGON_WAYPOINT_OUT;
|
|
case 25: return CIRCLE_WAYPOINT_OUT;
|
|
case 26: return BUS_STOP;
|
|
}
|
|
|
|
return BUS_STOP;
|
|
}
|
|
|
|
public override String ToString()
|
|
{
|
|
return name;
|
|
}
|
|
}
|
|
|
|
public Int64 Id { get; set; }
|
|
public TallysmanEventType EventType { get; set; }
|
|
public Int64 RadioID { get; set; }
|
|
public Double GPSFixTime { get; set; }
|
|
public DateTime EventTime { get; set; }
|
|
public Double Speed { get; set; }
|
|
public Double Latitude { get; set; }
|
|
public Double Longitude { get; set; }
|
|
public Double Altitude { get; set; }
|
|
public Double LevelOfConfidence { get; set; }
|
|
public Double Bearing { get; set; }
|
|
public Double HorizontalAccuracy { get; set; }
|
|
public Double VerticalAccuracy { get; set; }
|
|
public Double Odometer { get; set; }
|
|
public Int64 RunTime { get; set; }
|
|
public Int64 IdleTime { get; set; }
|
|
public Int32 VioStatus { get; set; }
|
|
public Int32 VioChanged { get; set; }
|
|
public Double AverageSpeed { get; set; }
|
|
public Int64 WaypointId { get; set; }
|
|
public String FirmwareVersion { get; set; }
|
|
public Double RSSI { get; set; }
|
|
public Int64 VitalId { get; set; }
|
|
|
|
public TallysmanEventArgs()
|
|
{
|
|
Id = 0;
|
|
EventType = TallysmanEventType.BUS_STOP;
|
|
RadioID = 0;
|
|
GPSFixTime = 0;
|
|
EventTime = DateTime.Now;
|
|
Speed = 0;
|
|
Latitude = 0;
|
|
Longitude = 0;
|
|
Altitude = -1;
|
|
LevelOfConfidence = -1;
|
|
Bearing = -1;
|
|
HorizontalAccuracy = 0;
|
|
VerticalAccuracy = 0;
|
|
Odometer = 0;
|
|
RunTime = 0;
|
|
IdleTime = 0;
|
|
VioStatus = 0;
|
|
VioChanged = 0;
|
|
AverageSpeed = 0;
|
|
WaypointId = 0;
|
|
FirmwareVersion = "";
|
|
RSSI = 0;
|
|
VitalId = 0;
|
|
}
|
|
|
|
public TallysmanMsg GetTallysmanMessage()
|
|
{
|
|
return new TallysmanMsg()
|
|
{
|
|
Id = this.Id,
|
|
EventType = this.EventType.ToString(),
|
|
RadioID = this.RadioID,
|
|
GPSFixTime = this.GPSFixTime,
|
|
EventTime = this.EventTime,
|
|
Speed = this.Speed,
|
|
Latitude = this.Latitude,
|
|
Longitude = this.Longitude,
|
|
Altitude = this.Altitude,
|
|
LevelOfConfidence = this.LevelOfConfidence,
|
|
Bearing = this.Bearing,
|
|
HorizontalAccuracy = this.HorizontalAccuracy,
|
|
VerticalAccuracy = this.VerticalAccuracy,
|
|
Odometer = this.Odometer,
|
|
RunTime = this.RunTime,
|
|
IdleTime = this.IdleTime,
|
|
VioStatus = this.VioStatus,
|
|
VioChanged = this.VioChanged,
|
|
AverageSpeed = this.AverageSpeed,
|
|
WaypointId = this.WaypointId,
|
|
FirmwareVersion = this.FirmwareVersion,
|
|
RSSI = this.RSSI,
|
|
VitalId = this.VitalId
|
|
};
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
}
|