Getting Started with the PAMI: PHP Asterisk Manager Interface = Easy Asterisk MonitoringTweet
The PHP AMI client ideal to write Telephony Applications and Operator Panels
UPDATE: Check the slides about writing telephony applications using Asterisk, PHP, and PAGI and PAMI, at the PHP Conference Argentina 2013. You can download the slides, don't forget to see the notes! The complete talk is right there if you missed it :)
PAMI will let you use the AMI interface to control and monitor your asterisk box(es) in a pretty easy way. Also, it supports Asynchronous AGI, so its even suitable to create a complete IVR solution.
With PAMI you receive events, and send actions. Each action is a command (for example, issue a dial or hangup an ongoing call). The events, on the other hand, are issued by asterisk whenever something interesting occurs in the system.
You will send the actions through the pami client. This is a synchronous operation, the process will block until the response has arrived. To get the events, just register an event listener (more on this after the installation instructions).
Download PAMI for PHP
First, a couple of useful links:
- http://marcelog.github.com/PAMI/: The homepage.
- http://packagist.org/packages/marcelog/pami: Packagist home
- https://github.com/marcelog/PAMI/: The GitHub repository
- Full PAMI examples
- AMI Protocol article
- http://marcelog.github.com/articles/php_asterisk_listener_example_using_pami_and_ding.html: A more advanced pami application, using ding as DI container to capture events.
For PHP 5.3.9 and 5.3.10 users
NOTE:Be sure that your PHP version is not 5.3.9 or 5.3.10, beacuse they had a bug in stream_get_line() that will prevent PAMI from working correctly. Please use a different 5.3 or 5.4 version. If you really need a patch, just email me or see this.
PAMI is available via composer, please see the repo README file for instructions on how to use it.
Packagist URL: http://packagist.org/packages/marcelog/pami
Configure your Asterisk installation to accept connections from your PHP Application
In your manager.conf file, create a user with permissions to access ami. In the following example, the user admin, has ALL permissions granted (beware!). This is the username that we are going to use from pami:
Connecting to your Asterisk PBX from your PHP Application
- Open the connection to asterisk AMI
- Close the connection to asterisk AMI
- Register an event listener
- Unregister an event listener
In order to get the client instance and open the connection, you need to provide the connection options through an array:
Easy, isn't it?
Listening for specific Asterisk events in your PHP Application
In order to get events, you need to register an event listener. There are 3 possible ways to register an event listener, all of them using the registerEventListener() method of the IClient implementation, and your listener will receive EventMessage objects.
You can have as many listeners as you want, and mix them however you need.
- Register a Closure
- Register a specific method of an object
- Register an object, that implements IEventListener
In order for pami to receive the events, you need to periodically call the process() method, like:
If you dont like having a main loop like that, try using register_tick_function() instead:
This will require to use declare(ticks=1) at the top of your source file.
Sample Skeleton for a Telephony Application for Asterisk PBX
Filtering incoming events from your PBX
Up to now, we've only seen how to register event listeners. These listeners will receive ALL the events that get to pami. What happens if we only want some events, or there is some important condition to be met before receiving the events? That's where predicates come to the rescue. When registering an event listener, an optional closure can be passed as argument that will be the predicate. If the predicate returns true, the event will be dispatched. If the predicate returns false, the event wont get to the listener:
In this case, our predicate will only return true if and only if the event received is DialEvent, and the subevent type is a begin (i.e: an agi application has issued a Dial() command). You can only add 1 predicate (per listener, but you can have multiple listeners), but you can make it as complex as as you wish, and as a result, your event listener will be a little cleaner.
By the way, here are all the events available.
Send actions and commands that will be executed in your Asterisk PBX
You can also send actions to asterisk. An action is just an object of a given type. You can see all the actions available here and the asterisk wiki with their official list of actions. Let's send a Reload action:
The result of the action sent, will come as a Response message.
Start writing your own VoIP and Telephony Applications for the Asterisk PBX
PAMI is simple and straightforward. I hope you have fun using it, just as I had when writing it! A component like this can open a lot of new possibilities to your cli and webapp applications.