June 17, 2008
MarkBernstein.org
 
Follow me on Twitter

Tinderbox Geocoding

Let's suppose you have a Tinderbox document that has some notes about customers. And those customers have addresses. You might like to be able to locate the customers on a map — and nowadays, there are plenty of nice Web 2.0 services like Google Maps that will draw you nice maps. But, generally, you'll need to know the latitude and longitude of the customer, and what you have is an address.

This is, I think, a nice example of how you can use Tinderbox to talk to all sorts of Web 2.0 services — especially those with RESTful interfaces.

Converting an address to geographical coordinates is called geocoding. Google Maps has an API that does this for you; here's how we can let Tinderbox do all the work.

Step 1: you'll need to sign up to use the Google Maps API, and get a free "key" — a long code string that identifies you to Google Maps. (This lets Google figure out what's going on when someone's runaway program starts making millions of requests.)

Step 2: We'll make a container to hold configuration information — user names, passwords, stuff like that. Call it config. In that container, add a note to hold the API key. Call it key, and paste the key Google assigns you into its text window.

Tinderbox Geocoding

Step 3: We might need to add some user attributes, if we don’t already have them. We’ll want an address (a string), as well as latitude and longitude, which are numbers. We'll also make a prototype called place, and give it some suitable key attributes.

Tinderbox Geocoding

Step 4: We'll make a place or two, and enter addresses. I chose Eastgate’s offices, the White House, and Julia Child’s former apartment in Paris.

Step 5: Now, we’re going to write an agent that asks Google to figure out the address’s latitude and longitude. This is a lot of work; we don’t want to ask Google to do it over and over. So, our agent looks for notes for which we don’t already have this information:

Query: Prototype=place & address!=""&RawData=""

That is, we want all the places that have an address to look up, but for which Google hasn’t yet provided any data.

Step 6: Next, we send Google a request to look up a Web page with a really long and complicated URL like this:

URL="http://maps.google.com/maps/geo?q=address&output=csv&key=your key"

To do this, we ask the Unix program curl to run itself, getting the URL you want from stdin: "curl -K - ","url="+$URL.

Why not just put the URL on the command line, as we usually do with curl? Because the shell treats ampersands specially, and I don't want to get tangled up with escaping the ampersands.

So here's the agent's action:

Action: URL="http://maps.google.com/maps/geo?q="+urlEncode($address)+"
&output=csv&key="+$Text(/config/key) ;
RawData=runCommand("curl -K - ","url="+$URL)

In the first step, we assemble the URL we want to send to Google; the second step sends it to google and stores the result in RawData. That result will be something like the following:

200, 8, 48.860642, 2.319756

The first number is the error code; 200 means all was well. The second number estimates how accurate Google thinks the results are; 0 means Google has no clue, and 9 means that Google knows exactly where the address is located. The third number is the latitude, the fourth is the longitude.

Step 7: Finally, we want to extract the latitude and longitude from RawData. This is a piece of cake! We make a second agent that looks for places that have already received data from Google but don’t yet have a latitude:

Query: Prototype=place&latitude=0&RawData((.*),(.*),(.*),(.*)$

The last clause looks for places that have several comma-separated values in RawData. Finally, the actions are easy: we put the third value in latitude and the fourth in longitude.

Action: latitude=$3;longitude=$4

And we’re done. Now, we can pass these latitudes and longitudes to stick pushpins on maps, or calculate how far apart the addresses are, or whatever else we need.

Here's 81 rue de l'Université, Paris 75007 France ( 48.8606 N, 2.31976 E)

Tinderbox Geocoding

If you want to try it yourself, the file is here — you’ll need to enter your own Google Maps Key.

Delicious: ht08

Questions? I'm going to be at Hypertext 2008 this week. I'm especially looking forward to the writing workshop. If you’re in the area, stop by and ask in person. If not, email is fine, but answers might be slightly delayed. Or try the Tinderbox Forum.