Asterisk Manager Interface

Asterisk Manager Interface

There are principally two ways Adhearsion can control Asterisk: the Asterisk Gateway Interface protocol or the Asterisk Manager Interface protocol (henceforth referred to as AGI and AMI respectively). The AGI protocol is modeled after the CGI protocol and is bound to a particular call. When a call comes in, Asterisk itself establishes an AGI connection out to Adhearsion via a TCP socket.

Conversely, the AMI protocol is for other processes to connect into Asterisk following a 3rd Party Call Control model similar, but not compliant with, TSAPI. An AMI connection is therefore not bound to a particular call and, instead, allows the other process to manage global operations and query global state on the Asterisk server, as well as manage and receive events on individual calls. The AMI protocol itself is inconsistently designed, but painstaking effort has been made to make it consistent to Adhearsion users. For more information on the protocol per se, see this page.

With the AMI protocol, users can...

Here are a few ideas of how you might use AMI:

AMI is not configured by default with Asterisk though the steps to setting it up are all simple.

Configure Asterisk

Open the /etc/asterisk/manager.conf file in a text editor. You'll probably see a lot of commented-out lines (a ";" denotes a comment) and a "general" section similar to the following:

[general]
enabled = yes
port = 5038
bindaddr = 0.0.0.0
The enabled key must be set to yes, the port can be anything above 1024 and bindaddr should be something which your Adhearsion process can address. If you're running Adhearsion and Asterisk on the same machine, you can safely make bindaddr "127.0.0.1". If you bind to "127.0.0.1", you won't be able to access your Asterisk server's AMI port from another machine.

You'll also need to define an AMI user for your Adhearsion app. Below is an example.

[ahn_ami]
secret = iheartlolcats
read 	= system,call,log,verbose,command,agent,user
write 	= system,call,log,verbose,command,agent,user
Be sure you configure some permissions for your user account. The permission settings above provide complete access to the user account. You can limit the access a user has to AMI interface if you wish, provided you know exactly what actions they're restricting.

Configure Adhearsion

Enabling Adhearsion to use AMI is quite easy. In your Adhearsion application, open up config/startup.rb with a text editor and uncomment the line which looks similar to the following

config.asterisk.enable_ami :host     => '127.0.0.1', :events   => true,
                           :username => 'ahn_ami',   :password => 'iheartlolcats'
Make sure that the line remains below the config.enable_asterisk line.

Using AMI events

The Asterisk Manager Interface supports broadcasting Asterisk events as they occur in realtime. Adhearsion exposes these events very cleanly using its own internal events subsystem. For more information on how to make use of AMI events, see this wiki's page on Events.

Controlling Asterisk from Rails with Adhearsion

Adhearsion ships with custom DRb support, which allow us to interact with Adhearsion from another application. DRb allows an object in one Ruby process to invoke methods on an object in another Ruby process on the same or a different machine. Add the line below to config/startup.rb:

config.enable_drb :port => 8888
... replacing 8888 with whatever port you want to use, of course.

Next, in your separate Ruby process, add the following code. If you're using Rails, add this to the bottom of your Rails app's config/environment.rb file.

AdhearsionDRb = DRbObject.new_with_uri 'druby://localhost:8888'
AdhearsionDRb.introduce('SIP/first-person', 'ZAP/second-person')
The methods exposed to this remote DRbObject are defined in components using the methods_for(:rpc) do..end }} syntax. New Adhearsion apps come with the {{ami_remote component already installed and enabled which exposes certain AMI methods via Adhearsion's RPC system. If you wish to see other AMI-related abstractions that're available, take a look at the ami_remote component. Additionally, you can write you own component and expose new, custom abstractions of AMI very easily. See the Components page for more info.

AMI from a standalone Ruby script

Adhearsion's AMI library was designed to be very reusable. The examples/asterisk_manager_interface folder contains a few example Ruby scripts but here is one below.

require 'rubygems'
require 'adhearsion'
require 'adhearsion/voip/asterisk/manager_interface'

include Adhearsion::VoIP::Asterisk::Manager

asterisk = ManagerInterface.connect :host => "10.0.1.97", :username => "jicksta", :password => "roflcopter"

response = asterisk.send_action "Originate", "Channel" => "SIP/mytrunk",
    "Application" => "Playback", "Args" => "hello-world"

puts response.headers.inspect

Handling Future Resources

A Future Resource allows you to have an object updated on a future event. Adhearsion provides this capability to deal with the asynchronous nature of dealing with AMI requests and responses. An example of using this would be to launch a request for the status of a call channel over AMI. The AMI action 'Status' only returns that the action was accepted by the AMI, but the result of that status request comes back as a response event. If you call the method synchronously:

result = send_action_synchronously 'status', { :channel => 'SIP/teliax-011fc210' }
It is the same as the following:
my_future_resource = send_action_asynchronously 'status', { :channel => 'SIP/teliax-011fc210' }
result = my_future_resource.response
In the second case the thread will block until my_future_resource.response returns. Keep in mind that send_action is an alias for send_action_synchronously and to send asynchronously to use send_action_asynchronously.

Handling AMI Errors

When making an action request to the AMI using send_action or  send_action_asynchronously and the AMI raises an error as the response Adhearsion will trap this error and raise it as an exception. To handle this properly, you will want to use a begin/rescue clause to have access to that exception. This example will log the resulting response to the Status action to the log:

begin 
  Adhearsion::VoIP::Asterisk.manager_interface.send_action_synchronously 'status', { :channel => 'SIP/teliax-011fc210' }
rescue Adhearsion::VoIP::Asterisk::Manager::ManagerInterfaceError => error         
  ahn_log.statusrequest.debug error 
end

Asterisk disconnects

When you restart the Asterisk process or the Asterisk process crashes for whatever reason, Adhearsion may be in the middle of something important (e.g. something billable). This introduces a race condition in the way that Adhearsion talks to Asterisk. Below is a high-level explanation of how commands are sent and received over AMI with Adhearsion:

The race condition exists during these scenarios

The way to protect yourself from this is simple: don't kill a production system forcefully! You should route traffic around any Asterisk/Adhearsion instance that needs to be removed from the cluster until Adhearsion and Asterisk are completely idle. When doing a new deployment (say, an upgrade of Asterisk), you should stop Adhearsion and Asterisk, then start Asterisk first and Adhearsion second.

SuperManager

The examples above use Adhearsion's ManagerInterface class. This class was designed specifically to be a robust and consistent abstraction of the AMI protocol, though it requires thorough knowledge of the data which AMI requires and supplies.

To be fully consistent with Adhearsion's philosophy, the AMI protocol should be abstracted in such a way that everything is an object. For example, if you were to ask for the current channels on the Asterisk server, you should get back an Array of Channel objects, each of which having intuitive methods such as hangup() or channel_variables().

The SuperManager class will soon offer these very high-level, very intuitive abstractions of AMI. At the moment it's still under development and not available in the stable master branch of Adhearsion.


Browse Space

- Pages
- News
- Labels
- Attachments
- Bookmarks
- Mail
- Advanced
- Activity

Explore Confluence

- Popular Labels
- Notation Guide

Your Account

Log In

or Sign Up  

Other Features

Add Content