Posts Tagged ‘eventmachine’

WebSockets and Tropo, Putting the Real-Time in Your Communications

Thursday, December 16th, 2010

Interactive applications require low-latency, just like phone calls, in order to make them real-time and natural. While REST drives much of the APIs on the web today, sometimes it just adds too much overhead and therefore introduces latency. In steps WebSockets, a part of the HTML5 standard. WebSockets provide a persistent bi-directional connection between your users and yours services. Now, with Tropo, you may write real-time applications that provide snappy interactions to drive games, interactive billboards and just about any other interactive application that requires a great user experience.

An example of just such an application was one built by Manou Andraos and Melissa Mongiat for the Mutek BlocJam festival in Montreal in June 2010. They projected a musical collaboration interface onto a seven story building in downtown Montreal. Then published a phone number that people on the street could dial with their mobile phones and interact together in a public space to make music in real-time.

This project was built using Adhearsion, a project sponsored by Voxeo Labs, which allows for real-time streaming of user input to an application using Asterisk.

Tropo also allows for real-time streaming of user input from the cloud. While Tropo may do REST just fine, the real power in our platform is Tropo Scripting. By hosting your app on our application servers, you may wire your apps to the web the way you want. So, building on Chris Matthieu’s recent post on using XMPP to speak to the web, and my previous post for using TCP Sockets, we will now walk you through using WebSockets to drive your applications from the Tropo cloud.

We created a prototype that provides an example of how to stream real-time DTMF (those sounds your phone makes when hitting the keys) input from a user to your application over a WebSocket.

In the diagram above you may see that we created a ‘WebSocket Relay’ that takes two inbound WebSocket requests and relays them via a unique session to each other. This allows for applications behind firewalls to establish outbound connections, rather than having to accept inbound requests. For the relay we used EventMachine and the em-websocket gem. And for the Tropo Ruby script we used the web-socket-ruby gem (originally created by Hiroshi Ichikawa) to establish the outbound WebSocket from Tropo to the relay. Here is this scenario in action:

(The source code for the WebSocket Relay, the Tropo Ruby script and the HTML5 web page are available on Github here.)

The Tropo portion of the script that powers this is quite straight forward (full script here):

# Create a connection to the WebSocket server
client = WebSocket.new("ws://sandite.orl.voxeo.net:8082")

loop do
  result = ask "Press any digit, or press zero to end the session.", { :choices => "[1 DIGITS]" }
  msg = { :type => 'publisher', :id => 'tropo-app1', :data => { :caller_id => '4155551212', :command => result.value  } }.to_json
  client.send msg
  break if result.value == '0' || $currentCall.isActive == false
end

say 'Thank you for playing, goodbye.' if $currentCall.isActive

While the EventMachine WebSocket Relay portion is only 57 lines of code:

class SessionChannels
  def initialize
    @channels = {}
    @mutex = Mutex.new
  end

  def publish(id, message)
    create_channel id if @channels[id].nil?
    @channels[id].push message
  end

  def subscribe(id, socket)
    create_channel id if @channels[id].nil?
    @channels[id].subscribe { |msg| socket.send msg.to_json }
  end

  private

  def create_channel(id)
    @mutex.synchronize { @channels[id] = EM::Channel.new }
  end
end

@session_channels = SessionChannels.new

EM::WebSocket.start(APP_CONFIG['websocket']) do |socket|
  socket.onopen {
    ap "WebSocket connection open"
  }

  socket.onmessage { |msg|
    msg = JSON.parse msg
    case msg['type']
    when 'subscriber'
      @session_channels.subscribe(msg['id'], socket)
    when 'publisher'
      @session_channels.publish(msg['id'], msg['data'])
    end
  }

  socket.onclose { ap "Connection closed" }
end

Now all that limits you for creating interactive applications is your imagination. If you would like any additional insight or assistance in exploring this approach or others, please do not hesitate to reach out to us on ‘support@tropo.com‘.

Note: Recently a security issue was disocovered in the WebSocket protocol which has caused Firefox to remove WebSockets from their latest beta. While you may still use WebSockets in certain scenarios, the standard now appears to be in flux again. WebSockets will be around, albeit most likely with changes. We will be following this post up with a more detailed overview of how to use XMPP and BOSH from our network, as Tropo natively supports XMPP, to achieve the same real-time capabilities.

Use Node.js & Javascript to Write Your Tropo Apps

Friday, October 1st, 2010

Today we would like to announce the availability of the Tropo WebAPI Node library for Node.js and the Tropo WebAPI. I have had a lot of fun working with the author – Mark Headd – to both grok Node.js and play with Tropo using this rising star of a framework.

For those of you new to Node.js it is a server side evented Javascript framework. If you have ever used the Python Twisted framework, or Ruby’s Eventmachine, you already have an idea of what Node.js is. You may write asynchronous apps that easily handle sockets or HTTP using Javascript on both the server and the browser.

A nice compliment to Node.js, in the context of the Tropo WebAPI, is the Express.js framework. Express is to Node.js what Sinatra is to Ruby. You may easily assign clojures to your various REST resources and serve up an application in no time. Here is an example:

/**
 * Showing with the Express framwork http://expressjs.com/
 * Express must be installed for this sample to work
 */

require('../../lib/tropo-webapi');
var express = require('express');
var app = express.createServer();

/**
 * Required to process the HTTP body
 * req.body has the Object while req.rawBody has the JSON string
 */
app.configure(function(){
	app.use(express.bodyDecoder());
});

app.post('/', function(req, res){
	// Create a new instance of the TropoWebAPI object.
	var tropo = new TropoWebAPI();
	// Use the say method https://www.tropo.com/docs/webapi/say.htm
	tropo.say("Welcome to my Tropo Web API node demo.");

	// Demonstrates how to use the base Tropo action classes.
	var say = new Say("Please enter your 5 digit zip code.");
	var choices = new Choices("[5 DIGITS]");

	// Action classes can be passes as parameters to TropoWebAPI class methods.
	// use the ask method https://www.tropo.com/docs/webapi/ask.htm
	tropo.ask(choices, 3, false, null, "foo", null, true, say, 5, null);
	// use the on method https://www.tropo.com/docs/webapi/on.htm
	tropo.on("continue", null, "/answer", true);

    res.send(TropoJSON(tropo));
});

app.post('/answer', function(req, res){
	// Create a new instance of the TropoWebAPI object.
	var tropo = new TropoWebAPI();
	tropo.say("Your zip code is " + req.body['result']['actions']['interpretation']);

	res.send(TropoJSON(tropo));
});

app.listen(8000);
console.log('Server running on http://0.0.0.0:8000/')

So what are you waiting for? Go to Github and get started!

Stay tuned as Mark Headd cooks up more good stuff, I hear he might be doing some interesting things with CouchDB. Every developer community would be so lucky to have a member like him. Thanks Mark!

Using Persistent Sockets in Tropo.com Applications

Thursday, September 10th, 2009

While Tropo supports RESTful Web Services as a form of moving data to and from the communication cloud, it may not always be fast enough for all applications. There are apps that require the lowest possible latency, for example, when mobile devices become input devices. The unique approach of Tropo, allowing developers to host scripts in our cloud, allows you the ability to write applications that take direct advantage of persistent sockets. This means that you may open the socket once and then stream data to your remote application in realtime without having to establish HTTP connections each time.

I recently created an example of this using Ruby to serve a socket using EventMachine, and then writing a script on Tropo that opens a socket and sends touch-tones (DTMF) down the socket immediately as they come in. Here it is in action:

The code examples may be found here.