|
using System;
using System.Windows.Forms;
using System.IO;
namespace Speaking_Garmin
{
/// <summary>
/// Class that implements the Garmin Protocol.
/// </summary>
public class Garmin
{
#region Variables
Serial.Port serialPort;
private bool received=false;
private bool logging=false;
private bool done=false;
private int q=0;
private int bytesEstimated;
private System.Collections.ArrayList bytesReceived=new System.Collections.ArrayList(100);
#endregion
#region Properties
/// <summary>
/// Estimate percentage already transfered
/// </summary>
public double Progress
{
get
{
return Math.Min((double)(bytesReceived.Count*100)/(double)bytesEstimated,100.0);
}
}
/// <summary>
/// Get bytes received from GPS to save them or whatever
/// </summary>
public System.Collections.ArrayList Bytes
{
get{return bytesReceived;}
}
#endregion
#region Constructors
public Garmin()
{
}
#endregion
#region Public Functions
public System.Collections.ArrayList GetTracks()
{
bytesReceived.Clear();
bytesEstimated=-1;
logging=false;
byte[] sendTracks = {0x10,0x0A,0x02,0x06,0x00,0xEE,0x10,0x03}; /* Ask for tracks */
Serial.BasicPortSettings a=new Serial.BasicPortSettings();
a.BaudRate = Serial.BaudRates.CBR_9600;
serialPort=new Serial.Port("COM1:",a);
serialPort.DataReceived += new Serial.Port.CommEvent(serialPort_DataReceived);
serialPort.OnError += new Serial.Port.CommErrorEvent(OnError);
if(!serialPort.IsOpen)
serialPort.Open();
logging=true;
SendData(sendTracks); /* Ask for tracks */
Application.DoEvents();
System.Threading.Thread.Sleep(200); /* Wait for response */
if(received)
received=false;
else
{
serialPort.Close();
serialPort.Dispose();serialPort=null;
return null;
}
q=Environment.TickCount; /* Keep track of elapsed time */
while(!done)
{
if(Environment.TickCount-q>2000) /* Timeout */
{
serialPort.Close();
serialPort.Dispose();serialPort=null;
return null;
}
Application.DoEvents();
System.Threading.Thread.Sleep(1000);
}
serialPort.Close();
serialPort.Dispose();serialPort=null;
System.Collections.ArrayList retval=new System.Collections.ArrayList(2);
Track tempTrack=null;
System.Collections.ArrayList al=SplitBytes(bytesReceived);
System.Collections.ArrayList command;
int nWaited=-1;
int nReceived=0;
for(int i=0;i<al.Count;i++)
{
command=(System.Collections.ArrayList)al[i];
if(command.Count>=7 && (byte)command[0]==0x10)
{
if((byte)command[1]==0x1B)
{ /* Number of commands to be sent */
nWaited=0;
for(int j=2+(byte)command[2];j>=3;j--)
{
nWaited <<= 8;
nWaited+=(byte)command[j];
}
}
else if((byte)command[1]==0x06)
{ /* OK - Do nothing */
}
else if((byte)command[1]==0x22)
{ /* New point */
++nReceived;;
if(tempTrack!=null)
{
/* Create new point based on received info. */
tempTrack.AddPoint(command);
}
}
else if((byte)command[1]==0x63)
{ /* New track */
++nReceived;
/* Last received track is now done. Add it to the values to be returned */
if(tempTrack!=null)
retval.Add(tempTrack);
/* Create new point based on received info. */
tempTrack=new Track(command);
}
else if((byte)command[0]==0x10 &&
(byte)command[1]==0x0C &&
(byte)command[2]==0x02 &&
(byte)command[3]==0x06 &&
(byte)command[4]==0x00 &&
(byte)command[5]==0xEC &&
(byte)command[6]==0x10 &&
(byte)command[7]==0x03)
{ /* EOF */
/* Last received track is now done. Add it to the values to be returned */
if(tempTrack!=null)
retval.Add(tempTrack);
/* Check if the information received matches what was expected*/
if(nReceived!=nWaited)
MessageBox.Show("Transfer error...\nNumber of commands expected: " + nWaited.ToString() + "\nNumber of commands received: " + nReceived.ToString(),"Error",MessageBoxButtons.OK,MessageBoxIcon.Hand,MessageBoxDefaultButton.Button1);
}
}
else /* command[0] != 0x10 */
{
/* Invalid! */
retval=null;
}
}
return retval;
}
public System.Collections.ArrayList GetTracksFromFile(string filename)
{
bytesReceived.Clear();
FileInfo fi=new FileInfo(filename);
FileStream fs=fi.OpenRead();
byte[] ByteArray=new byte[600000];
int nBytesRead=fs.Read(ByteArray, 0, 600000);
fs.Close();
for(int i=0;i<nBytesRead;i++)
{
bytesReceived.Add(ByteArray[i]); /* Pretend we received data from a GPS device */
}
System.Collections.ArrayList retval=new System.Collections.ArrayList(2);
Track tempTrack=null;
System.Collections.ArrayList al=SplitBytes(bytesReceived);
System.Collections.ArrayList command;
int nWaited=-1;
int nReceived=0;
for(int i=0;i<al.Count;i++)
{
command=(System.Collections.ArrayList)al[i];
if(command.Count>=7 && (byte)command[0]==0x10)
{
if((byte)command[1]==0x1B)
{ /* Number of commands to be sent */
nWaited=0;
for(int j=2+(byte)command[2];j>=3;j--)
{
nWaited <<= 8;
nWaited+=(byte)command[j];
}
}
else if((byte)command[1]==0x06)
{ /* OK - Do nothing */
}
else if((byte)command[1]==0x22)
{ /* New point */
++nReceived;;
if(tempTrack!=null)
{
tempTrack.AddPoint(command);
}
}
else if((byte)command[1]==0x63)
{ /* New track */
++nReceived;
if(tempTrack!=null)
retval.Add(tempTrack);
tempTrack=new Track(command);
}
else if((byte)command[0]==0x10 &&
(byte)command[1]==0x0C &&
(byte)command[2]==0x02 &&
(byte)command[3]==0x06 &&
(byte)command[4]==0x00 &&
(byte)command[5]==0xEC &&
(byte)command[6]==0x10 &&
(byte)command[7]==0x03)
{ /* EOF */
if(tempTrack!=null)
retval.Add(tempTrack);
if(nReceived!=nWaited)
MessageBox.Show("File corrupt...\nNumber of commands expected: " + nWaited.ToString() + "\nNumber of commands received: " + nReceived.ToString(),"Error",MessageBoxButtons.OK,MessageBoxIcon.Hand,MessageBoxDefaultButton.Button1);
}
}
else /* command[0] != 0x10 */
{
retval=null;
}
}
return retval;
}
public void Exit()
{
if(serialPort!=null)
serialPort.Close();
}
#endregion
#region Private Functions
/// <summary>
/// Function called each time data comes in which stores the received bytes
/// </summary>
/// <param name="bytes">byte[] array whose bytes are to be added to the ArrayList receivedBytes</param>
/// <returns></returns>
private bool Append(byte[] bytes)
{
for(int i=0;i<bytes.Length;i++)
{
bytesReceived.Add(bytes[i]);
}
if(bytesEstimated==-1) /* Not initialized yet */
{
if(bytesReceived.Count>=16)
{
System.Collections.ArrayList Data=SplitBytes(bytesReceived);
if( (byte)((System.Collections.ArrayList)Data[1])[0]==0x10 &&
(byte)((System.Collections.ArrayList)Data[1])[1]==0x1B)
{ /* Received number of commands to be sent */
bytesEstimated=0;
for(int j=2+(byte)((System.Collections.ArrayList)Data[1])[2];j>=3;j--)
{
bytesEstimated <<= 8;
bytesEstimated+=(byte)((System.Collections.ArrayList)Data[1])[j];
}
bytesEstimated*=30; /*Estimate each message has 30 bytes average */
}
}
}
return true;
}
/// <summary>
/// Main function in parsing the received bytes, it splits the received bytes into messages
/// </summary>
/// <param name="arrayListBytes">ArrayList filled with elements of type byte which are to be split</param>
/// <returns></returns>
private static System.Collections.ArrayList SplitBytes(System.Collections.ArrayList arrayListBytes)
{
System.Collections.ArrayList retval=new System.Collections.ArrayList(10);
System.Collections.ArrayList tempBytes;
int count=0;
for(int i=0;i<arrayListBytes.Count;i++)
{
if((byte)arrayListBytes[i]==0x10)
{ /* First byte in a message */
tempBytes=new System.Collections.ArrayList(8);
tempBytes.Add(arrayListBytes[i]);
for(int x=i+1;;x++)
{
i=x;
tempBytes.Add(arrayListBytes[x]);
if((byte)arrayListBytes[x]==0x10)
++count;
else if((byte)arrayListBytes[x]==0x03)
{
if(count%2==1) /* If found an even number of 0x10 followed by 0x03 we have to split the message here */
break;
}
else
count=0;
}
retval.Add(tempBytes);
}
}
return retval;
}
/// <summary>
/// Function used to send data through the serial port
/// </summary>
/// <param name="buffer"></param>
/// <returns></returns>
private bool SendData(byte[] buffer)
{
if(serialPort.IsOpen)
serialPort.Output=buffer;
else
return false;
return true;
}
#endregion
#region Events Actions
/// <summary>
/// Response to error event raised by the serial port
/// </summary>
/// <param name="Description">String that contains error specifics</param>
private void OnError(string Description)
{
MessageBox.Show("An error occured during the transfer:\n" + Description,"Error",MessageBoxButtons.OK,MessageBoxIcon.Hand,MessageBoxDefaultButton.Button1);
}
/// <summary>
/// Response to DataReceived event raised by serialPort called each time new data is received
/// </summary>
private void serialPort_DataReceived()
{
q=Environment.TickCount; /* Keep track of the time in order to check for timeouts */
received=true; /* Received data */
if(logging) /* Keep track of data received */
{
byte[] a=serialPort.Input; /* Get what was received */
Append(a); /* Store received bytes */
if(bytesReceived.Count>=8)
if(
(byte)bytesReceived[bytesReceived.Count-8]==0x10 &&
(byte)bytesReceived[bytesReceived.Count-7]==0x0C &&
(byte)bytesReceived[bytesReceived.Count-6]==0x02 &&
(byte)bytesReceived[bytesReceived.Count-5]==0x06 &&
(byte)bytesReceived[bytesReceived.Count-4]==0x00 &&
(byte)bytesReceived[bytesReceived.Count-3]==0xEC &&
(byte)bytesReceived[bytesReceived.Count-2]==0x10 &&
(byte)bytesReceived[bytesReceived.Count-1]==0x03)
{ /* EOF */
done=true; /* Transfer is complete */
logging=false; /* Stop logging */
return;
}
/* Ask for next record as soon as data is received */
SendData(new byte[] {0x10,0x06,0x02,0x22,0x00,0xD6,0x10,0x03});
}
}
#endregion
}
}
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
I am currently 18 years old and since I was very little I've been into computer-programming. Back then I used to play with a Basic compiler and now I am using the most powerful development environments out there for creating games and windows applications in general.