Comments
Richard Davies wrote: The UK has a good crop of technology pioneers in cloud computing - for example ElasticHosts, FlexiScale, Flexiant, OnApp - and also some strong government initiatives such as G-Cloud. We will have to see whether this kind of technical leadership converts into swift mass-market adoption or not.
Cloud Computing
Conference & Expo
November 2-4, 2009 NYC
Register Today and SAVE !..
SYS-CON.TV
Today's Top SOA Links


A Location Tracking System Using PowerBuilder, a GPS Receiver, and Microsoft MapPoint
Finding the location of any individual in real time

Did you ever wonder where your kids are driving around on a Saturday night? Perhaps you are a business owner and need to know where your workforce is located on different job sites. With the help of PowerBuilder, a wireless connection, a GPS receiver, and Microsoft MapPoint, you can track the location of any individual in real-time. This article will show you how.

To get things started you will need a few things:

  • PowerBuilder
  • A serial-based GPS receiver (Bluetooth will do)
  • MS MapPoint 2004
  • MS Visual C# (for sockets implementation)
  • A static IP address or a router capable of port forwarding
  • A wireless connection for the client
  • Some time to learn!
Introduction to Client/Server Programming
First, an introduction to socket-based client/server programming: In this project we will write two components. One will be a server to listen for requests on port 1968. The other will be a client that will read information from the GPS receiver and send it to the server. The message the server will receive will be the client's current latitude and longitude. It will then use this information to plot the current location on a map using MS MapPoint.

You may be wondering why it is necessary to use port 1968. The answer is simple: It is not a well-known port, so we are free to use any number we like provided it is less than 2^8. In this case, I choose 1968 because it was the year I was born, but you can choose any number you like.

Determining Your IP Address
The next part of the equation is to get the IP address of the server. One way you can do this is to visit a site called http://whatsmyipaddress.com. This will give you the IP address the outside world uses to communicate with your computer. However, unless you have a static IP address, your server machine will have been assigned a local address by your router that is not accessible to the outside world. To get around this, you will need to set up port forwarding on the router. For example, if I login to my Linksys router, which is usually at 192.168.1.1, I can choose the applications and gaming tab to specify that I would like all requests to port 1968 to go to the machine my server is listening on. And how to do I know that address? Just use ipconfig at a command line. Here is an example so you get the idea.

Writing the Server
The server component is responsible for listening for requests from the client. In order to "listen" for requests, you will need two pieces of information: the IP address of the server machine and the port you wish to listen on. The IP address can be obtained by running ipconfig at a command line, while the port can be anything you want as long as it is not well known, and is less than 2^8. Note, in the example, I have hard-coded in the IP address and port number. However, in a production implementation, you probably want these values to be user-configurable.

To implement our TCP client/server sockets, we have a couple of choices. One is to use the Win32 API; the other is to create a .NET assembly. In this case, I chose the latter. In essence, what we are doing is calling a .NET assembly from PowerBuilder using COM wrappers. What this allows us to do is to create a class using C#, for example, and create a DLL that we can call from PowerBuilder. Wondering how to do that? See Bruce Armstrong's article at http://pbdj.sys-con.com/read/258395.htm for details. However, in terms of the assembly, I will share my C# code with you in Listing 1 but defer the details of creating the assembly to his article.

You may wonder at this point, now that you have created a .NET assembly, how you use it in PowerBuilder. The following code listing shows how I am calling my assembly from PowerBuilder from a ue_postopen event. Notice that I have hard-coded in the IP address and port number. In a production version you would want these to be user-configurable options.

Integer li_Return

    ole_map.object.Units = 1
    ioo_map = ole_map.object.NewMap(1)

    ioo_listner = CREATE OleObject
    li_Return = ioo_Listner.ConnectToNewObject( "DotNetListner.DotNetSocketListner" )

    ioo_listner.ipAddr = "192.168.1.108";
    ioo_listner.portNumber = 1968;

    ioo_listner.Initialize();

Once we have initialized our "socket listener," we will need to retrieve data from the client. We will also need some agreement as to the protocol for the messages it accepts from the client. In this case, I am having the client pass the following information (each separated by a comma): latitude, longitude, user, and current time. For example, here is a sample message that will be received by the server:

42.43608, -89.022857, Chance, 1:22 a.m..

The code for retrieving data from the client is shown below. There are some important points to consider here. One, this is not a multi-threaded application, thus we have the infinite loop. However, I have placed some calls to Yield() to allow for any queued messages to be processed in between data retrievals from the client. Messy, but it works.

Double ldb_lat, ldb_long

do while 1=1
    Yield()
    ioo_Listner.GetData()
    ldb_lat = Double(ioo_Listner.Latitude);
    ldb_long = Double(ioo_Listner.Longitude);
    Yield()
    event post ue_plotdata(ldb_lat, ldb_long)
loop

Finally, once the client has retrieved the current latitude and longitude from the GPS receiver and sent it to the server, we need to plot the current position on the map. There are many mapping solutions out there, from Yahoo! Maps to Google Maps to MS MapPoint. (Figure 1) I choose the latter, primarily because - well, what would happen if your Internet connection went down? There would be no way to make the mapping calls. Given that, the MS MapPoint code for plotting a given latitude and longitude is in Listing 2.

Writing the Client
The client component is responsible for reading information from the GPS receiver and sending it to the server. You will need to decide how often this occurs by programming the timer event. In this case, I chose every five minutes. As far as reading GPS information, this can be done using Win32 API calls that "talk" to the comm port for which the receiver is configured. (Figure 2)

The protocol the receiver uses is called NMEA (for more, see www.gpsinformation.org/dale/nmea.htm). In general, the device sends sentences that describe the current position. Of interest to us is the GPGAA message that includes the current location. NMEA sentences are comma-delimited, so they are prime candidates for easy parsing using an external data window. For this example, I used Ian Thain's NMEA parser, which can be found on Code-Exchange. So, the sequence of events is:

  • Read an NMEA sentence from the GPS receiver
  • Determine if it is GPGAA
  • Convert the data to decimal degrees
  • Send the message described above to the server
First, we need a way to communicate with the GPS server. To do that, we can use some Win32 API calls. Following are their prototypes. Why not just use the built-in PowerBuilder I/O functions such as FileOpen and FileRead? The underlying reason is that PowerBuilder will buffer the data for you (on top of the native buffering that the OS provides). This can be problematic for serial I/O devices.
  • Function Long CreateFile(ref string lpszName, long fdwAccess, long fdwShareMode, long lpsa, long fdwCreate, long fdwAttrsAndFlags, long hTemplateFile) Library "Kernel32.dll"
  • Function Long CloseHandle(Long hObject) Library "Kernel32.dll"
  • Function Long ReadFile(Long hFile, ref string lpBuffer, long nBytesToRead, ref Long & nBytesRead, Long lNull) Library "Kernel32.dll"
  • Function Long WriteFile(Long hFile, ref string lpBuffer, long nBytesToWrite, ref Long & nBytesWritten, LONG lNull) Library "Kernel32.dll"
The next order of business is to see how Ian Thain wrote his object to go about parsing a particular NMEA stream. For that, all we have to do is take a look at the format of an example sentence. Since our code picks off GGA; essential fix data that provide 3D location and accuracy data, we will look at that. A sample is in Listing 3.

What you can see from this example is that the data is comma delimited. This makes it a prime candidate for easy parsing by storing it in an external data window using the ImportString function. To get at the individual elements, we only need to index them by their position in the data window.

To extract each individual sentence out of the stream to be passed for parsing to the NMEA object, I wrote the wf_get_token function. This will extract a string based on a delimiter. For the NMEA stream, that is the newline character. (Figure 3)

Finally, we need a way to send our message to our server. You can write a .NET assembly by following the example that acts as a client in order to send the GPS information to the client.

One final note: If you plan on connecting to a Bluetooth serial port greater than COM9, you will need to use the syntax "\\.\COMx" as the port name. Just substitute the port number you wish to use for x. The cause of the problem is that CreateFile accepts strings "COM1" - "COM9" as names of devices, but rejects those with two or more digits.

That's it! You have now rolled your own location tracker. If you want to improve it, you might consider tracking more than one device at a time. This could easily be managed by an external data window that contains the user's name and last position. When a new position comes in, simply do a lookup on the user name, update the data window, and plot the new location on the map. Additionally, all the hard-coded references to ports and IP addresses would well be served by user configuration files.

Happy coding!

This article was first published in the ISUG Technical Journal, Jan.-Feb. 2007

About Deanne M. Chance
Ms. Chance graduated in 1996 with a degree in computer science from the University of Illinois. She has been a frequent contributor to the PowerBuilder Developer's Journal and gave a key presentation at Sybase TechWave 2005 entitled "A Real-Time Physical Inventory Solution Using PocketBuilder ASA and a WiFi Connection." She has held several engineering positions, starting a career at Motorola where she focused on mobile I.P. by doing real-time embedded programming for the base radio controller group as part of the iDEN/Nextel project.

In order to post a comment you need to be registered and logged in.

Register | Sign-in

Reader Feedback: Page 1 of 1

You can find a link to CodeExchange here
http://www.sybase.com/developer/downloads/codexchange

Look in the special hardware section, look for GPS. There is another GPS project I cooked up which has the NMEA parser with example.

Good Luck!

I can't find the NMEA parser mentioned in your article - do you have a link to the site I could use please?

You mention GPGAA, but don't you mean GPGGA?
"GGA - essential fix data which provide 3D location and accuracy data"

Could you please provide a link to the NMEA parser at Code-Exchange? I couldn't figure out which site you mean.

Many thanks in advance,
Anders Borg

Ooops...there is glaring mathematical error in here....2^8 = 256. I think what we were looking for was 2^16. My apologies.


Your Feedback
chance wrote: You can find a link to CodeExchange here http://www.sybase.com/developer/downloads/codexchange Look in the special hardware section, look for GPS. There is another GPS project I cooked up which has the NMEA parser with example. Good Luck!
Stuart wrote: I can't find the NMEA parser mentioned in your article - do you have a link to the site I could use please?
Anders Borg wrote: You mention GPGAA, but don't you mean GPGGA? "GGA - essential fix data which provide 3D location and accuracy data" Could you please provide a link to the NMEA parser at Code-Exchange? I couldn't figure out which site you mean. Many thanks in advance, Anders Borg
Chance wrote: Ooops...there is glaring mathematical error in here....2^8 = 256. I think what we were looking for was 2^16. My apologies.
Subscribe to the World's Most Powerful Newsletters
Subscribe to Our Rss Feeds & Get Your SYS-CON News Live!
Click to Add our RSS Feeds to the Service of Your Choice:
Google Reader or Homepage Add to My Yahoo! Subscribe with Bloglines Subscribe in NewsGator Online
myFeedster Add to My AOL Subscribe in Rojo Add 'Hugg' to Newsburst from CNET News.com Kinja Digest View Additional SYS-CON Feeds
Publish Your Article! Please send it to editorial(at)sys-con.com!

Advertise on this site! Contact advertising(at)sys-con.com! 201 802-3021

SYS-CON Featured Whitepapers
ADS BY GOOGLE