|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
|
Announcements
Chapters
Services
Feature Zones
|
IntroductionThis is a simple GPS tracer developed for Window Mobile 2005/2003 on Compact Framework 2.0 SDK. So first of all, you need VisualStudio 2005 and Windows Mobile CE 5 SDK. You can develop it on emulator devices or on a real device. As you can see in that photo, I developed that application on a read device: the great Asus MyPal 636N.
How it works: backgroundThe screenshot above shows that the map generated by this application is very simple. It's only your path, and the application is able to:
You can save and load it, but for now you can't edit or add other text. About application setup, it's very simple: you have only to setup your COM port. This port must be that same port where your NMEA device is attached via Bluetooth, IrDA or Integrate. Personally, I have an Asus MyPal 636N device, so I have the GPS device built-in on COM5. Using the codeIt's basically composed of three main actors, similar to a simple MVC pattern:
FormIt initializes the application; as you can see it's able to run on 240px X 320px devices. public Form1()
{
InitializeComponent();
m_graphics = this.CreateGraphics();
m_mapper = new Mapper(m_graphics, 0, 30, 240, 300);
m_rTh = new reader(m_port);
m_rTh.dataReceived += new reader.DataReceivedEventHandler(parse);
}
The event registered method is called on the public void parse(String readed)
{
if (!m_isDemoMode)
{
m_mapper.parseAndDraw(readed);
}
else
{
Random r = new Random();
String rSecond1 = (int)(r.NextDouble() * 10 - 1) + "" +
(int)(r.NextDouble() * 10 - 1) + "" +
(int)(r.NextDouble() * 10 - 1) + "" +
(int)(r.NextDouble() * 10 - 1);
String rSecond2 = (int)(r.NextDouble() * 10 - 1) + "" +
(int)(r.NextDouble() * 10 - 1) + "" +
(int)(r.NextDouble() * 10 - 1) + "" +
(int)(r.NextDouble() * 10 - 1);
String rPrime1 = (int)(r.NextDouble() * 1 - 1) + "";
String rPrime2 = (int)(r.NextDouble() * 1 - 1) + "";
m_mapper.drawLatLong("434" + rPrime1 + "." + rSecond1,
"0111" + rPrime2 + "." + rSecond2);
}
}
This is the method that starts and stops the private void menuItemRunStop_Click(object sender, EventArgs e)
{
if (m_isRunning)
{
m_rTh.stop();
}
else
{
m_rTh.start();
}
menuItemRunStop.Checked = !menuItemRunStop.Checked;
m_isRunning = !m_isRunning;
}
This is the region that solves problem of panning the map on your touchscreen device. You can enable #region Panning
private Point touch;
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
if (m_mapper != null)
{
m_mapper.moveCenter(touch.X - e.X, touch.Y - e.Y);
m_mapper.draw();//m_mapper.clearAndDraw();
}
touch.X = e.X;
touch.Y = e.Y;
}
private void Form1_MouseDown(object sender, MouseEventArgs e)
{
touch.X = e.X;
touch.Y = e.Y;
}
private void Form1_MouseUp(object sender, MouseEventArgs e)
{
Form1_MouseMove(sender, e);
m_mapper.clearAndDraw();
}
#endregion
ReaderEvent exposed to public delegate void DataReceivedEventHandler(string data);
public event DataReceivedEventHandler dataReceived;
The thread method that reads on serial port: private void methodTh()
{
m_serialPort1.Open();
byte[] buffer= new byte[100];
while (m_run)
{
Thread.Sleep(500);
m_readed = m_serialPort1.ReadLine();
if (m_readed.Length > 0)
{
dataReceived(m_readed);
}
}
}
These methods allow the public void start()
{
if (m_th == null)
{
m_th = new Thread(methodTh);
}
m_run = true;
m_th.Start();
}
public void stop()
{
m_run = false;
Thread.Sleep(500);
m_serialPort1.Close();
if (m_th != null)
{
m_th.Abort();
m_th = null;
}
}
MapperNow follow me through the public void parseAndDraw(string s)
{
string[] Words = s.Split(',');
m_g.FillRectangle(m_bgBrush, new Rectangle(m_clip.X,
m_clip.Y + 5, m_clip.Width, 15));
m_g.DrawString(s, m_font,m_fontBrush, new RectangleF(m_clip.X ,
m_clip.Y + 5, m_clip.Width, 15));
switch (Words[0])
{
case "$GPRMC":
// $GPRMC,170111,A,4338.5810,N,07015.1010,W,000.0,
// 360.0,060199,017.5,W*73
// RMC - Recommended minimum specific GPS/Transit data
if (Words[3].Length > 0 && Words[5].Length > 0)
{
drawLatLong(Words[3], Words[5]);
}
break;
case "$GPGSV":
// $GPGSV,2,1,08,03,17,171,42,06,21,047,44,14,
// 28,251,45,16,25,292,44*71
// GSV - Satellites in view
break;
case "$GPGSA":
// $GPGGA,170111,4338.581,N,07015.101,W,1,
00,2.0,1.1,M,-31.8,M,,*71
//GSA - GPS dilution of precision and active satellites
break;
default:
break;
}
}
The public void drawLatLong(string latitude, string longitude)
{
Point aPoint = new Point();
aPoint.X =
(Convert.ToInt32(latitude.Substring(latitude.Length - 4, 4)));
aPoint.Y =
(Convert.ToInt32(longitude.Substring(longitude.Length - 4, 4)));
aPoint.X +=
(Convert.ToInt32(latitude.Substring(latitude.Length - 7, 2))) * 60;
aPoint.Y +=
(Convert.ToInt32(longitude.Substring(longitude.Length - 7, 2))) * 60;
aPoint.X +=
(Convert.ToInt32(latitude.Substring(latitude.Length - 9, 2))) * 3600;
aPoint.Y +=
(Convert.ToInt32(longitude.Substring(longitude.Length - 9, 2))) * 3600;
m_points.Add(aPoint);
draw();
}
public void draw()
{
float xTo = 0;
float xFrom = 0;
float yTo = 0;
float yFrom = 0;
for (int i = m_drawded; i < m_points.Count; i++)
{
xTo = (m_points[i].X - m_points[0].X) / m_scale + m_center.X;
xFrom = (m_points[i - 1].X -
m_points[0].X) / m_scale + m_center.X;
yTo = (m_points[i].Y - m_points[0].Y) / m_scale + m_center.Y;
yFrom = (m_points[i - 1].Y - m_points[0].Y) /
m_scale + m_center.Y;
m_g.DrawLine(m_linePen, (int)xTo, (int)yTo,
(int)xFrom, (int)yFrom);
m_g.DrawEllipse(m_pointPen,
new Rectangle((int)xFrom - 2,
(int)yFrom - 2, 4, 4));
}
m_g.DrawEllipse(m_lastPointPen,
new Rectangle((int)xTo - 2, (int)yTo - 2, 4, 4));
m_drawded++;
}
At the end, you can see the public void loatPath(String filename)
{
StreamReader sr = new StreamReader(filename);
m_points.Clear();
int n = 0;
Point p = new Point();
while (!sr.EndOfStream)
{
String readed = sr.ReadLine();
p.X = Convert.ToInt32(readed);
readed = sr.ReadLine();
p.Y = Convert.ToInt32(readed);
m_points.Add(p);
n++;
}
m_drawded = 1;
sr.Close();
clearAndDraw();
}
public void savePath(String filename)
{
StreamWriter sw = new StreamWriter(filename);
foreach (Point p in m_points)
{
sw.WriteLine(Convert.ToString(p.X));
sw.WriteLine(Convert.ToString(p.Y));
}
sw.Flush();
sw.Close();
}
Points of interestI know that this is a simple project for a skilled developer, but I want to demonstrate that the device development is very simple with VisualStudio2005 and CompactFramework 2.0. It's my first project on the great CodeProject website, so please contact me if you have any doubts or proposals. I'm always available for collaboration. History
|
||||||||||||||||||||||