Building Cloud Communication Apps with Tropo: Part 3

This post is a continuation of the series on building cloud communication applications with Tropo, the PHP WebAPI Library and the Limonade framework for PHP .

If you’re just starting, you can take a look back at part 1 and part 2 to get caught up.

In this post, we’ll continue our work from the last post and complete a simple, yet powerful multi-channel application that can be accessed via telephone, SMS or IM client.

In the previous post, we looked closely at the Session and Result objects – these are JSON objects that are sent to your application by the Tropo platform that contain information about how a user is accessing your app (i.e., through which channel) and any input they have provided in response to prompts. If you worked through the last post, you have a partially complete script that looks like this:

You should save this script to a server that can be accessed by the Tropo platform – any web hosting platform that supports PHP >= 5.2.0 will do. Let’s call our script get_zip_code.php.

When you set up the start URL for this script in the Tropo Application Manager, you’ll want to structure it like so:

http://name_of_my_host.com/path/to/get_zip_code.php?uri=start

As you can see, we’ve added a querystring parameter called uri. This will ensure that the initial HTTP POST to this script by the Tropo platform matches our /start pattern and executes our zip_start() method, which is where we want users to begin. Make sure you review the Limonade documentation on setting up routes, as there are multiple options for configuring route pattern matching.

Next, we’ll want to start modifying our partially constructed script. First go to step 6 in the zip_start() method, where we had set up a PostBin URL for Tropo to send a user’s input to so we could examine the Result object. Now that we know what the Result object looks like, we want to start using it to look up information and present it to the caller.

You’ll want to set up a URL to the get_zip_code.php script that will match the route for the zip_end() method. This is where we will access the Tropo Result object and process it. Change the URL in the “next” array element to look like this:

$tropo->on(array(“event” => “continue”, “next” => “get_zip_code.php?uri=end“, “say” => “Please hold.”));

This change tells Tropo that when the “continue” event is raised (after the caller has completed entering input) POST the Result object back to the get_zip_code.php script using a relative URL and a querystring parameter that will ensure matching of our /end pattern.

Next, we need to build out the zip_end() method to process the results:

dispatch_post('/end', 'zip_end');
function zip_end() {

        // Step 1. Create a new instance of the result object
	$result = new Result();
	$zip = $result->getValue(); // get the value of the user input.

        // Step 2. Get weather information for the zip code the caller entered.
	$weather_info = getWeather($zip);
	$city = array_pop($weather_info);

        // Step 3. Create a new instance of the Tropo object.
	$tropo = new Tropo();

        // Step 4. Begin telling the user the weather for the city their zip code is in.
	$tropo->say("The current weather for $city is...");

        // Step 5. Iterate over an array of weather information.
	foreach ($weather_info as $info) {
	    $tropo->say("$info.");
	}

        // Step 6. Say thank you (never hurts to be polite) and end the session.
	$tropo->say("Thank you for using Tropo!");
        $tropo->hangup();

        // Step 7. Render the JSON for the Tropo WebAPI to consume.
       return $tropo->RenderJson();

}

As you can see, our zip_end() method looks similar to our zip_start() method – both use a Tropo object to format information that will be presented to the user, and both call the RenderJson() method of the Tropo object at the end.

You may be wondering about the getWeather() method that is called in step 2. Let’s build that out now and examine how it works – to keep things simple, we’ll make use of the Google Weather API, which provides weather information by zip code and returns the information in XML format.

// The URL to the Google weather service. Renders as XML doc.
define("GOOGLE_WEATHER_URL", "http://www.google.com/ig/api?weather=%zip%&hl=en");

// A helper method to get weather details by zip code.
function getWeather($zip) {

	$url = str_replace("%zip", $zip, GOOGLE_WEATHER_URL);
	$weatherXML = simplexml_load_file($url);
	$city = $weatherXML->weather->forecast_information->city["data"];
	$current_conditions = $weatherXML->weather->current_conditions;
	$current_weather = array(
		"condition" => $current_conditions->condition["data"],
		"temperature" => $current_conditions->temp_f["data"]." degrees",
		"wind" => formatDirection($current_conditions->wind_condition["data"]),
		"city" => $city
	);
	return $current_weather;

}

// A helper method to format directional abbreviations.
function formatDirection($wind) {
	$abbreviated = array(" N ", " S ", " E ", " W ", " NE ", " SE ", " SW ", " NW ");
	$full_name = array(" North ", " South ", " East ", " West ", " North East ", " South East ", " South West ", " North West ");
	return str_replace($abbreviated, $full_name, str_replace("mph", "miles per hour", $wind));
}

The mechanics of these functions are pretty straighforward, so I won’t go in to too much detail – you can now see the connection between the call to the getWeather() method mentioned above and the array of weather data that it returns.

The last thing we need to do in order to complete our zip code weather demo script is to finish the zip_error() method. This is a method we’ll use to tell a user an error occurred (never hurts to be prepared for the unexpected):

dispatch_post('/error', 'zip_error');
function zip_error() {

	// Step 1. Create a new instance of the Tropo object.
	$tropo = new Tropo();

	// Step 2. This is the last thing the user will be told before the session ends.
	$tropo->say("Please try your request again later.");

	// Step 3. End the session.
	$tropo->hangup();

	// Step 4. Render the JSON for the Tropo WebAPI to consume.
	return $tropo->renderJSON();
}

In order for this method to be invoked, we need to make sure that we set up the proper handler in our zip_start() method for it. The Tropo WebAPI makes it possible to set up callback methods that handle things when certain events are raised. This is done by using the On object.

Setting up an event handler using the On object with the PHP WebAPI Library is easy. In fact, we’ve already done it once – look at the zip_start() method and you’ll see a hander for the “continue” event (which is raised when a user has finished entering the proper input). We want to set up something similar for when an error event is raised. Let’s add a handler in our zip_start() method for an error event:

	// Step 6. Tell Tropo what to do when the user has entered input, or if there is an error.
	$tropo->on(array("event" => "continue", "next" => "get_zip_code.php?uri=end", "say" => "Please hold."));
	$tropo->on(array("event" => "error", "next" => "get_zip_code.php?uri=error", "say" => "An error has occured."));

Our script is now complete and ready to test.

Make sure you log into your Tropo account and set up the start URL to your script as discussed above. You can test this script with the phone numbers that are automatically provisioned by Tropo when you set up your account.

Tropo will automatically provision a Skype number, a SIP number and an iNum. You can additionally add a PSTN number in a range of different area codes at no charge. This PSTN number can also be used to send an SMS to, so you can interact with this script via text message. Additionally, you can add an IM account, so you can test this script using your favorite IM client/network.

You may notice, if you test this script using SMS or IM that there are things that don’t yet work perfectly. In the next post, we will make some very simple changes to this script to optimize it for use with SMS and IM (and even Twitter!).

This will transform our simple PHP script into a powerful unified communications application.

Stay tuned…

Advertisements

Building Cloud Communication Apps with Tropo: Part 1

A few months back, I wrote a series of posts on building NoSQL telephony applications with Tropo and CouchDB. Today I’m going to start a continuation of that series, focusing on how to build cutting edge cloud communications apps with the Tropo WebAPI.

What is the Tropo WebAPI?

The Tropo WebAPI is, in a nutshell, an HTTP/JSON API for building multi-channel communication applications – applications that you interact with via phone, IM, SMS or Twitter. While my earlier series on Tropo focused on building applications in Tropo’s scripting environment (another fine option for developers), this series will focus on building JSON-based applications (generated using PHP) that can be hosted anywhere and executed in the Tropo cloud environment.

Faithful readers will recognize some similarities here to a post I did a while back on the HTTP/JSON API provided by CloudVox, another cloud telephony provider. While the concept behind these two API’s is very similar, there are some key differences that make Tropo a highly attractive option for developers.

First, the Tropo service is truly multi-channel – using the Tropo WebAPI you can build applications that work on a range of different communication channels, not just phones (although you can build some pretty slamming phone apps as well).

Since I’m a phone app developer at heart, some of the features that Tropo provides for phone applications really get me excited. Tropo supports both DTMF entry and speech recognition. It also has broad multilingual support. In addition, Tropo gives phone application developers the ability to manipulate SIP headers, an important feature in building sophisticated cloud communication apps that I hope to demonstrate down the road a bit.

Getting Started

Head on over to Tropo.com and set up a new account (if you don’t have one already). Take a little time to review the documentation for the Tropo WebAPI. For the example applications in this series of blog posts I’ll be using a PHP class library I developed specifically to interact with the Tropo WebAPI.

The crew behind Tropo have provided a Ruby Gem for interacting with the Tropo WebAPI. However, since I like to do my cloud telephony work with PHP I decided to write my own set of classes for doing this. Whether you’re a Ruby-head or a PHP enthusiast, using one of these tools to generate JSON for consumption by the Tropo WebAPI can make build an application significantly easier, particularly as you get into more sophisticated application development.

You can get the PHP Library, as well as some of the sample apps we’ll be looking at, from GitHub:

$ git clone git://github.com/tropo/tropo-webapi-php.git

You’ll need to host these classes and the PHP scripts you write with them on a server that can be accessed from the Tropo environment. Any web server that supports PHP will do.

My First Tropo WebAPI Application

Let’s start with the standard Hello World app:


Say("Hello World!");

// Render the JSON for the Tropo WebAPI to consume.
$tropo->RenderJson();

?>

You can look at the rendered JSON in your browser, and you should see something like this:


{
    "tropo": [
        {
            "say": [
                {
                    "value": "Hello World!"
                }
            ]
        }
    ]
}

Go to the Applications section in your Tropo account and set up a new WebAPI application that points to the location of this script.

Create a new Tropo WebAPI application

Assign a URL to your new Tropo WebAPI application

When you create your application, Tropo will automatically provision a Skype number, a SIP number and an iNum. You can additionally add a PSTN number in a range of different area codes at no charge.

You may also notice the section below the provisioned phone numbers entitled “Instant Messaging Networks” – this section allows you to set up any number of different IM accounts (and Twitter!) that your application can use. We’ll dive deeper into this in future posts.

For now, we’ll keep it simple and use the auto provisioned Skype number – when you call this number, you will hear it say “Hello World.”

The next post in this series will focus on a more sophisticated application that uses the TropoPHP classes and the utterly awesome Limonade PHP framework.

Stay tuned…

Using Twitter to Respond to Natural Disasters

Dan York of Voxeo has posted a great interview with Martin Murray of Public Service of New Hampshire (PSNH) detailing the utility’s response to an ice storm last month that knocked out power to a significant number of customers.

PSNH is New Hampshire’s largest electric utility, serving more than 490,000 homes and businesses throughout the state. The utility made extensive use of Twitter, YouTube and other social networking tools during the recent ice storm to provide information to customers impacted by the storm. This is yet another example of a creative use of social networking tools by a utility company.

Governments take heed! In some parts of the country (including my home state of Delaware) local governments are also the local utility company. But more than that, the creative use of social networking tools by PSNH should stand as an example of the different ways governments can improve their communications with citizens using these tools.

What a great service it would be to find out how long the wait is at the local DMV, or to find out how long the wait in the automobile inspection lanes are via Twitter. Or how about getting Tweets when trash or recycling picks up change because of a holiday?

There is enormous potential for improving the interactions between citizens and their governments using these tools. Time for more governments to get with it

Spread the Love

Is YouYube getting preferential treatment from governments?

Frederic Lardinois, of ReadWriteWeb, argues that when it comes to posting videos online governments should spread the love:

Lately, there has been a trend for government agencies and elected officials to put their videos up on YouTube. While we commend them for doing so, we can’t help but wonder if this is, in the end, a positive trend. After all, while YouTube is definitely the most popular video sharing site, it is definitely not the only one.

He’s right. I’ve made this same argument about governments using Twitter. There are other microblogging sites out there, and governments need to make sure that their use of new channels to communicate with citizens (whether through video or microblogging) is not targeted to one specific company.

Some might argue that using multiple video sharing or microblogging sites is just adding work. Don’t underpayed and overburdened public employees have enough to do?

If this is the argument, then I’d respond by saying that the use of these services should be automated — almost all of them (certainly any of them worth using) have an API that makes it easy to develop scripts or applications that can significantly cut down the time and effort required to post content. YouTube has one. So does Twitter.

Social networking platforms are becoming the norm for government communication and outreach. Its time for governments to get smart about their use of these services.

Automate your processes. Use the APIs. Spread the love.

How NOT to Manage an API

Recently, I decided to build a small application that interacts with the Twitter API, the cli.gs API and Google Calendar to allow me to get advanced notice of any and all Boston Celtics games. The app is actually live and can be followed on Twitter.
Boston Celtics
It’s a pretty neat little application that runs on a daily cron job and queries a small database to see if there is a Celtics game on the following day. If there is a game the next day, it generates a link to add the game to Google Calendar, shortens the link using the cli.gs API and sends out a Tweet with the game details and Calendar link. Pretty sweet, right?

Unfortunately, almost immediately after going live the Twitter API started to return some nasty HTTP responses and I was unable to update the status of the celticsgames account. Specifically, the Twitter API started to return the HTTP 417 response code. After doing a little Googling, I found that I was not the only person using the Twitter API to suddenly (and without any warning) run into a problem that broke their application.

The issue stems from the inclusion of the HTTP Expect header in the request that is sent to the Twitter API. I’m using PHP and cURL to interact with the Twitter API. Apparently, this header is sent by default with a value of ‘100-continue’ by cURL (unless you override it and set a different value). Seems the Twitter API grew very confused by this setting in the past few days. The HTTP spec states that:

A server that does not understand or is unable to comply with any of the expectation values in the Expect field of a request MUST respond with appropriate error status. The server MUST respond with a 417 (Expectation Failed) status if any of the expectations cannot be met or, if there are other problems with the request, some other 4xx status.

I did some checking and I can’t find any mention on the Twitter API Wiki about a recent change that would have affected how the Twitter API responded to HTTP requests with the Expect header set in any particular way (it is possible, though, that I could have missed it). I also referred to the specific list of HTTP status codes returned by the API — no mention of a 417 response at all.

In my opinion, this is a pretty crappy way to manage an API. If your goal is to encourage third-party developers to build applications that work with your API, don’t make breaking changes without going to great lengths to ensure the developer community understands how the change will impact them. And for goodness sake, update your documentation.

Fortunately, there is a Celtics game on later today (during which they will absolutely pound the LA Lakers) — that should take this bad taste out of my mouth.

Wanted: One IM/VoIP Client That Does it All

Vacancy Description:

There is an immediate opening in my life for a smart, fast, next-generation IM client that can integrate with multiple social networks, standard XMPP servers, email and POP accounts and VoIP services.

Candidates already evaluated:

Digsby: Digsby is an IM client that connects to AIM, MSN, Yahoo, ICQ, Google Talk, Jabber, and Facebook Chat.

Pros:

  • Can be used to manage e-mail on different networks (Hotmail, Gmail, Yahoo Mail, AOL/AIM Mail, IMAP, and POP accounts).
  • Integrates with social networks like Facebook (receive friend requests, etc.) and Twitter (change status).

Cons:

  • Windows only (for now).
  • Can’t use for VoIP phone / video calls.

WengoPhone: A SIP client that also integrates with IM networks such as Google and AIM.

Pros:

  • Multi-platform (runs on Windows, Linux or Mac).
  • Supports SIP.
  • Support for AIM and Jabber IM accounts.

Cons:

  • Can’t integrate with social networks like Facebook.
  • Can’t be used to manage e-mail accounts

Meebo: A web-based service that integrates with a host of different IM and social networks, including Facebook and MySpace.

Pros:

  • Web-based — no install required, and can be accessed from anywhere.
  • Can connect to AIM, Yahoo, Google, MySpace, Facebook, Jabber and ICQ accounts

Cons:

  • Can’t use for VoIP phone / video calls.
  • Ad supported, so I get asked if I want to watch Miley Cyrus videos on occasion (who doesn’t though…)

This position will remain open until a suitable candidate has been found.

More Governments Using Twitter

I posted a few weeks ago about the potential that Twitter has to assist governments in disseminating information. Since then, I’ve come across lots of stories on how governments are using Twitter for everything from traffic notifications to press releases to public meeting notices.

Government Technology has an interesting piece on how the State of Washington is using Twitter.

If you know of an interesting use of Twitter by a public sector organization, post a link to it in the comments section.