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) { } } } /// /// Stop the Location UDP client /// 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; } /// /// 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 /// /// The byte from which the bits will be extracted /// The number of bits which will be skipped from right[LST]. O for no offset /// Number of bits which are required /// The byte value of the required bits. This values is generated shifting the bits towards LST 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 }; } } } }