Friday, May 15, 2009

A simple GPS reader class

I've been recently involved in a number of projects that require information from the Window Mobile GPS Intermediate Driver. The usage pattern is quite similar in all cases as the application needs to update a window based on the GPS information stream. There are two possible approaches for this: you can use a window timer and poll the GPSID or you can create a worker thread that waits on the GPS stream to wake up and notify the window through a PostMessage call.

The CGps class (download here) is very simple to use. On your window class just declare a member variable of type CGps, like this:

CGps m_gps;

To start receiving GPS data, just call

m_gps.Start(m_hWnd, WM_GPS);

where WM_GPS is a user-defined window message. You can use something like:

#define WM_GPS (WM_USER + 0x654)

Now you need to handle the WM_GPS message in your code (this will be somewhat different if you are using straight API, MFC or WTL). Note that when handling the message, both wParam and lParam are zero - the message works as a simple notification mechanism to let the window class or procedure know that the GPS updated its data. You read the GPS information quite simply:

GPS_POSITION gpsPos;

m_gps.GetPosition(&gpsPos);

To stop the GPS events you can either call Stop() or let the destructor do that for you when the object goes out of scope and is destroyed.

When implementing this class, I had to work around the now-known GPSID API bug. On some devices, the GPSGetPosition API uses a different size for the GPS_POSITION structure (something that has been explained by John Spaith here). The workaround is simple: just feed the thing with a fake buffer and cast it back to a GPS_POSITION. If you look at the implementation, you will see all this trickery at work. But don't worry - it does work!

3 comments:

vincent said...

Don't really understand how to use it. I have tested very quickly and followed your instructions but I never receive the GPS message.
What I don't understand is what is signaling the m_hEventData in GpsReaderLoop()?

vincent said...

Hum, I suppose since you are passing m_hEventData to GPSOpenDevice, GPS layer signals the event but it doesn't seem to work on my device(HTC Touch Cruise).

João Paulo Figueira said...

That's exactly how it is supposed to work, but you must make sure that your GPSID is correctly configured (see in Settings / System / GPS).