Asterisk Manager Interface (AMI)

Asterisk Manager Interface (AMI)

The Asterisk Manager Interface (AMI) is a system monitoring and management interface provided by Asterisk. It allows live monitoring of events that occur in the system,as well as enabling requests for Asterisk to perform some action. The available actions
are wide-ranging and include things such as returning status information and originating new calls. Many interesting applications have been developed on top of Asterisk that use the AMI as their primary interface to Asterisk.

Quick Start

This section is for getting your hands dirty with the AMI as quickly as possible. First, put the following configuration in /etc/asterisk/manager.conf:
;
; Turn on the AMI and ask it to only accept connections from localhost.
;
[general]
enabled = yes
webenabled = yes
bindaddr = 127.0.0.1

;
; Create an account called “hello”, with a password of “world”
;
[hello]
secret=world
read=all        ; Receive all types of events
write=all       ; Allow this user to execute all actions

Once the AMI configuration is ready, enable the built-in HTTP server by putting the following contents in /etc/asterisk/http.conf:
;
; Enable the built-in HTTP server, and only listen for connections on localhost.
;
[general]
enabled = yes
bindaddr = 127.0.0.1

AMI over TCP

There are multiple ways to connect to the AMI, but a TCP socket is the most common. We will use telnet to demonstrate AMI connectivity. This example shows these steps:

1. Connect to the AMI over a TCP socket on port 5038.
2. Log in using the Login action.
3. Execute the Ping action.
4. Log off using the Logoff action.

Here’s how the AMI responds to those actions:
$ telnet localhost 5038
Trying 127.0.0.1…
Connected to localhost.
Escape character is ‘^]’.
Asterisk Call Manager/1.1
Action: Login
Username: hello
Secret: world

Response: Success
Message: Authentication accepted

Action: Ping
Response: Success
Ping: Pong
Timestamp: 1282739190.454046

Action: Logoff

Response: Goodbye
Message: Thanks for all the fish.

Connection closed by foreign host.

Once you have this working, you have verified that AMI is accepting connections via a TCP connection.

AMI over HTTP

It is also possible to use the AMI over HTTP. In this section we will perform the same actions as before, but over HTTP instead of the native TCP interface to the AMI.

This example demonstrates how to access the AMI over HTTP, log in, execute the Ping action, and log off:

$ wget “http://localhost:8088/rawman?action=login&username=hello&secret=world” \
> –save-cookies cookies.txt -O –

–2010-08-31 12:34:23–
Resolving localhost… 127.0.0.1
Connecting to localhost|127.0.0.1|:8088… connected.
HTTP request sent, awaiting response… 200 OK
Length: 55 [text/plain]
Saving to: `STDOUT’

Response: Success
Message: Authentication accepted

2010-08-31 12:34:23 (662 KB/s) – written to stdout [55/55]

$ wget “http://localhost:8088/rawman?action=ping” –load-cookies cookies.txt -O –

–2010-08-31 12:34:23–
Resolving localhost… 127.0.0.1

Connecting to localhost|127.0.0.1|:8088… connected.
HTTP request sent, awaiting response… 200 OK
Length: 63 [text/plain]
Saving to: `STDOUT’

Response: Success
Ping: Pong
Timestamp: 1283258063.040293

2010-08-31 12:34:23 (775 KB/s) – written to stdout [63/63]

$ wget “http://localhost:8088/rawman?action=logoff” –load-cookies cookies.txt -O –

–2010-08-31 12:34:23–
Resolving localhost… 127.0.0.1
Connecting to localhost|127.0.0.1|:8088… connected.
HTTP request sent, awaiting response… 200 OK
Length: 56 [text/plain]
Saving to: `STDOUT’

Response: Goodbye
Message: Thanks for all the fish.

       2010-08-31 12:34:23 (696 KB/s) – written to stdout [56/56]
The HTTP interface to AMI lets you integrate Asterisk call control into a web service.-

Configuration

The section  showed a very basic set of configuration files to get you started. However, there are many more options available for the AMI.

manager.conf

The main configuration file for the AMI is /etc/asterisk/manager.conf. The [general] section contains options (listed in Table -1) that control the overall operation of the AMI. Any other sections in the manager.conf file will define accounts for logging in and using the AMI.

Table -1. Options in the manager.conf [general] section

1c1

1c2

1c3

The manager.conf configuration file also contains the configuration of AMI user accounts. An account is created by adding a section with the username inside square brackets. Within each [username] section there are options that can be set that will apply only to that account. Table -2 lists the options available in a [username] section.

Table -2. Options for [username] sections

1c4

1c5

As discussed in Table -2, the read and write options set which manager actions and manager events a particular user has access to. Table -3 shows the available permission values that can be specified for these options.

Table -3. Available values for AMI user account read/write option

1c6

1c7

http.conf

As we’ve seen, the Asterisk Manager Interface can be accessed over HTTP as well as TCP. To make that work, a very simple HTTP server is embedded in Asterisk. All of the options relevant to the AMI go in the [general] section of /etc/asterisk/http.conf.

The available options are listed in Table -4.

Table -4. Options in the http.conf [general] section

1c8

Protocol Overview

There are two main types of messages on the Asterisk Manager Interface: manager events and manager actions. Manager events are one-way messages sent from Asterisk to AMI clients to report something that has occurred on the system. See Figure -1 for a graphical representation of the transmission of manager events.

1c9

Figure -1. Manager events

Manager actions are requests from a client that have associated responses that come back from Asterisk. That is, a manager action may be a request that Asterisk perform some action and return the result. For example, there is an AMI action to originate a new call. See Figure -2 for a graphical representation of a client sending manager actions and receiving responses.

1c10Figure -2. Manager actions

Other manager actions are requests for data that Asterisk knows about. For example, there is a manager action to get a list of all active channels on the system: the details about each channel are delivered as a manager event. When the list of results is complete, a final message will be sent to indicate that the end has been reached. See Figure -3 for a graphical representation of a client sending this type of manager action and receiving a list of responses.

1c11

Figure -3. Manager actions that return a list of data

Message Encoding

All AMI messages, including manager events, manager actions, and manager action responses, are encoded the same way. The messages are text-based, with lines terminated by a carriage return and a line-feed character. A message is terminated by a blank line:

Header1: This is the first header<CR><LF>
Header2: This is the second header<CR><LF>
Header3: This is the last header of this message<CR><LF>
<CR><LF>

Events

Manager events always have an Event header and a Privilege header. The Event header gives the name of the event, while the Privilege header lists the permission levels associated with the event. Any other headers included with the event are specific to the event type. Here’s an example:

        Event: Hangup
Privilege: call,all
Channel: SIP/0004F2060EB4-00000000
Uniqueid: 1283174108.0
CallerIDNum: 2565551212

        CallerIDName: Russell Bryant
Cause: 16
Cause-txt: Normal Clearing

Asterisk 11 introduced the manager show events and manager show event <event> CLI commands. Run these commands at the Asterisk CLI to get a list of events or to find out the details of a specific event.

Actions

When executing a manager action, it must include the Action header. The Action header identifies which manager action is being executed. The rest of the headers are arguments to the manager action, and may or may not be required depending on the action.

To get a list of the headers associated with a particular manager action, type manager show command <Action> at the Asterisk command line. To get a full list of manager actions supported by the version of Asterisk you are running, enter manager show commands at the Asterisk CLI.

The final response to a manager action is typically a message that includes the Re sponse header. The value of the Response header will be Success if the manager action was successfully executed. If the manager action was not successfully executed, the value of the Response header will be Error . For example:

Action: Login
Username: russell
Secret: russell

Response: Success
Message: Authentication accepted

AMI over HTTP

In addition to the native TCP interface, it is also possible to access the Asterisk Manager Interface over HTTP. Programmers with previous experience writing applications that use web APIs will likely prefer this over the native TCP connectivity. While the TCP interface only offers a single type of message structure, AMI over HTTP offers a few encoding options. You can receive responses in the same format as the TCP interface, in XML, or as a basic HTML page. The encoding type is chosen based on a field in the request URL.

Authentication and session handling

There are two methods of performing authentication against the AMI over HTTP. The first is to use the Login action, similar to authentication with the native TCP interface.

Once successfully authenticated, Asterisk will provide a cookie that identifies the authenticated session. Here is an example response to the Login action that includes a session cookie from Asterisk:

$ curl -v “http://localhost:8088/rawman?action=login&username=hello&secret=world”

* About to connect() to localhost port 8088 (#0)
*Trying 127.0.0.1… connected
* Connected to localhost (127.0.0.1) port 8088 (#0)
> GET /rawman?action=login&username=hello&secret=worlda HTTP/1.1
> User-Agent: curl/7.19.7 (x86_64-pc-linux-gnu) libcurl/7.19.7
OpenSSL/0.9.8k zlib/1.2.3.3 libidn/1.15
> Host: localhost:8088
> Accept: */*
>
< HTTP/1.1 200 OK
< Server: Asterisk/SVN-branch-11-r378376
< Date: Tue, 07 Sep 2010 11:51:28 GMT
< Connection: close
< Cache-Control: no-cache, no-store
< Content-Length: 55
< Content-type: text/plain
< Cache-Control: no-cache;
< Set-Cookie: mansession_id=”0e929e60″; Version=1; Max-Age=60
< Pragma: SuppressEvents
<

Response: Success
Message: Authentication accepted
* Closing connection #0

The second authentication option is HTTP digest authentication. In this example, the  requested encoding type based on the request URL is rawman . To indicate that HTTP digest authentication should be used, prefix the encoding type in the request URL with an a :
curl -v –digest -u hello:world http://127.0.0.1:8088/arawman?action=ping

  • About to connect() to 127.0.0.1 port 8088 (#0)
  • Trying 127.0.0.1…
  • connected
  • Connected to 127.0.0.1 (127.0.0.1) port 8088 (#0)
  • Server auth using Digest with user ‘hello’
    > GET /arawman?action=ping HTTP/1.1
    > User-Agent: curl/7.27.0

Host: 127.0.0.1:8088
> Accept: */*
>
< HTTP/1.1 401 Unauthorized
< Server: Asterisk/SVN-branch-11-r378376
< Date: Thu, 17 Jan 2013 13:19:05 GMT
< Connection: close
< Cache-Control: no-cache, no-store
< Content-Length: 210
< WWW-authenticate: Digest algorithm=MD5, realm=”asterisk”, nonce=”55b30b6d”,
<
qop=”auth”, opaque=”55b30b6d”
< Content-type: text/html
<
* Closing connection #0
* Issue another request to this URL: ‘http://127.0.0.1:8088/arawman?action=ping’
* About to connect() to 127.0.0.1 port 8088 (#0)
*
Trying 127.0.0.1…
* connected
* Connected to 127.0.0.1 (127.0.0.1) port 8088 (#0)
* Server auth using Digest with user ‘hello’
> GET /arawman?action=ping HTTP/1.1
> Authorization: Digest username=”hello”, realm=”asterisk”, nonce=”55b30b6d”,
>
uri=”/arawman?action=ping”, cnonce=”MTQ0MTQ5″, nc=00000001,
>
qop=auth, response=”df8edf75f3571ad425cacb975d09280b”,
>
opaque=”55b30b6d”, algorithm=”MD5″
> User-Agent: curl/7.27.0
> Host: 127.0.0.1:8088
> Accept: */*
>
< HTTP/1.1 200 OK
< Server: Asterisk/SVN-branch-11-r378376
< Date: Thu, 17 Jan 2013 13:19:05 GMT
< Connection: close
< Cache-Control: no-cache, no-store
< Content-Length: 63
< Content-type: text/plain
<
Response: Success
Ping: Pong
Timestamp: 1358428745.481800

* Closing connection #0

/rawman encoding

The rawman encoding type is what has been used in all the AMI over HTTP examples in this chapter so far. The responses received from requests using rawman are formatted in the exact same way that they would be if the requests were sent over a direct TCP connection to the AMI.

          /manager encoding

The manager encoding type provides a response in simple HTML form. This interface is primarily useful for experimenting with the AMI. Here is an example Login using this encoding type:

$ curl -v “http://localhost:8088/manager?
> “action=login&username=hello&secret=world”
* About to connect() to localhost port 8088 (#0)
*Trying 127.0.0.1… connected
* Connected to localhost (127.0.0.1) port 8088 (#0)
> GET /manager?action=login&username=hello&secret=world HTTP/1.1
> User-Agent: curl/7.19.7 (x86_64-pc-linux-gnu) libcurl/7.19.7
OpenSSL/0.9.8k zlib/1.2.3.3 libidn/1.15
> Host: localhost:8088
> Accept: */*
>
< HTTP/1.1 200 OK
< Server: Asterisk/SVN-branch-11-r378376
< Date: Tue, 07 Sep 2010 12:19:05 GMT
< Connection: close
< Cache-Control: no-cache, no-store
< Content-Length: 881
< Content-type: text/html
< Cache-Control: no-cache;
< Set-Cookie: mansession_id=”139deda7″; Version=1; Max-Age=60
< Pragma: SuppressEvents
<

<title>Asterisk&trade; Manager Interface</title><body bgcolor=”#ffffff”>
<table align=center bgcolor=”#f1f1f1″ width=”500″>
<tr><td colspan=”2″ bgcolor=”#f1f1ff”><h1>Manager Tester</h1></td></tr>
<tr><td colspan=”2″ bgcolor=”#f1f1ff”><form action=”manager” method=”post”>
Action: <select name=”action”>
<option value=””>—–&gt;</option>
<option value=”login”>login</option>
<option value=”command”>Command</option>
<option value=”waitevent”>waitevent</option>
<option value=”listcommands”>listcommands</option>
</select>
or <input name=”action”><br/>
CLI Command <input name=”command”><br>
user <input name=”username”> pass <input type=”password” name=”secret”><br>
<input type=”submit”>
</form>
</td></tr>
<tr><td>Response</td><td>Success</td></tr>
<tr><td>Message</td><td>Authentication accepted</td></tr>
<tr><td colspan=”2″><hr></td></tr>
* Closing connection #0
</table></body>

/mxml encoding

The mxml encoding type provides responses to manager actions encoded in XML. Here is an example Login using the mxml encoding type:
$ curl -v “http://localhost:8088/mxml?action=login&username=hello&secret=world”
* About to connect() to localhost port 8088 (#0)
*Trying 127.0.0.1… connected
* Connected to localhost (127.0.0.1) port 8088 (#0)
> GET /mxml?action=login&username=hello&secret=world HTTP/1.1
> User-Agent: curl/7.19.7 (x86_64-pc-linux-gnu) libcurl/7.19.7
OpenSSL/0.9.8k zlib/1.2.3.3 libidn/1.15
> Host: localhost:8088
> Accept: */*
>
< HTTP/1.1 200 OK
< Server: Asterisk/SVN-branch-11-r378376
< Date: Tue, 07 Sep 2010 12:26:58 GMT
< Connection: close
< Cache-Control: no-cache, no-store
< Content-Length: 146
< Content-type: text/xml
< Cache-Control: no-cache;
< Set-Cookie: mansession_id=”536d17a4″; Version=1; Max-Age=60
< Pragma: SuppressEvents
<

<ajax-response>
<response type=’object’ id=’unknown’>
<generic response=’Success’ message=’Authentication accepted’ />
</response>
* Closing connection #0
</ajax-response>

Manager events

When connected to the native TCP interface for the AMI, manager events are delivered asynchronously. When using the AMI over HTTP, events must be retrieved by polling for them. Events are retrieved over HTTP by executing the WaitEvent manager action. The following example shows how events can be retrieved using the WaitEvent manager action. The steps are:
1. Start an HTTP AMI session using the Login action.
2. Register a SIP phone to Asterisk to generate a manager event.
3. Retrieve the manager event using the WaitEvent action.

The interaction looks like this:
$ wget –save-cookies cookies.txt \
> “http://localhost:8088/mxml?action=login&username=hello&secret=world” -O –
<ajax-response>
<response type=’object’ id=’unknown’>
<generic response=’Success’ message=’Authentication accepted’ />
</response>
</ajax-response>
$ wget –load-cookies cookies.txt \
< “http://localhost:8088/mxml?action=waitevent” -O –
<ajax-response>
<response type=’object’ id=’unknown’>
<generic response=’Success’ message=’Waiting for Event completed.’ />
</response>
<response type=’object’ id=’unknown’>
<generic event=’PeerStatus’ privilege=’system,all’
channeltype=’SIP’ peer=’SIP/0000FFFF0004′
peerstatus=’Registered’ address=’172.16.0.160:5060′ />
</response>
<response type=’object’ id=’unknown’>
<generic event=’WaitEventComplete’ />
</response>
</ajax-response>

Call Files

Before we go into examples of using the AMI, it is worth talking about call files. Many people look at the AMI for originating calls. For many situations, it’s easier to use call files. A call file is a simple text file that describes the call that you would like Asterisk to originate. After the call file is created, you move it into the /var/spool/asterisk/outgoing directory. Asterisk will detect that a file has been placed there and will process the call promptly.

To use call files, Asterisk must load the pbx_spool module. Run the following command at the Asterisk CLI to verify that the module is loaded. If the module is not loaded, check the modules configuration file, /etc/asterisk/modules.conf:
*CLI> module show like spool
Module                           Description                                             Use Count
pbx_spool.so                  Outgoing Spool Support                                 0
1 modules loaded

Asterisk comes with a sample call file. You can find the sample.call file in the root directory of the Asterisk source tree.

Call files have a simple syntax. You can place comments in the file by preceding the comment with a # . The options specified in the file are key/value pairs, separated by a colon. For example:
# This is a comment

       Option: Value

Table -5 describes the options that may be specified in a call file.

Table -5. Call file options

1c12

1c13

Here is an example of creating a call file and then placing it in the proper directory so Asterisk will process it:

$ cat > demo-congrats.call << EOF
> Channel: SIP/someone@shifteight.org
> Application: Playback
> Data: demo-congrats
> CallerID: Asterisk <(555) 555-1212>
> EOF
$ mv demo-congrats.call /var/spool/asterisk/outgoing/

Example Usage

Most of this yopic so far discussed the concepts and configuration related to the AMI. This section will provide some example usage.

Originating a Call

The AMI has the Originate manager action that can be used to originate a call. Many of the accepted headers are the same as the options placed in call files. Table 20-6 lists the headers accepted by the Originate action.

Table -6. Headers for the Originate action

1c14

1c15

The simplest example of using the Originate action is via telnet:

$ telnet localhost 5038
Trying 127.0.0.1…
Connected to localhost.
Escape character is ‘^]’.
Asterisk Call Manager/1.3
Action: Login
Username: hello
Secret: world
Response: Success
Message: Authentication accepted
Action: Originate
Channel: Local/loop@test
Application: Playback
Data: demo-congrats
Response: Success
Message: Originate successfully queued
^]
telnet> quit
Connection closed.

Redirecting a Call

Redirecting (or transferring) a call from the AMI is another feature worth mentioning. The Redirect AMI action can be used to send one or two channels to any other extension in the Asterisk dialplan. If you need to redirect two channels that are bridged together, do them both at the same time. Otherwise, once one channel has been redirected, the other will be hung up.

To redirect a single channel:

Action: Redirect
Channel: SIP/myphone-0011223344
Exten: 1234
Context: default
Priority: 1

To redirect two channels:

Action: Redirect
Channel: SIP/myphone-0011223344
Context: default
Exten: 1234
Priority: 1
ExtraChannel: SIP/otherphone-0011223344
ExtraContext: default
ExtraExten: 5678
ExtraPriority: 1

One fairly common use of the redirect action from an external application is to redirect both parties of a call into a conference bridge. Place this context in your dialplan:
[confbridge]

     exten => _X.,1,ConfBridge(${EXTEN})

You could now redirect any two callers into a conference bridge using something like this:

Action: Redirect
Channel: SIP/myphone-0011223344
Context: confbridge
Exten: 1234
Priority: 1
ExtraChannel: SIP/otherphone-0011223344
ExtraContext: confbridge
ExtraExten: 1234
ExtraPriority: 1

Now other callers could join this bridge, or the external application using the AMI could proceed to redirect other channels to this bridge.

Originating a Call Using Python and StarPy

To help further demonstrate the use of the Originate action, we have provided a script that uses it. It can be downloaded from https:// github.com/russellb/amiutils. To get an idea of the usage of the example application, here is the help output:

$ ./amioriginate.py –help
Usage: amioriginate.py [options] <channel>

This program is used to originate a call on an Asterisk server using the Asterisk Manager Interface (AMI). The channel argument to this application tells Asterisk what outbound call to make. There are various options that can be used to specify what the outbound call is connected to once it answers.

Options:
-h, –help                                                           show this help message and exit
-d, –debug                                                        Enable debug output
-u USERNAME,                    –username=USERNAME
AMI username
-p PASSWORD,                    –password=PASSWORD
AMI password

-H HOST, –host=HOST Hostname or IP address of the Asterisk server
-t PORT, –port=PORT Port number for the AMI
-a APPLICATION, –application=APPLICATION
Application to connect the call to. When using this
option, you may also specify arguments to the
application with the -D/–data option. Do not use this
option and the context, extension, and priority
options at the same time.
-D DATA, –data=DATA Arguments to pass to the dialplan application
specified with -a/–application.
-c CONTEXT, –context=CONTEXT
Context in the dialplan to send the call to once it
answers. If using this option, you must also specify
an extension and priority. Do not specify the
application or data options if using this option.
-e EXTEN, –extension=EXTEN
Extension to connect the call to. This should be used
along with the context and priority options.
-P PRIORITY, –priority=PRIORITY
Priority of the extension to connect the call to. This
should used along with the context and extension
options.

If you run the utility in debug mode, you can see the raw AMI message exchange. First, here is an example of using the script to originate a call and connect it to an application. The MSG OUT and Line In lines in the output identify the AMI exchange. The MSG OUT lines are showing the AMI action in an internal format to the application instead of the raw AMI format, but you can still see the headers and their values. The Line In lines show the raw TCP response from Asterisk. The output shows:

1. The application requests to log into the AMI.
2. Asterisk responds, accepting the authentication request.
3. The application sends a request to originate a call.
4. Asterisk responds indicating that the origination request has been successfully processed. The call will occur asynchronously since the originate request included Async: True . Otherwise, we would not get a response until the outbound call either answers or fails for some reason.

$ ./amioriginate.py -d -u hello -p world \
> -a playback -D demo-congrats SIP/myphone

DEBUG:AMI:MSG OUT: {‘action’: ‘login’, ‘username’: ‘hello’, ‘secret’: ‘world’,
‘actionid’: ‘rhel6.3-server-28064728-1’}

DEBUG:AMI:Line      In:         ‘Asterisk Call Manager/1.3’
DEBUG:AMI:Line      In:    ‘Response: Success’
DEBUG:AMI:Line      In:   ‘ActionID: rhel6.3-server-28064728-1’
DEBUG:AMI:Line      In:  ‘Message: Authentication accepted’
DEBUG:AMI:Line      In: ”

DEBUG:AMI:MSG OUT: {‘application’: ‘playback’,
‘actionid’: ‘rhel6.3-server-28064728-2’,
‘variable’: ”, ‘async’: ‘True’, ‘data’: ‘demo-congrats’,
‘action’: ‘originate’, ‘channel’: ‘SIP/myphone’}

DEBUG:AMI:Line   In:  ‘Response: Success’
DEBUG:AMI:Line   In:   ‘ActionID: rhel6.3-server-28064728-2’
DEBUG:AMI:Line   In:   ‘Message: Originate successfully queued’
DEBUG:AMI:Line   In:   ”

Example -1. amioriginate.py
#!/usr/bin/env python

# Copyright (C) 2012, Russell Bryant
# Licensed under the Apache License, Version 2.0 (the “License”); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an “AS IS” BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.

”’Originate a call on an Asterisk server
Developed as an example for “Asterisk: The Definitive Guide”
”’
import  getpass
import  logging
import  optparse
import  sys

import starpy.manager
from twisted.internet import reactor

LOG = logging.getLogger(__name__)

 class OriginateCall(object):
def __init__(self, options, channel):
self.options = options
self.channel = channel
self.ami = starpy.manager.AMIFactory(self.options.username,
self.options.password)

def _on_login(self, ami):
kwargs = dict(channel=self.channel, async=True)

if self.options.application:
kwargs[‘application’] = self.options.application
kwargs[‘data’] = self.options.data

else:
kwargs[‘context’] = self.options.context
kwargs[‘exten’] = self.options.exten
kwargs[‘priority’] = self.options.priority

def _on_success(ami):
reactor.stop()

def _on_error(reason):
LOG.error(‘Originate failed: %s’ % reason.getErrorMessage())
reactor.stop()

              ami.originate(**kwargs).addCallbacks(_on_success, _on_error)

def connect_and_call(self):
def _on_login_error(reason):
LOG.error(‘Failed to log in: %s’ % reason.getErrorMessage())
reactor.stop()

       df = self.ami.login(self.options.host, self.options.port)
df.addCallbacks(self._on_login, _on_login_error)

def main(argv=None):

     if argv is None:
argv = sys.argv

logging.basicConfig(level=logging.INFO)

description = (‘This program is used to originate a call on an Asterisk ‘
‘server using the Asterisk Manager Interface (AMI). The ‘
‘channel argument to this application tells Asterisk what ‘
‘outbound call to make. There are various options that ‘
‘can be used to specify what the outbound call is ‘
‘connected to once it answers.’)
usage = ‘%prog [options] <channel>’

parser = optparse.OptionParser(description=description, usage=usage)

parser.add_option(‘-d’, ‘–debug’, action=’store_true’,
dest=’debug’, help=’Enable debug output’)

parser.add_option(‘-u’, ‘–username’, action=’store’, type=’string’,
dest=’username’, default=None, help=’AMI username’)

parser.add_option(‘-p’, ‘–password’, action=’store’, type=’string’,
dest=’password’, default=None, help=’AMI password’)

parser.add_option(‘-H’, ‘–host’, action=’store’, type=’string’,
dest=’host’, default=’localhost’,
help=’Hostname or IP address of the Asterisk server’)

parser.add_option(‘-t’, ‘–port’, action=’store’, type=’int’,
dest=’port’, default=5038,
help=’Port number for the AMI’)

parser.add_option(‘-a’, ‘–application’, action=’store’, type=’string’,
dest=’application’, default=”,
help=’Application to connect the call to. When using ‘
‘this option, you may also specify arguments to ‘
‘the application with the -D/–data option. Do ‘
‘not use this option and the context, extension, ‘
‘and priority options at the same time.’)

parser.add_option(‘-D’, ‘–data’, action=’store’, type=’string’,
dest=’data’, default=”,
help=’Arguments to pass to the dialplan application ‘
‘specified with -a/–application.’)

parser.add_option(‘-c’, ‘–context’, action=’store’, type=’string’,
dest=’context’, default=”,
help=’Context in the dialplan to send the call to ‘
‘once it answers. If using this option, you ‘
‘must also specify an extension and priority. ‘
‘Do not specify the application or data options ‘
‘if using this option.’)

parser.add_option(‘-e’, ‘–extension’, action=’store’, type=’string’,
dest=’exten’, default=”,
help=’Extension to connect the call to. This should ‘
‘be used along with the context and priority ‘
‘options.’)

parser.add_option(‘-P’, ‘–priority’, action=’store’, type=’string’,
dest=’priority’, default=”,
help=’Priority of the extension to connect the call ‘
‘to. This should used along with the context ‘
‘and extension options.’)
(options, args) = parser.parse_args(argv)

if options.debug:
LOG.setLevel(logging.DEBUG)
starpy.manager.log.setLevel(logging.DEBUG)

if len(args) != 2 or not len(args[1]):
LOG.error(‘Please specify a single outbound channel.’)
parser.print_usage()
return 1
channel = args[1]

valid_application = len(options.application)
valid_extension = (len(options.context) and len(options.exten) and
len(options.priority))

if not valid_application and not valid_extension:
LOG.error(‘Please specify a valid point to connect the call to once ‘
‘it answers. Either specify an application or a context, ‘
‘extension, and priority.’)
parser.print_usage()
return 1

if valid_application and valid_extension:
LOG.error(‘Please specify only one of extension and application.’)
parser.print_usage()
return 1

if not options.username:
user = raw_input(‘Username [%s]: ‘ % getpass.getuser())
if not user:
user = getpass.getuser()
options.username = user

if not options.password:
options.password = getpass.getpass()

o = OriginateCall(options, channel)
reactor.callWhenRunning(o.connect_and_call)
reactor.run()

return 0

if __name__ == ‘__main__’:
sys.exit(main())

Development Frameworks

Many application developers write code that directly interfaces with the AMI. However, there are a number of existing libraries that aim to make writing AMI applications easier. Table -7 lists a few that we know are being used successfully. If you search for Asterisk libraries in any popular programming language of your choice, you are likely to find one.

Table -7. AMI development frameworks

1c18

CSTA

Computer-Supported Telecommunications Applications (CSTA) is a standard for Computer Telephony Integration (CTI) that is used by multiple manufacturers. Some of what is provided by CSTA can be mapped to operations available in the AMI. There have
been multiple efforts to provide a CSTA interface to Asterisk, including the Open CSTA project. While none of the authors have experience with this CSTA interface to Asterisk, it is certainly worth considering if you have CSTA experience or an existing CSTA application you would like to integrate with Asterisk.

Interesting Applications

Many useful applications have been developed that take advantage of the AMI. Here is one example.

Flash Operator Panel

Flash Operator Panel is an application that runs in a web browser using Flash. It is primarily used as an interface to see which extensions are currently ringing or in use. It also includes the ability to monitor conference-room and call-queue status. Some call actions can be performed as well, such as barging into a call and transferring calls. Figure -4 shows the Flash Operator Panel interface.

Downloads and more detailed information on Flash Operator Panel can be found at http://www.asternic.org and http://www.fop2.com.

1c16

Figure -4. Flash Operator Panel