My particular interest is voice mashups. I’ve been using Voxeo tools for a few years to delve into such areas as talking calendars, location-based voice notes, and on-the-fly driving directions. Most of the time, a crucial piece of the mashup is the tie-in with some rich stream of data, often provided by a Google web services. In recent years, the maturation of OAuth as a standard has provided for a really slick user experience. Signing up for one of these mashups, as far as the user is concerned, amounts to handing your app a “valet key” revocable at any time. No need to ask for passwords, which for many folks, would be a bridge too far.
As anybody who has played with Google data services can tell you, Python is a lingua franca down there in Mountainview. It was the first language to be offered with Google’s App Engine, and every Google data service with an API supports it. So it was with great enthusiasm that I took on the task of providing the initial Python implementation of the Tropo WebAPI. With that task completed, as of late last summer, we can all get down to the business of creating cool and powerful mashups using Python.
Sometimes a demo can be worth 10,000 words, so let’s get right to it. I’ve written the Moveable Weather demo so that it can run in a continuous loop. You call the access number to kick it off, and it reads your local weather to you. Then, you travel somewhere else, and press any key, and it will read you the weather in your new location. This demo is best performed while travelling on a high speed train, so you can see how the weather reports dynamically change. However, if this is impractical for you, it’s still possible to have the experience by using Google Latitude on iGoogle, as described below.
First, you’ll need a consumer Google account, such as you get with GMail.
- Visit http://moveable-weather.appspot.com and follow the prompts to sign up for the app. During signup, you’ll be asked to join Google Latitude, if you haven’t already done so. You’ll also be asked to agree to share your location data with Moveable Weather. Don’t worry, you can revoke it at any time. And if you choose to just travel virtually, you won’t be disclosing anything more intimate than the track of your mouse.
- During signup, Moveable Weather will assign you an 8-digit password. The first time you call in to Moveable Weather, you’ll enter this password, and an association will be created between your mobile phone, and your member account , which has access to the data. on Moveable Weather.
- (Optional, but recommended.) Go to the Google Latitude site, and follow the link to setup Google Latitude on you iGoogle page. This helps you minimize your carbon footprint, as you race around the country.
- Call back Moveable Weather, and this time it will tell you the weather at your current location. Then go someplace else far away, and hit any key. You’ll get read the weather at the new location.
About the Code
Most of the complexity in the coding and setup for Moveable Weather exists outside the realm of Tropo. And this is as it should be. A key design goal of Tropo was to enable web programmers to readily access the power of a voice interface, without having to first master VoiceXML programming.
I include some code below that show’s how I dealt with authentication for this voice app. The trickiest part of the authentication is handled by some some OAuth routines supplied by a Google engineer, on the Latitude group mailing list. The problem remained of how to pair this authenticated user with their cell phone number.
I decided on a simple scheme, where, upon web signup for Moveable Weather, a user is issued an 8-digit password. The first time the user calls in, they’ll be asked to supply this password. Here’s a piece of the implementation, in Tropo:
class TropoCheckPassword(webapp.RequestHandler): def post(self): """Check the user's 8-digit password. This password was assigned when they first authenticated. If we find a match in the datastore, we associate the incoming phone number with the member account that was retrieved. """ cellnumber = self.request.get('cellnumber') # This is how we get at the result was was posted to Tropo. json = self.request.body result = tropo.Result(json) password_attempt = result.getValue() try: q = model.Member.all().filter('passw =', password_attempt) members = q.fetch(1) member = members except: member = None # #1. Create a Tropo object we will use to post back to the Tropo engine. trop = tropo.Tropo() if (member): member.cellnumber = cellnumber member.put() trop.say ("Congratulations. Password entry accepted. From now on, when you call this number, you'll get the weather report of your current Google latitude location.") else: trop.say ("Sorry. That password was not correct.") choices = tropo.Choices("[1 digits]").obj trop.ask(choices, say="Press any key to try again.", attempts=3, bargein=True, name="confirm", timeout=5, voice="dave") # Redirect back to try again. trop.on(event="continue", next="/tropo_multi_weather.py?id=%s" % cellnumber, say="Ok, good luck.") # Render all the code, from #1. to here, to a json object. json = trop.RenderJson() # Post the json code back out to the Tropo engine. self.response.out.write(json)
The conversation between your app and the Tropo engine is handled using JSON, but the Tropo Web API for Python shields you from the details.
Coding using the Tropo Web API is pretty simple, once you grasp the basic idiom When you are POSTing to Tropo, you first build a JSON object embodying all your commands, and then you “render” it to JSON, and then you write it out. Likewise, when you receive a POST from Tropo, you read the JSON piece, and then unpack it to its various components. In this way, the conversation between you and Tropo proceeds.
An Ongoing Effort
There are lots of details about Moveable Weather that I won’t go into here, but that are covered in this project’s Wiki. There’s information there about geohashes, bulk loading of data, etc., and also, of course, the complete code itself.
Moveable Weather is just a proof of concept, at this point, a framework that you can adapt and expand. I’m eager to see what the Tropo community chooses to build on top of it. As for me, I’m going to create some more examples, and scratch some more personal itches. For example, a few years ago I wrote a voice application that tapped into NOAA data and told you the local tide info, after you entered your zip code. That should be pretty easy to adapt.
I’ll race you.