SafeNet/SafeNetLib/LocationDecoder.cs
2021-02-24 13:50:23 +02:00

935 lines
45 KiB
C#

using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
namespace SafeNetLib
{
public class LocationDecoder
{
private int ACCEPTED_LEVEL_OF_CONFIDENCE = 20;
public htCell_t cell;
public byte result;
private string radioID;
public string RadioID
{
get { return radioID; }
set { radioID = value; }
}
public LocationDecoder(string radioID, String[] data)
{
this.radioID = radioID;
try
{
cell = DecodePacket(data);
if (cell.lat.Length == 0) //invalid position
cell.lat = null;
}
catch (Exception e)
{
cell.lat = null;
Console.WriteLine("Error decoding data: " + data);
Console.WriteLine(e.ToString());
}
}
public LocationDecoder(string radioID, byte[] data, bool testmode)
{
this.radioID = radioID;
try
{
if (!testmode)
cell = DecodePacket(data);
else
cell = DecodePacket_Connect_plus(data);
if (cell.lat.Length == 0) //invalid position
cell.lat = null;
}
catch (Exception e)
{
//cell.lat = null;
Console.WriteLine("Error decoding data: " + Byte2String(data));
Console.WriteLine(e.ToString());
}
}
public LocationDecoder(byte[] data)
{
try
{
cell = DecodePacket_Connect_plus(data);
if (cell.lat.Length == 0) //invalid position
cell.lat = null;
}
catch (Exception e)
{
cell.lat = null;
Console.WriteLine("Error decoding data: " + Byte2String(data));
Console.WriteLine(e.ToString());
}
}
public htCell_t DecodePacket(String[] dataString)
{
htCell_t retCell = new htCell_t();
retCell.lat = "";
retCell.lng = "";
retCell.di = "0";
retCell.seq_ID = "";
retCell.seqID = 0;
retCell.isCSBK = false;
retCell.location_time = DateTime.MinValue;
retCell.activity_time = DateTime.MinValue;
System.DateTime dateTime = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
dateTime = dateTime.AddSeconds(long.Parse(dataString[0]));
retCell.location_time = dateTime;
retCell.spd = dataString[1];
retCell.lat = dataString[2];
retCell.lng = dataString[3];
return retCell;
}
public htCell_t DecodePacket(Byte[] data)
{
int i = 0, pdata;
htCell_t cell = new htCell_t();
cell.lat = "";
cell.lng = "";
cell.di = "0";
cell.seq_ID = "";
cell.seqID = 0;
cell.isCSBK = false;
cell.location_time = DateTime.MinValue;
cell.activity_time = DateTime.MinValue;
cell.triggered = false;
cell.level_confidence = -1;
result = (byte)Result_Codes_ENUM.SUCCESS;
switch (data[0])
{
// -----------------------------------------------------------------------------------------------------------------------
case (byte)Document_Identifiers_ENUM.Triggered_Location_Stop_Answer_NoCDT:
case (byte)Document_Identifiers_ENUM.Triggered_Location_Answer_NoCDT:
if (data[0] == (byte)Document_Identifiers_ENUM.Triggered_Location_Stop_Answer_NoCDT)
Utils.ConsWrite(DebugMSG_Type.always, Document_Identifiers_ENUM.Triggered_Location_Stop_Answer_NoCDT + "");
else
Utils.ConsWrite(DebugMSG_Type.always, Document_Identifiers_ENUM.Triggered_Location_Answer_NoCDT + "");
pdata = (int)data[1];
//Console.WriteLine("Length =" + pdata + "(0x" + pdata.ToString("X") + ")");
for (i = 2; i < data[1] + 2; i++)
{
switch (data[i])
{
case (byte)Common_Element_Tokens_ENUM.request_id:
{
int length = (int)data[i + 1];
// CSBK Location has a request ID of 3 Bytes
if (length == 3)
cell.isCSBK = true;
cell.seq_ID = Byte2String(data, i + 2, length) + "";
cell.seqID = Byte2Int64(data, i + 2, length);
//Console.WriteLine(Common_Element_Tokens_ENUM.request_id + ": " + cell.seq_ID);
i = i + 1 + length;
break;
}
case (byte)Report_Messages_Tokens_ENUM.result:
case (byte)Report_Messages_Tokens_ENUM.result2:
Console.WriteLine("Result: " + Byte2String(data, i + 1, 1));
if (data[i + 1] != 0)
{
result = data[i + 1];
Utils.ConsWrite(DebugMSG_Type.ARS, "Location Error = " + ProcessError(data[i + 1]));
}
//Console.WriteLine("OpaqueData: " + Byte2String(data, i + 2, data[1] - i));
i = data[1] + 1; // exit
break;
case (byte)Report_Messages_Tokens_ENUM.result1:
//Console.WriteLine("Result: OK");
break;
}
}
break;
// -----------------------------------------------------------------------------------------------------------------------
case (byte)Document_Identifiers_ENUM.Triggered_Location_Report_NoCDT:
// cell.triggered = true;
case (byte)Document_Identifiers_ENUM.Immediate_Location_Report_NoCDT:
{
if (data[0] == (byte)Document_Identifiers_ENUM.Triggered_Location_Report_NoCDT)
{
cell.triggered = true;
//Utils.ConsWrite(DebugMSG_Type.always, Document_Identifiers_ENUM.Triggered_Location_Report_NoCDT + "");
}
else
{
//Utils.ConsWrite(DebugMSG_Type.always, Document_Identifiers_ENUM.Immediate_Location_Report_NoCDT + "");
}
pdata = (int)data[1];
Boolean parsingError = false;
DateTime gps_time = DateTime.MinValue;
for (i = 2; i < data[1] + 2; i++)
{
switch (data[i])
{
case (byte)Report_Messages_Tokens_ENUM.point_2d:
cell.lat = ProcessLat(data, i + 1, 4).ToString();
cell.lng = ProcessLng(data, i + 1 + 4, 4).ToString();
if (gps_time == DateTime.MinValue)
cell.location_time = DateTime.Now.ToUniversalTime();
//Console.WriteLine("Point_2d: " + data[i].ToString("X"));
//Console.WriteLine("Lat: " + Byte2String(data, i + 1, 4) + " =" + cell.lat);
//Console.WriteLine("Lng: " + Byte2String(data, i + 1 + 4, 4) + " =" + cell.lng);
i += 8;
break;
case (byte)Report_Messages_Tokens_ENUM.circle_2d:
cell.lat = ProcessLat(data, i + 1, 4).ToString();
cell.lng = ProcessLng(data, i + 1 + 4, 4).ToString();
if (gps_time == DateTime.MinValue)
cell.location_time = DateTime.Now.ToUniversalTime();
cell.radius = ProcessUFloat2B(data, i + 1 + 8);
//Console.WriteLine("Circle_2d: " + data[i].ToString("X"));
//Console.WriteLine("Lat: " + Byte2String(data, i + 1, 4) + " =" + cell.lat);
//Console.WriteLine("Lng: " + Byte2String(data, i + 1 + 4, 4) + " =" + cell.lng);
//Console.WriteLine("Rad: " + Byte2String(data, i + 1 + 8, 2) + " =" + cell.radius);
i += 10;
break;
case (byte)Report_Messages_Tokens_ENUM.point_3d:
case (byte)Report_Messages_Tokens_ENUM.point_3d1:
{
byte opCode = data[i];
cell.lat = ProcessLat(data, i + 1, 4).ToString();
cell.lng = ProcessLng(data, i + 1 + 4, 4).ToString();
if (gps_time == DateTime.MinValue)
cell.location_time = DateTime.Now.ToUniversalTime();
cell.altitude = (int)ProcessUFloat2B(data, i + 1 + 8);
if (opCode == (byte)Report_Messages_Tokens_ENUM.point_3d1)
{
cell.altitude_accuracy = (int)ProcessUFloat2B(data, i + 1 + 10);
i += 12;
}
else
i += 10;
//Console.WriteLine("Point_2d: " + data[i].ToString("X"));
//Console.WriteLine("Lat: " + Byte2String(data, i + 1, 4) + " =" + cell.lat);
//Console.WriteLine("Lng: " + Byte2String(data, i + 1 + 4, 4) + " =" + cell.lng);
//Console.WriteLine("Alt: " + Byte2String(data, i + 1 + 8, 2) + " =" + cell.altitude);
//Console.WriteLine("Ala: " + Byte2String(data, i + 1 + 10, 2) + " =" + cell.altitude_accuracy);
break;
}
case (byte)Report_Messages_Tokens_ENUM.circle_3d:
case (byte)Report_Messages_Tokens_ENUM.circle_3d1:
{
byte opCode = data[i];
cell.lat = ProcessLat(data, i + 1, 4).ToString();
cell.lng = ProcessLng(data, i + 1 + 4, 4).ToString();
if (gps_time == DateTime.MinValue)
cell.location_time = DateTime.Now.ToUniversalTime();
cell.radius = ProcessUFloat2B(data, i + 1 + 8);
cell.altitude = (int)ProcessUFloat2B(data, i + 1 + 10);
if (opCode == (byte)Report_Messages_Tokens_ENUM.circle_3d1)
{
cell.altitude_accuracy = (int)ProcessUFloat2B(data, i + 1 + 12);
i += 14;
}
else
i += 12;
//Console.WriteLine("Circle_3d: " + data[i].ToString("X"));
//Console.WriteLine("Lat: " + Byte2String(data, i + 1, 4) + " =" + cell.lat);
//Console.WriteLine("Lng: " + Byte2String(data, i + 1 + 4, 4) + " =" + cell.lng);
//Console.WriteLine("Rad: " + Byte2String(data, i + 1 + 8, 2) + " =" + cell.radius);
//Console.WriteLine("Alt: " + Byte2String(data, i + 1 + 10, 2) + " =" + cell.altitude);
//Console.WriteLine("Ala: " + Byte2String(data, i + 1 + 12, 2) + " =" + cell.altitude_accuracy);
break;
}
case (byte)Report_Messages_Tokens_ENUM.speed_vrt: //!! not tested
cell.spd_v = Math.Round((ProcessUFloat2B(data, i + 1) * 3.6)).ToString();
Console.WriteLine(Report_Messages_Tokens_ENUM.speed_vrt + ": " + Byte2String(data, i + 1, 2) + " =" + cell.spd_v);
LOGS.LOG("speed_ver : " + Byte2String(data, i + 1, 2) + " = " + cell.spd_v);
i += 2;
break;
case (byte)Report_Messages_Tokens_ENUM.speed_hor:
cell.spd = Math.Round((ProcessUFloat2B(data, i + 1) * 3.6)).ToString();
Console.WriteLine(Report_Messages_Tokens_ENUM.speed_hor + ": " + Byte2String(data, i + 1, 2) + " =" + cell.spd);
LOGS.LOG("speed_hor : " + Byte2String(data, i + 1, 2) + " = " + cell.spd);
i += 2;
break;
case (byte)Report_Messages_Tokens_ENUM.lev_conf: //!! not tested
cell.level_confidence = (int)data[i + 1];
//Console.WriteLine(Report_Messages_Tokens_ENUM.lev_conf + ": " + Byte2String(data, i + 1, 1) + " =" + cell.level_confidence) ;
i += 1;
break;
case (byte)Common_Element_Tokens_ENUM.request_id:
{
int length = (int)data[i + 1];
// CSBK Location has a request ID of 3 Bytes
if (length == 3)
cell.isCSBK = true;
cell.seq_ID = Byte2String(data, i + 2, length) + "";
cell.seqID = Byte2Int64(data, i + 2, length);
//Console.WriteLine(Common_Element_Tokens_ENUM.request_id + ": " + cell.seq_ID);
i = i + 1 + length;
break;
}
//cell.seq_ID = Byte2Int64(data, i + 2, 5)+"";
//Console.WriteLine(Common_Element_Tokens_ENUM.request_id + ": " + (cell.seq_ID = Byte2String(data, i + 1, 5) + ""));
//Console.WriteLine(Common_Element_Tokens_ENUM.request_id + ": " + (cell.seq_ID = Byte2Int64(data, i + 2, 5)+""));
//i += 5;
//break;
case (byte)Report_Messages_Tokens_ENUM.info_time:
case (byte)Report_Messages_Tokens_ENUM.info_time1:
gps_time = ProcessTime(data, i + 1, 5);
Console.WriteLine(Report_Messages_Tokens_ENUM.info_time + ": " + Byte2String(data, i + 1, 5) + " =" + gps_time);
i += 5;
break;
// RESULTS
case (byte)Report_Messages_Tokens_ENUM.result:
case (byte)Report_Messages_Tokens_ENUM.result2:
//Console.WriteLine("Result: " + Byte2String(data, i + 1, 1));
// fix case when subscriber is inside and sends more data than normal, so the parsing is messed up
// and in some cases the altitude contains 0x37 = result
if (cell.lat.Length > 0)
break;
if (data[i + 1] != 0)
{
result = data[i + 1];
if (data[i + 1] == (byte)Result_Codes_ENUM.QUERY_INFO_NOT_ATTAINABLE ||
data[i + 1] == (byte)Result_Codes_ENUM.QUERY_INFO_NOT_CURRENTLY_ATTAINABLE)
{
cell.lat = "0";
cell.lng = "0";
cell.spd = "0";
gps_time = DateTime.UtcNow;
//Console.WriteLine("INFO got QUERY_INFO_NOT_ATTAINABLE ...adding values lat=0,lng=0,time =DateTime.UtcNow");
}
else
{
parsingError = true;
/*
Utils.ConsWrite(DebugMSG_Type.DB, "___________________________");
Utils.ConsWrite(DebugMSG_Type.DB, "Error processing position " + ProcessError(data[i + 1]));
Utils.ConsWrite(DebugMSG_Type.DB, "___________________________");
*/
}
}
//Console.WriteLine("OpaqueData: " + Byte2String(data, i + 2, data[1] - i));
i = data[1] + 1; // exit
break;
case (byte)Report_Messages_Tokens_ENUM.result1:
result = data[i + 1];
//Console.WriteLine("Result: OK");
break;
case (byte)Report_Messages_Tokens_ENUM.direction_hor:
i += 1;
break;
default:
//Console.WriteLine("Unknown: 0x" + data[i].ToString("X"));
break;
}
}
if (!parsingError)
{
cell.location_time = gps_time;
}
}
break;
// -----------------------------------------------------------------------------------------------------------------------
default:
Console.WriteLine("UNDEFINED 0x" + data[0].ToString("X"));
break;
}
if (cell.level_confidence == -1)
{
// message didn't contained any level of confidence information
}
else if (cell.level_confidence < ACCEPTED_LEVEL_OF_CONFIDENCE)
{
cell.lat = "0";
cell.lng = "0";
cell.spd = "0";
cell.location_time = DateTime.UtcNow;
}
return cell;
}
public htCell_t DecodePacket_Connect_plus(Byte[] data)
{
int i = 0, pdata;
htCell_t cell = new htCell_t();
cell.lat = "";
cell.lng = "";
cell.di = "0";
cell.seq_ID = "";
cell.seqID = 0;
cell.isCSBK = false;
cell.location_time = DateTime.MinValue;
cell.activity_time = DateTime.MinValue;
cell.level_confidence = -1;
result = (byte)Result_Codes_ENUM.SUCCESS;
switch (data[0])
{
// -----------------------------------------------------------------------------------------------------------------------
case (byte)Document_Identifiers_ENUM.Triggered_Location_Stop_Answer_NoCDT:
case (byte)Document_Identifiers_ENUM.Triggered_Location_Answer_NoCDT:
if (data[0] == (byte)Document_Identifiers_ENUM.Triggered_Location_Stop_Answer_NoCDT)
Console.WriteLine(Document_Identifiers_ENUM.Triggered_Location_Stop_Answer_NoCDT);
else Console.WriteLine(Document_Identifiers_ENUM.Triggered_Location_Answer_NoCDT);
pdata = (int)data[1];
//Console.WriteLine("Length =" + pdata + "(0x" + pdata.ToString("X") + ")");
for (i = 2; i < data[1] + 2; i++)
{
switch (data[i])
{
case (byte)Common_Element_Tokens_ENUM.request_id:
{
int length = (int)data[i + 1];
// CSBK Location has a request ID of 3 Bytes
if (length == 3)
cell.isCSBK = true;
cell.seq_ID = Byte2String(data, i + 2, length) + "";
cell.seqID = Byte2Int64(data, i + 2, length);
//Console.WriteLine(Common_Element_Tokens_ENUM.request_id + ": " + cell.seq_ID);
i = i + 1 + length;
break;
}
case (byte)Report_Messages_Tokens_ENUM.result:
case (byte)Report_Messages_Tokens_ENUM.result2:
Console.WriteLine("Result: " + Byte2String(data, i + 1, 1));
result = data[i + 1];
if (data[i + 1] != 0)
{
Console.WriteLine("Error = " + ProcessError(data[i + 1]));
}
//Console.WriteLine("OpaqueData: " + Byte2String(data, i + 2, data[1] - i));
i = data[1] + 1; // exit
break;
case (byte)Report_Messages_Tokens_ENUM.result1:
Console.WriteLine("Result: OK");
break;
case (byte)Report_Messages_Tokens_ENUM.SU_IPv4:
radioID = ProcessSU_ID(data, i + 1).ToString();
i += 4;
break;
}
}
break;
// -----------------------------------------------------------------------------------------------------------------------
case (byte)Document_Identifiers_ENUM.Triggered_Location_Report_NoCDT:
case (byte)Document_Identifiers_ENUM.Immediate_Location_Report_NoCDT:
{
if (data[0] == (byte)Document_Identifiers_ENUM.Triggered_Location_Report_NoCDT)
{
cell.triggered = true;
//Console.WriteLine(Document_Identifiers_ENUM.Triggered_Location_Report_NoCDT);
}
else
{
//Console.WriteLine(Document_Identifiers_ENUM.Immediate_Location_Report_NoCDT);
}
pdata = (int)data[1];
Boolean parsingError = false;
DateTime gps_time = DateTime.MinValue;
for (i = 2; i < data[1] + 2; i++)
{
switch (data[i])
{
case (byte)Report_Messages_Tokens_ENUM.point_2d:
cell.lat = ProcessLat(data, i + 1, 4).ToString();
cell.lng = ProcessLng(data, i + 1 + 4, 4).ToString();
if (gps_time == DateTime.MinValue)
cell.location_time = DateTime.Now.ToUniversalTime();
//Console.WriteLine("Point_2d: " + data[i].ToString("X"));
//Console.WriteLine("Lat: " + Byte2String(data, i + 1, 4) + " =" + cell.lat);
//Console.WriteLine("Lng: " + Byte2String(data, i + 1 + 4, 4) + " =" + cell.lng);
i += 8;
break;
case (byte)Report_Messages_Tokens_ENUM.circle_2d:
cell.lat = ProcessLat(data, i + 1, 4).ToString();
cell.lng = ProcessLng(data, i + 1 + 4, 4).ToString();
if (gps_time == DateTime.MinValue)
cell.location_time = DateTime.Now.ToUniversalTime();
cell.radius = ProcessUFloat2B(data, i + 1 + 8);
//Console.WriteLine("Circle_2d: " + data[i].ToString("X"));
//Console.WriteLine("Lat: " + Byte2String(data, i + 1, 4) + " =" + cell.lat);
//Console.WriteLine("Lng: " + Byte2String(data, i + 1 + 4, 4) + " =" + cell.lng);
//Console.WriteLine("Rad: " + Byte2String(data, i + 1 + 8, 2) + " =" + cell.radius);
i += 10;
break;
case (byte)Report_Messages_Tokens_ENUM.point_3d:
case (byte)Report_Messages_Tokens_ENUM.point_3d1:
{
byte opCode = data[i];
cell.lat = ProcessLat(data, i + 1, 4).ToString();
cell.lng = ProcessLng(data, i + 1 + 4, 4).ToString();
if (gps_time == DateTime.MinValue)
cell.location_time = DateTime.Now.ToUniversalTime();
cell.altitude = (int)ProcessUFloat2B(data, i + 1 + 8);
if (opCode == (byte)Report_Messages_Tokens_ENUM.point_3d1)
{
cell.altitude_accuracy = (int)ProcessUFloat2B(data, i + 1 + 10);
i += 12;
}
else
i += 10;
//Console.WriteLine("Point_2d: " + data[i].ToString("X"));
//Console.WriteLine("Lat: " + Byte2String(data, i + 1, 4) + " =" + cell.lat);
//Console.WriteLine("Lng: " + Byte2String(data, i + 1 + 4, 4) + " =" + cell.lng);
//Console.WriteLine("Alt: " + Byte2String(data, i + 1 + 8, 2) + " =" + cell.altitude);
//Console.WriteLine("Ala: " + Byte2String(data, i + 1 + 10, 2) + " =" + cell.altitude_accuracy);
break;
}
case (byte)Report_Messages_Tokens_ENUM.circle_3d:
case (byte)Report_Messages_Tokens_ENUM.circle_3d1:
{
byte opCode = data[i];
cell.lat = ProcessLat(data, i + 1, 4).ToString();
cell.lng = ProcessLng(data, i + 1 + 4, 4).ToString();
if (gps_time == DateTime.MinValue)
cell.location_time = DateTime.Now.ToUniversalTime();
cell.radius = ProcessUFloat2B(data, i + 1 + 8);
cell.altitude = (int)ProcessUFloat2B(data, i + 1 + 10);
if (opCode == (byte)Report_Messages_Tokens_ENUM.circle_3d1)
{
cell.altitude_accuracy = (int)ProcessUFloat2B(data, i + 1 + 12);
i += 14;
}
else
i += 12;
//Console.WriteLine("Circle_3d: " + data[i].ToString("X"));
//Console.WriteLine("Lat: " + Byte2String(data, i + 1, 4) + " =" + cell.lat);
//Console.WriteLine("Lng: " + Byte2String(data, i + 1 + 4, 4) + " =" + cell.lng);
//Console.WriteLine("Rad: " + Byte2String(data, i + 1 + 8, 2) + " =" + cell.radius);
//Console.WriteLine("Alt: " + Byte2String(data, i + 1 + 10, 2) + " =" + cell.altitude);
//Console.WriteLine("Ala: " + Byte2String(data, i + 1 + 12, 2) + " =" + cell.altitude_accuracy);
break;
}
case (byte)Report_Messages_Tokens_ENUM.speed_vrt: //!! not tested
cell.spd_v = ((int)data[i+1] * 3.6).ToString();
Console.WriteLine(Report_Messages_Tokens_ENUM.speed_vrt + ": " + Byte2String(data, i + 1, 2) + " =" + cell.spd_v);
i += 2;
break;
case (byte)Report_Messages_Tokens_ENUM.speed_hor:
cell.spd = Math.Round((ProcessUFloat2B(data, i + 1) * 3.6)).ToString();
Console.WriteLine(Report_Messages_Tokens_ENUM.speed_hor + ": " + Byte2String(data, i + 1, 2) + " =" + cell.spd);
i += 2;
break;
case (byte)Common_Element_Tokens_ENUM.request_id:
{
int length = (int)data[i + 1];
// CSBK Location has a request ID of 3 Bytes
if (length == 3)
cell.isCSBK = true;
cell.seq_ID = Byte2String(data, i + 2, length) + "";
cell.seqID = Byte2Int64(data, i + 2, length);
//Console.WriteLine(Common_Element_Tokens_ENUM.request_id + ": " + cell.seq_ID);
i = i + 1 + length;
break;
}
//cell.seq_ID = Byte2Int64(data, i + 2, 5)+"";
//Console.WriteLine(Common_Element_Tokens_ENUM.request_id + ": " + (cell.seq_ID = Byte2String(data, i + 1, 5) + ""));
//Console.WriteLine(Common_Element_Tokens_ENUM.request_id + ": " + (cell.seq_ID = Byte2Int64(data, i + 2, 5)+""));
//i += 5;
//break;
case (byte)Report_Messages_Tokens_ENUM.lev_conf: //!! not tested
cell.level_confidence = (int)Math.Round((ProcessUFloat2B(data, i + 1)));
Console.WriteLine(Report_Messages_Tokens_ENUM.lev_conf + ": " + Byte2String(data, i + 1, 2) + " =" + cell.level_confidence);
i += 2;
break;
case (byte)Report_Messages_Tokens_ENUM.info_time:
case (byte)Report_Messages_Tokens_ENUM.info_time1:
gps_time = ProcessTime(data, i + 1, 5);
Console.WriteLine(Report_Messages_Tokens_ENUM.info_time + ": " + Byte2String(data, i + 1, 5) + " =" + gps_time);
i += 5;
break;
// RESULTS
case (byte)Report_Messages_Tokens_ENUM.result:
case (byte)Report_Messages_Tokens_ENUM.result2:
//Console.WriteLine("Result: " + Byte2String(data, i + 1, 1));
// fix case when subscriber is inside and sends more data than normal, so the parsing is messed up
// and in some cases the altitude contains 0x37 = result
if (cell.lat.Length > 0)
break;
if (data[i + 1] != 0)
{
result = data[i + 1];
if (data[i + 1] == (byte)Result_Codes_ENUM.QUERY_INFO_NOT_ATTAINABLE)
{
cell.lat = "0";
cell.lng = "0";
cell.spd = "0";
gps_time = DateTime.UtcNow;
//Console.WriteLine("INFO got QUERY_INFO_NOT_ATTAINABLE ...adding values lat=0,lng=0,time =DateTime.UtcNow");
}
else
{
parsingError = true;
Utils.ConsWrite(DebugMSG_Type.DB, "___________________________");
Utils.ConsWrite(DebugMSG_Type.DB, "Error processing position " + ProcessError(data[i + 1]));
Utils.ConsWrite(DebugMSG_Type.DB, "___________________________");
}
}
//Console.WriteLine("OpaqueData: " + Byte2String(data, i + 2, data[1] - i));
i = data[1] + 1; // exit
break;
case (byte)Report_Messages_Tokens_ENUM.result1:
Console.WriteLine("Result: OK");
break;
case (byte)Report_Messages_Tokens_ENUM.SU_IPv4:
radioID = ProcessSU_ID(data, i + 1).ToString();
i += 4;
break;
default:
Console.WriteLine("Unknown: 0x" + data[i].ToString("X"));
break;
}
}
if (!parsingError)
{
cell.location_time = gps_time;
}
}
break;
// -----------------------------------------------------------------------------------------------------------------------
default:
Console.WriteLine("UNDEFINED 0x" + data[0].ToString("X"));
break;
}
if (cell.level_confidence == -1)
{
// message didn't contained any level of confidence information
}
else if (cell.level_confidence < ACCEPTED_LEVEL_OF_CONFIDENCE)
{
cell.lat = "0";
cell.lng = "0";
cell.spd = "0";
cell.location_time = DateTime.UtcNow;
}
return cell;
}
// -------------------------------------------------------------------
// Aux functions
// -------------------------------------------------------------------
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 string Byte2String(byte[] data)
{
string sdata = "";
int i;
try
{
for (i = 0; i < data.Length; i++)
{
int ii;
ii = (int)data[i];
sdata += "0x" + ii.ToString("X") + " ";
}
}
catch (Exception e)
{
Console.WriteLine("Error converting to string!\n"+e.ToString());
}
return sdata;
}
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;
}
/* convert a byte array to the corresponding Int64*/
public Int64 Byte2Int64(byte[] data, int startIndex, int len)
{
Int64 val = 0;
int i = 0, j = len-1;
try
{
for (i = startIndex; i < startIndex + len && i < data.Length; i++)
{
val = val + (int)data[i] * ((Int64)Math.Pow(16, j--));
}
}
catch (Exception ee) { Console.WriteLine("\n" + ee.ToString()); }
return val;
}
private string ProcessError(Byte err)
{
switch (err)
{
case (byte)Result_Codes_ENUM.SUCCESS: return "" + Result_Codes_ENUM.SUCCESS;
case (byte)Result_Codes_ENUM.UNSUPPORTED_VERSION: return "" + Result_Codes_ENUM.UNSUPPORTED_VERSION;
case (byte)Result_Codes_ENUM.SYNTAX_ERROR: return "" + Result_Codes_ENUM.SYNTAX_ERROR;
case (byte)Result_Codes_ENUM.PROTOCOL_ELEMENT_NOT_SUPPORTED: return "" + Result_Codes_ENUM.PROTOCOL_ELEMENT_NOT_SUPPORTED;
case (byte)Result_Codes_ENUM.PROTOCOL_ELEMENT_VALUE_OUT_OF_RANGE: return "" + Result_Codes_ENUM.PROTOCOL_ELEMENT_VALUE_OUT_OF_RANGE;
case (byte)Result_Codes_ENUM.QUERY_INFO_NOT_ATTAINABLE: return "" + Result_Codes_ENUM.QUERY_INFO_NOT_ATTAINABLE;
case (byte)Result_Codes_ENUM.NO_SUCH_REQUEST: return "" + Result_Codes_ENUM.NO_SUCH_REQUEST;
case (byte)Result_Codes_ENUM.DUPLICATE_REQUEST_ID: return "" + Result_Codes_ENUM.DUPLICATE_REQUEST_ID;
}
return "Unknown err";
}
private double ProcessUFloat2B(Byte[] data, int startIndex)
{
int aux = data[startIndex];
aux &= 0xff;
int int_part = 0;
int i = 0;
// get the int part
while ((aux & 0x80) != 0)
{
int_part |= (aux ^ 0x80);
int_part <<= 7;
i++;
aux = data[startIndex + i];
aux &= 0xff;
}
int_part |= aux;
// ignore the float part
i++;
while ((data[startIndex + i] & 0x80) != 0)
{
i++;
}
//Console.WriteLine();
return (double)int_part;
}
/*
private double ProcessUFloat2B(Byte[] data, int startIndex, int endIndex)
{
int aux = data[startIndex];
aux &= 0xff;
int int_part = 0;
int i = 0;
// get the int part
while ((aux & 0x80) != 0)
{
int_part |= (aux ^ 0x80);
int_part <<= 7;
i++;
aux = data[startIndex + i];
aux &= 0xff;
}
int_part |= aux;
// ignore the float part
i++;
while ((data[startIndex + i] & 0x80) != 0)
{
i++;
}
Console.WriteLine();
return (double)int_part;
}*/
private DateTime ProcessTime(Byte[] data, int startIndex, int len)
{
// (yyyy*2^26) + (MM*2^22) + (DD*2^17) + (hh*2^12) + (mm*2^6) + ss
Byte B1 = data[startIndex];
Byte B2 = data[startIndex + 1];
Byte B3 = data[startIndex + 2];
Byte B4 = data[startIndex + 3];
Byte B5 = data[startIndex + 4];
int hh, mm, ss, YY, MM, DD;
ss = B5 & 0x3F; // remove first 2b
mm = B4 & 0x0F;
mm <<= 2;
mm |= ((B5 >> 6) & 0x03);
hh = B3 & 0x01;
hh <<= 4;
hh |= ((B4 & 0xf0) >> 4);
DD = B3 & 0x3E;
DD >>= 1;
MM = B2 & 0x03;
MM <<= 2;
MM |= ((B3 >> 6) & 0x03);
YY = B1;
YY <<= 6;
YY |= ((B2 >> 2) & 0x3F);
//Console.WriteLine("GPSTime : " + YY + "/" + MM + "/" + DD + " " + hh + ":" + mm + ":" + ss);
return new DateTime(YY, MM, DD, hh, mm, ss, DateTimeKind.Utc);
}
private double ProcessLat(Byte[] data, int startIndex, int len)
{
bool sign = false;
if ((data[startIndex] & 0x80) != 0)
{
sign = true;
}
ulong l = (ulong)data[startIndex];
if (sign)
l ^= 0x80; // remove the sign
l <<= 8;
l |= (ulong)data[startIndex + 1];
l <<= 8;
l |= (ulong)data[startIndex + 2];
l <<= 8;
l |= (ulong)data[startIndex + 3];
//Console.WriteLine("lat ulong=0x" + l.ToString("X"));
double ld = (double)l;
ld *= 90;
ld /= 1024;
ld /= 1024;
ld /= 1024;
ld /= 2;
if (sign)
ld *= -1;
return ld;
}
private double ProcessLng(Byte[] data, int startIndex, int len)
{
bool sign = false;
if ((data[startIndex] & 0x80) != 0)
{
sign = true;
}
//Console.WriteLine("data[]=" + data[startIndex].ToString("X") + " sign=" + sign);
ulong l = (ulong)data[startIndex];
if (sign)
l ^= 0x80; // remove the sign
l <<= 8;
l |= (ulong)data[startIndex + 1];
l <<= 8;
l |= (ulong)data[startIndex + 2];
l <<= 8;
l |= (ulong)data[startIndex + 3];
double ld = (double)l;
ld *= 360;
ld /= 1024;
ld /= 1024;
ld /= 1024;
ld /= 4;
if (sign)
{
ld = 180 - ld;
ld *= -1;
}
return ld;
}
private int ProcessSU_ID(Byte[] data, int startIndex)
{
Byte B1 = data[startIndex];
Byte B2 = data[startIndex + 1];
Byte B3 = data[startIndex + 2];
Byte B4 = data[startIndex + 3];
int radioID = B4 + B3 * 256 + B2 * 256 * 256;
return radioID;
}
}
}