Plugin to interact with the Tropo Cloud platform

  • Tags : cloud, tropo, voip
  • Latest : 0.2.1
  • Last Updated: 03 October 2011
  • Grails version : 1.3.6 > *
  • Authors : null
0 vote
Dependency :
compile ":tropo-webapi-grails:0.2.1"

Documentation Source Issues

Summary

Installation

grails install tropo-webapi-grails

Description

Description

Tropo is an Open Source massively scalable developer platform that makes it simple to quickly and easily build phone, SMS and Instant Messaging applications - or applications that handle all three - using the web technologies you already know and Tropo's powerful cloud API.

This plugin implements the Tropo WebApi which is a server-side API that allows developers to create with very few lines of code applications that can send and receive SMSs and calls, build instant messaging powered applications, build conferences, transfer calls, record conversations, play and send sound files to other people and many other cool things. Apart from the Tropo WebApi, this plugin also implements the Tropo REST API which is a provisioning API that lets you configure, launch and manage all your Tropo applications.

To run your Tropo applications you will need a Tropo powered application server. Voxeo (Tropo authors) offers the Tropo Cloud platform which is totally free for developers and which has very competitive rates for production deployment.

Requires

Grails 1.0.5 or higher.

Includes

  • commons-codec-1.3.jar
  • ezmorph-1.0.6.jar
  • http-builder-0.5.1.jar
  • httpclient-4.0.3.jar
  • httpcore-4.0.1.jar
  • json-lib-2.4-jdk15.jar
  • xml-resolver-1.2.jar

Installation

You can install this plugin by running the following command:

grails install-plugin tropo-webapi-grails

Screencast

Be sure to check out this screencast on how to create your first project with Tropo and Grails: http://blog.tropo.com/2011/04/20/voice-powered-applications-with-grails-screencast

5 minutes tutorial

In the following sections we will create a sample Grails application that uses Tropo services. It will take you less than 5 minutes.

Creating your Tropo application

Once you have the plugin installed you will find that creating voice and SMS powered application becomes incredibly easy. But first of all you need to sign up with Tropo. Once you have registered and signed in you can proceed and create your first application. As we are creating an application that uses the WebApi, you need to click on the plus button and then choose WebApi application like in the picture below:

Tropo applications can be executed in very different ways. Whenever a tropo application is launched the Tropo Cloud platform will create a new session and will invoke an URL at your server. Tropo applications can be triggered in many different ways like for example:

  • Calling a phone number that you have set up
  • Calling a skype number
  • Sending a SMS
  • Sending a message through an IM network
  • Using the REST API
  • From Grails itself using the TropoService object (effectively it runs a GET request to the REST API)
Therefore, the next step you need to do is to define the URL at your server that will be invoked when a new session is launched from your Tropo application. The next picture shows how I pointed my newly created Tropo application to my Grails instance:

Once the application is created you will find that there is already several phone numbers linked to it. There is already a Skype phone number and you can link your application with several IM networks or even your Twitter account. On that same screen you will find links to attach new US national and international phone numbers to your application. More than 40 countries are supported. A mesage or phone call to any of these phone numbers or services will trigger your Grails controller logic. In the screenshot below you will find that I have attached an US national number and an UK phone number to our sample application:

Creating your Controller

Once your application is created adding voice support to it is really simple. You do not need any specific artifacts so you can add voice and messaging support to any of your Grails controllers, services or Taglibs. However, you will need to provide some implementation for the Grails controller that you have linked to your application in the previous steps.

The Tropo WebApi is based in JSON and defines many different methods. This plugin provides a groovy builder that makes really easy to interact with the Tropo platform. Below you can find an example for our TropoController.groovy:

import com.tropo.grails.TropoBuilder;

class TropoController {

def index = {

def tropo = new TropoBuilder() tropo.tropo { say("Hello World. Hello Tropo. We are going to play a song.") say("http://ccmixter.org/content/copperhead/copperhead_-_When_We_Do.mp3") hangup() } tropo.render(response) } }

Note that you can also use a more 'traditional' approach. The following source code is equivalent to the snippet above. Use whatever syntax you feel more comfortable with.

import com.tropo.grails.TropoBuilder;

class TropoController {

def index = {

def tropo = new TropoBuilder()

tropo.say("Hello World. Hello Tropo. We are going to play a song.") tropo.say("http://ccmixter.org/content/copperhead/copperhead_-_When_We_Do.mp3") tropo.hangup()

tropo.render(response) } }

Testing your application

If you have created some landline phone numbers you can test your application just by calling those phone numbers. For example, in this tutorial you could call either +44 1259340253 or (407) 680-0744 and you would hear a welcome message and a mp3 song would be played until either the song stops or you hang up. You can also use Skype to call your application:

And that is it. As you have seen, we have created a Grails application that answers a phone call and plays some song to the user with almost no effort. This is a very naive example but it shows how easy this plugin makes to add voice and messaging to your apps. Now it would be a nice moment to stop and learn more about the Tropo WebApi reference and all the possibilities that brings up to developers.

In the sections below we would expand on this plugin and will provide samples about how to call all the different methods.

Source Code

Although the plugin is available from Grails SVN, the latest source code for this plugin is hosted at GitHub. You can find it here: https://github.com/tropo/tropo-webapi-grails

Using Tests as a reference

At the source code there is several unit tests that show how to use the Groovy builder. Check them out here.

Configuration

This plugin does not require specific configuration parameters by default.

If you plan to use the REST API then you should provide your Tropo username and password as most of the REST API methods are secured by default. In this case you need to add the following lines to your Config.groovy file providing your Tropo username and password:

tropo.username = "yourtropousername"
tropo.password = "yourtropopassword"

Interacting with Tropo REST API

Tropo REST API allows you to interact with Tropo platform through a REST based service. This API can be used to directly invoke your applications (for example you could provide a phone image link in your webapp GUI that will invoke your application and trigger the Controller that we saw in the 5 minutes tutorial). Another usage for this API is to administer your account. You can use this API to create new applications, create and delete phone numbers, create and delete IM accounts, send signals to your application (like hanging up), etc. In summary, it is an admin and provisioning API.

Although you could send the REST requests yourself, this plugin provides a handy Grails service named TropoService that is injected in your applications and that you may use to execute all the different Tropo REST API calls.

Here is an example on how simple would be to launch your Tropo application using the TropoService:

class TropoController {

def tropoService

def index = {

tropoService.launchSession(token: '72979191d971e344b46a0e4a3485571844250e689bb13548a75f1cce2ce9a53dde82c3fe944479bcb650500e') }

As you can see in the code above, some of the TropoService calls will require a token. Each Tropo application has a unique token for handling voice calls and a different token for handling messaging. You can find your application's tokens at your application page in Tropo.com

IMPORTANT: Transcription issues

The interaction with Tropo is based on the interchange of JSON based documents. There is a known bug where Tropo sends transcription POST requests with a Content-Type header set to 'application/x-www-form-urlencoded' which basically will make the JSON coverter to fail with a message pretty similar to "org.codehaus.groovy.grails.web.json.JSONException: Missing value. at character 0 of "

If you face this issue the workaround is to disable Grails' automcatic content handling and parse the POST body yourself with the JSON converter. This is actually pretty easy. Here is an example:

import grails.converters.JSON

class TestController {

static allowedMethods = [add:'POST']

def index = { }

def transcription = {

def raw = request.reader.text def json = JSON.parse(raw) render "ok" } }

Examples using the Tropo Builder

As you could see in the 5 minutes tutorial above, this plugin provides a groovy builder that makes really easy to interact with the Tropo platform. The following examples showcase some of the actions that you could do in your Grails applications.

Saying something to the user

def builder = new TropoBuilder()
builder.tropo {
	say('Hello Mr. User')
}
Find more about the 'say' method at the 'say' reference page

Asking a question to the user

def builder = new TropoBuilder()
builder.tropo {
	ask(name : 'foo', bargein: true, timeout: 30, required: true, choices: '[5 DIGITS]') {
		say('Please say your account number')
	}
}
Find more about the 'ask' method at the 'ask' reference page

Asking a question and redirecting the user to a different controller

Simply asking a question wasn't really a very useful action. Lets ask a question and redirect the user to a new action in our controller:

def builder = new TropoBuilder()
builder.tropo {
	ask(name : 'foo', bargein: true, timeout: 30, required: true) {
		say('Please say your account number')
		choices(value: '[5 DIGITS]')
	}
        on(event:'continue',next:'/tropo/zipcode')
}

Displaying the outcome of your application actions

In the example above we've seen how we can redirect to a different controller to handle the user's input like for example when entering a number or saying something. How can we get the user input from our controllers?

It is really easy. Tropo will send a POST request to our controller containing the result of the action that we have executed. That includes any input from the user:

def zipcode = {

def tropoRequest = request.JSON def zipcode = tropoRequest.result.actions.value

def builder = new TropoBuilder() builder.tropo { say(value: "Your zipcode is ${zipcode}. Thank you.") hangup() }

builder.render(response) }

Creating a conference

The conference action allows multiple lines in separate sessions to be conferenced together so that the parties on each line can talk to each other simultaneously.

def builder = new TropoBuilder()
builder.tropo {
	conference(name: 'foo', id: '1234', mute: false, send_tones: false, exit_tone: '#') {
		on(event: 'join') {
			say(value: 'Welcome to the conference')
		}
		on(event:'leave') {
			say(value: 'Someone has left the conference')
		}
	}
}
Find more about the 'conference' method at the 'conference' reference page

Hanging up

As it name says, the hangup action will simply hang up the call.

def builder = new TropoBuilder()
builder.hangup()
Find more about the 'hangup' method at the 'hangup' reference page

Recording a call

The record action plays a prompt (audio file or text to speech) then optionally waits for a response from the caller and records it.

def builder = new TropoBuilder()

builder.record(name: 'foo', url: 'http://sendme.com/tropo', beep: true, sendTones: true, exitTone: '#') { transcription(id: 'bling', url:'mailto:jose@voxeo.com', emailFormat: 'encoded') say('Please say your account number') choices(value: '[5 DIGITS]') }

Find more about the 'record' method at the 'record' reference page

Redirecting a call

Redirect is used to deflect the call to a third party SIP address. This function must be called before the call is answered; for active calls, consider using transfer.

def builder = new TropoBuilder()
builder.tropo {
	redirect(to: 'sip:1234', from: '4155551212')
}

Find more about the 'redirect' method at the 'redirect' reference page

Rejecting a call

This action rejects the incoming call. For example, an application could inspect the callerID variable to determine if the user is known, then reject the call accordingly.

def builder = new TropoBuilder()
builder.reject()

Find more about the 'reject' method at the 'reject' reference page

Starting a recording

Allows your plugin to begin recording the current session. The resulting recording may then be sent via FTP or an HTTP POST/Multipart Form.

builder.tropo {
	startRecording(url:'http://postrecording.com/tropo')
}
Find more about the 'startRecording' method at the 'startRecording' reference page

Stopping some recording

This stops the recording of the current call after startCallRecording has been called.

def builder = new TropoBuilder()
builder.stopRecording()

Find more about the 'stopRecording' method at the 'stopRecording' reference page

Transfering a call

The transfer action will transfer an already answered call to another destination / phone number

builder.tropo {
	transfer(to: 'tel:+14157044517') {
		on(event: 'unbounded', next: '/error')
		choices(value: '[5 DIGITS]')
	}
}

Find more about the 'transfer' method at the 'transfer' reference page

Calling someone

The call method initiates an outbound call or a text conversation. Note that this verb is only valid when there is no active WebAPI call.

builder.call(to: 'foo', from: 'bar', network: 'SMS', channel: 'TEXT', timeout: 10, answerOnMedia: false) {
	headers(foo: 'foo', bar: 'bar')
	startRecording(url: 'http://foobar', method: 'POST', format: 'audio/mp3', username: 'jose', password: 'passwd')
}

Find more about the 'call' method at the 'call' reference page

Sending messages

The message action creates a call, says something and then hangs up, all in one step. This is particularly useful for sending out a quick SMS or IM.

def builder = new TropoBuilder()

builder.message(to: 'foo', from: 'bar', network: 'SMS', channel: 'TEXT', timeout: 10, answerOnMedia: false) { headers(foo: 'foo', bar: 'bar') startRecording(url: 'http://foobar', method: 'POST', format: 'audio/mp3', username: 'jose', password: 'passwd') say('Please say your account number') }

Find more about the 'message' method at the 'message' reference page

Event handling

Some actions may respond to different events. You can specify the different events as parameters. Refer to the WebApi reference to get more information.

def builder = new TropoBuilder()

def help_stop_choices = '0(0,help,i do not know, agent, operator, assistance, representative, real person, human), 9(9,quit,stop,shut up)' def yes_no_choices = 'true(1,yes,sure,affirmative), false(2,no,no thank you,negative),' + help_stop_choices builder.ask(name: 'donate_to_id', bargein: true, timeout: 10, silenceTimeout: 10, attempts: 4) { say([[event: 'timeout', value: 'Sorry, I did not hear anything.'], [event: 'nomatch:1 nomatch:2 nomatch:3', value: "Sorry, that wasn't a valid answer. You can press or say 1 for 'yes', or 2 for 'no'."], [value: 'You chose organization foobar. Are you ready to donate to them? If you say no, I will tell you a little more about the organization.'], [event: 'nomatch:3', value: 'This is your last attempt.']]) choices(value: yes_no_choices) }

Embedding builders

Sometimes you may need to create a builder in one method then run some logic and append extra content to the builder. This plugin lets you append builders within other builders. Here is an example:

def builder1 = new TropoBuilder() 
		builder1.tropo {
			on(event:'continue',next:'/result.json')
		}

def builder2 = new TropoBuilder() builder2.tropo { ask(name : 'foo', bargein: true, timeout: 30, required: true) { say('Please say your account number') choices(value: '[5 DIGITS]') } append(builder1) }

Author

Martín Pérez (mpermar@gmail.com)

Please report any issues to the guys at Voxeo support. You can also use the Grails User mailing list and/or write up an issue in JIRA at http://jira.codehaus.org/browse/GRAILSPLUGINS under the Tropo-Webapi-Grails component.

History

October 4, 2011

  • Fixed: public/private mixed warning from STS2.8.0M1 and grails snapshot
  • Released version 0.2.1
August 31, 2011
  • Added a new isEmpty method to TropoBuilder
  • Bug fixed. Append could only be used at the end of a closure.
  • Bug fixed. Recordings use a choices element not exit_tone attribute.
  • Added support for the new interdigitTimeout element in WebApi
  • Released version 0.2 of the plugin
August 4, 2011
  • Added the possibility to embed builders within other builders
  • released version 0.1.2
August 3, 2011
  • Fixed TropoBuilder's toString
  • released patched version 0.1.1
February 7, 2011
  • released initial version 0.1