Archive for April, 2010

New SMS Features Deployed

Tuesday, April 27th, 2010

As we work to continue to extend the Tropo API, we have added a few new SMS features for your enjoyment. The new features:

  • Caller ID may be set for outbound SMS to any phone number assigned to the application sending the SMS.
  • If Caller ID is not set, then by default the first phone number in your application list of numbers will be used as the Caller ID.
  • Tropo will now respond from the same phone number that was initially contacted by an Inbound SMS by default if there is more than one number assigned to your application.

Here is a quick snippet on how to send an outbound SMS using Tropo Scripting and setting the Caller ID:

call $numberToMessage, { :channel  => 'TEXT', :network  => 'SMS', :callerID => '4155551212' }
say 'Here is your friendly SMS message'
hangup

More to come, so stay tuned!

tropo-webapi-ruby Ruby Gem Version 0.1.6 Released

Monday, April 26th, 2010

We have updated the tropo-webapi-ruby gem to version 0.1.6 today. The gem is available on Rubygems.org.

The gem is now dependent on ‘json_pure‘ instead of ‘json‘, in order to ensure compatibility between the Ruby MRI and JRuby. If you are using the Ruby MRI and would prefer to use the C version of ‘json’ you may still do so. Simply run ‘sudo gem install json’ and the tropo-webapi-ruby gem will start using the native version of ‘json’.

The second item that was added to the gem is a dependency on the ‘hashie‘ gem. Hashie provides a class, Mash, that the tropo-webapi-ruby gem now uses. From the Hashie README:

Mash is an extended Hash that gives simple pseudo-object functionality that can be built from hashes and easily extended. It is designed to be used in RESTful API libraries to provide easy object-like access to JSON and XML parsed hashes. – Hashie

Now, when you receive an HTTP POST from Tropo you may handle in any one of these three ways:

tropo_event = Tropo::Generator.parse request.env["rack.input"].read

# All three of these are now valid with Hashie
p 'Call Answered!' if tropo_event.result.call_state == 'Answered'
p 'Call Answered!' if tropo_event[:result][:call_state] == 'Answered'
p 'Call Answered!' if tropo_event['result']['call_state'] == 'Answered'

Tutorial: Using Loops & Functions in your Tropo applications

Monday, April 26th, 2010

Hello,

This afternoon I got a ticket over here at the Fortress of Solitude, err I mean Voxeo Support that I thought I would share with the class. This developer opened a ticket asking how to implement control document execution in his applications. In short he was looking to prompt his callers, in a loop, and stay in said loop until the user explicitly opts to hung up, or proceed with the call. This developer was stuck on whether or not he would have to explicitly repeat the ask() with each iteration.

The developer was also wondering how he could alternate prompts in hopes of giving his application a more natural feel for his users. I could immediately see how implementing this could be confusing for some of our developers, and also how this could be helpful on any channel not just Voice (SMS, Instant Message, Twitter,ect). This being the case I thought this most certainly warranted a blog posting to shared the example with our developers in hopes it may prove helpful; And now for our feature presentation….

<?php
answer();

//Global options for ask, declare once, use many =)
$globalOptions = array(
  "choices"     => "one( 1, one), two( 2, two),exit(3,exit)", 
  "repeat"      => 3,
  "onBadChoice" => create_function( '$event', 'say("I am sorry, I did not understand what you said.");' ),
  "onTimeout"   => create_function( '$event', 'say("I am sorry.  I didn\'t hear anything.");' )
	);

$promptArray = array(
    "Hello, to select the first option please press or say one, for the second option please press or say two.  To exit the application please say exit or just press 3",
    "For option one press or say one, or for option two press or say two"
   );
$promptIteratorVariable = 0;
/**
 * whichPromptToSay
 *
 * @return Array element of  our array ($promptArray) depending on count of $promptIteratorVariable
 */

function whichPromptToSay(){
	global $promptArray;
	if ($promptIteratorVariable==0){
		$promptIteratorVariable++;
		return $promptArray[0];
	}else{
		return $promptArray[1];
	}
}

/**
 * whichVerbToSay()
 *
 * @return element of our verb array
 */
$verbArray = array("selected","chose","picked","opted for");

function whichVerbToSay(){
	return $verbArray[rand(0,(count($verbArray)-1))];
}

//We will continue our loop until false, but first we need to set to true
$continueLoop = true;

while($continueLoop){
$result = ask(whichPromptToSay(),$globalOptions);
	if($result->name=='choice'){
		if ($result->value=="one"){
			say( "You " . whichVerbToSay() . " option one");
		}elseif ($result->value=="two"){
			say( "You " . whichVerbToSay() . " option two");
		}elseif ($result->value=="exit"){
			say( "peace out");
				$continueLoop = false;
		}
	}
}
hangup();
?>

The thing to take home from this example is that you can make use of functions to add a bit of flair to your applications, as well as loops to control application execution. These two techniques will hopefully not only help you have cleaner code, but also help you provide a better, more natural, user experience for your callers! If there are any questions on anything presented here please don’t hesitate to let us know, as our team is most certainly standing by to offer any help our developers may require!

Regards,

John Dyer
Customer Engineer
Voxeo Support

Tutorial: Click-to-Call applications (w/ conferencing)

Saturday, April 24th, 2010

Hello,

A great use of Token initiated calls, or calls initiated via HTTP request, are click to call applications. This is when you have a fancy button on your website and can have your customers simply ‘click to call’ your call center. This allows them to get right to the people they need quickly and effectively, but how do you do it? Well over here at the ‘Halls of Justice’, sorry I mean Tropo Support we get this a lot. This being the case I have gone ahead and put together a nice example to show you just how to put a click to call application together!

So before we start I need to make one thing clear, Scripting is top down execution, or the fancy word is synchronous. This means task 2 can’t start until task 1 is complete, but to get around this we will make use of threads, providing our language of choice supports it. In Ruby this is pretty simple, and other markups may allow for threading, but that is a whole another discussion. In this example it’s Ruby and we are using with threads, just go with it =):

So, in order to start a new thread you just need a call to Thread.new. A new thread will be created to execute the code inside the thread block, then the original thread will return from Thread.new right away and continue with the next statement

# Thread #1 is running here
 Thread.new
  # Thread #2 runs this code
 end
# Thread #1 runs this code

If you want to read up on this more there is a great tutorial I have linked here which you should check out.

Now this whole posting is predicated on the fact that you do know how to do a token call, so if you don’t please take a quick look at the Tropo Session API (Token Initiation ) documentation. You can find this here in our documentation so please give it a read if you have not already.

In this example we are going to base our code on a code snippet provided in that section of our documentation:

call('tel:+1' + $numberToDial, {
  :onAnswer => lambda { |event|
    say("Hello " + $customerName + ", " + $message);
    log("Contacted customer: " + $numberToDial);
    hangup()
  }}
)

So this example will call someone, and it will play a message, but that is only going to get us halfway there I am afraid; The reason is we not only need to call our user (customer) we also need to call our call center. Once have them both on the line we then need to get them to talk to each other using a conference. Since as I mentioned Ruby is executed top down we’ll need to use threads in order to achieve this goal. Yea, it may sound complicated, but in actuality it’s bark is much worse then it’s bite; Lets take a look at the finished example below:

#Define Global Options
operatorNumber = "4074181800"
applicationCallerID = "8008675309"

#Method to create timeStamp as our conferenceID
	def get_conference_id()
		timeVar  = Time.new
		returnValue = timeVar.strftime("%Y%H%M%S")
		return returnValue
	end

	conferenceOptions={
				:mute=>false,
				:playTones=>true,
				:leaveprompt=>"beep"
				}

begin

#Create conference ID
 conferenceID = get_conference_id()

#Call First Leg (User)
	call 'tel:+1'+$numberToCall, {
	        :callerID => applicationCallerID,
	        :onAnswer => lambda{|event|
			log "@"*5 + "User has answered"
			#Create second thread for second leg (Operator)
			Thread.new do
				log "@"*5 + "Start second tread"
					call 'tel:+1'+operatorNumber, {
						:callerID=>applicationCallerID,
						:onAnswer=>lambda{|event|
							log "@"*5+"Operator answered join conference"
							newCall = event.value
							#announce caller
							newCall.say("You have a call from " + $callerName)
							#join operator to conference
							newCall.conference(conferenceID,conferenceOptions)
						}
					}
			end

			newCall = event.value
			# prompt user
			newCall.say("Please hold while we connect you")
			newCall.conference(conferenceID,conferenceOptions)
		}
	}
end

The only thing really not covered here is the fact that you need to have a conference to join the callers, and since we are using threads we need to make sure each one joins the right conference. This is done with the conference ID, and in my example we are going to use a time stamp, called from a method, as our conferenceID.

#Method to create timeStamp as our conferenceID
	def get_conference_id()
		timeVar  = Time.new
		returnValue = timeVar.strftime("%Y%H%M%S")
		return returnValue
	end

So I think this part is pretty simple, and I don’t think going in to much more then a ‘hey look at that, it’s that thing you like’ type of explanation is really needed here; Of course if I am wrong please comment below, or contact our support team, and we would be glad to offer more clarification.

So as a whole you can see the script is pretty simple, we just fire off an HTTP request to the session API which can be done by a form on our website (obviously you need to change the values highlighted here):

<form action="http://api.tropo.com/1.0/sessions" method="get" accept-charset="utf-8">
	<input type="text" name="numberToCall" value="4075551212"/><br>
	<input type="text" name="callerName" value="John"/><br>
	<input type="hidden" name="token" value="token_id_goes_here"/>
	<input type="hidden" name="action" value="create"/>
	<p><input type="submit" value="Continue &rarr;"></p>
</form>

Of if you want you can also use CURL as well:

curl -I "http://api.tropo.com/1.0/sessions?action=create&token=my_token_id_goes_here&numberToCall=4075551212&callerName=john"

You can even get real fancy and build an XML payload which you can then post to the sessions API (curl -d @token.xml “http://api.tropo.com/1.0/sessions”)

<session>
 <token>my_token_id_goes_here</token>
 <var name="callerName" value="John"/>
 <var name="numberToCall" value="4075551212"/>
</session>

Once we caller 1 has answered we do a Thread.new and call caller two, and then as mentioned above Thread.new instantly returns us the the first thread and then we join caller 1 to the conference. Then once caller two answers we announce caller 1′s name and join him to the waiting conference participant, pretty simple huh?

Well I really do hope this is helpful, and if there are any questions on any of this please let us know!

Regards,

John Dyer
Customer Engineer
Voxeo Support

International Male (Voices)

Tuesday, April 20th, 2010

Since going international a few weeks ago, we’ve had some requests for more text to speech (TTS) voices. In our launch, we provided eight female voices in various languages and dialects. A number of customers have inquired about male voices for those same dialects.

They’re available starting now. Just like the female voices, each male voice is identified by a character’s name. The new voices we’ve added are:

  • jorge – Castilian Spanish – Male
  • bernard – French – Male
  • dave – US English – Male
  • simon – British English – Male
  • stefan – German – Male
  • luca – Italian – Male
  • willem – Dutch – Male
  • carlos – Mexican Spanish – Male

To use one of the new voices, just add the character’s name to your text to speech command in Tropo. For example, in PHP, you can do…

<?php
answer();
say('Comment allez-vous?', array('voice' => 'bernard'));
say('ça va bien merci.', array('voice' => 'florence'));
?>

Or in Ruby, try:

answer
say "1 2 3 4 5 my name is Dave and I'm from the U S.", :voice => 'dave'
say "Hello, Dave. I'm Simon from London.", :voice => 'simon'

Want to use one of these languages in speech recognition? Our Automated Speech Recognition (ASR) platform recognizes all of the languages we can speak, regardless if if they’re said by a man or woman.

In JavaScript:

answer();
result=ask("Quel âge avez-vous?", {
  choices:"[1-3 digits]",
  recognizer:"fr-fr",
  voice:"bernard"
  } );
if (result.name=='choice') {
  say("C'est bon. Je suis " + result.value + " ans.", {voice:"bernard"})
}

The full list of voices and documentation of how to use various TTS voices is available under the say() function.

Tropo Developers Doing Great Write-ups!

Thursday, April 15th, 2010

We have had some great developer write-ups about Tropo this week, which we really appreciate. The first one is by The Technoverse Blog, which highlights the ability to do Unified Communications with the Tropo platform. To read it go here.

The second one, does a great job of giving an overview of how to use Tropo in many ways a developer would want to. @ananelson‘s write-up, Welcome to the Troposphere, goes on to show you how to write apps that allow you to leave voicemails, do currency conversions, listen to audio streams and conferencing. We also understand Ana did a great presentation on Tropo at the Girl Geek Dinner in Dublin last week.

Thanks! We love it when developers are passionate about our APIs.

Tropo Beta Gift

Monday, April 12th, 2010

To celebrate the production launch of Tropo, last week we sent out $10 via PayPal to everyone who had signed up for Tropo during our year-long public beta. It was our way of thanking people for helping out.

We’d love to sit down and have a cup of coffee with each of you, but since that’s not possible, we’re sending you $10. Have a cup of coffee (or three) on us.

It seems people aren’t used to generosity from a company. Reactions ranged from surprise, to thinking it was an April Fool’s joke, to outright suspicion that the PayPal payment notice email was some sort of phishing scam. A couple of people even felt guilty they hadn’t done anything with Tropo and returned the money or donated it to charity.

Rest assured, folks, this is real. Feel free to accept your PayPal payments and spend the money. No strings attached. We’re grateful for your help in testing out Tropo and recommending it to your friends and peers.

Some of our favorite reactions on Twitter:

Tropo sending us $10 bucks just for trying out their private beta, that is awful generous of them .. thx @tropoBranchcut

@tropo is awesome! They are giving me some coffee money for beta testing. Can’t wait to release our new SMS & VoIP features. - Josh Coats

@Voxeo @Tropo Thanks for build such a killer service. You rock.Terry Martin

Just got $10 via PayPal from @voxeo for testing @tropo. Now *that* is how you thank users. I can’t imagine it scales well, though.Gabe Kangas

Signup for beta. Profit. I got $10 for being in the @tropo beta program. Google, the ball’s in your court.Adam Meehan

Sweet! $10 from @voxeo for using @tropo in beta! I basically got paid to try out an awesome service!no.good.at.coding

Once again, thank you all for participating in Tropo’s beta period. We learned a lot and made some fantastic improvements to the service thanks to your feedback.

http://twitter.com/coffe4u/status/11324864968

Deutsch? French? Spanish? How To Use International Text-To-Speech (TTS) in Tropo Apps

Thursday, April 1st, 2010

Last week we announced that Tropo now included for free the ability to support Text-To-Speech in 8 languages. In this post, I want to show you how you can easily implement this in your Tropo app. First, though, if you want to hear the different voices, you can call these numbers now and try it out:

+1 (407) 374-9911
Skype: +990009369991430013
SIP: sip:9991430013@sip.tropo.com
iNum: +883510001805741

Here is what the JavaScript code looks like for that application (thanks to Voxeon Ron Blaisdell):

answer();
wait('500');

say("Hello world! This is a demonstration of the various voices & languages on Tropo.");

//English Female - Allison - en-us
say("1 2 3 4 5 this is Allison", { voice: 'allison' });

//Spanish Castillian Female - Carmen - es-es
say("1 2 3 4 5 this is Carmen", { voice: 'carmen' });

//French Female - Florence - fr-fr
say("1 2 3 4 5 this is Florence", { voice: 'florence' });

//English UK - Kate - en-uk
say("1 2 3 4 5 this is Kate", { voice: 'kate' });

//German Female - Katrin - de-de
say("1 2 3 4 5 this is Katrin", { voice: 'katrin' });

//Italian Female - Paola - it-it
say("1 2 3 4 5 this is Paola", { voice: 'paola' });

//Dutch Female - Saskia - nl-nl
say("1 2 3 4 5 this is Saskia", { voice: 'saskia' });

//American Spanish Female - Soledad - es-mx
say("1 2 3 4 5 this is Soledad", { voice: 'soledad' });

say("ta da");

hangup();

That’s literally all you need to do… add the { voice:'name' } parameter to the say function and there you go!

Now for those of you who don’t use JavaScript, the syntax is similar for the other languages.

Ruby:

say "J'aime les écureuils!", :voice => 'florence'
say "1 2 3 4 5 this in Florence", :voice => 'florence'

Python:

say ("Guten Tag!", {'voice':'katrin'})
say ("1 2 3 4 5 this is Katrin", {'voice':'katrin'})

Groovy:

say( "Hola, como estas?", [ 'voice':"carmen" ])
say( "1 2 3 4 5 this is Carmen", [ 'voice':"carmen" ])

PHP:

<?php say ("J'aime les écureuils!", array('voice'=>'florence')); ?>
<?php say ("1 2 3 4 5, this is Florence", array('voice'=>'florence')); ?>

That’s it! Simple and easy…

Today we support these languages and currently only female voices, but you can expect to see us releasing support for even more languages as well as male voices in the weeks and months ahead. And if you have a project that needs a specific voice, please do email our support team and let them know what you need.