PHPAGI
phpagi-2.x
Class Documentation
phpagi-1.x
AGI
AGI_AsteriskManager
Project Links
Source Forge Project
CVS
Download
Bugs
Feature Requests
example config
|
configuration
the asterisk request
examples
Frequently Asked Quizles and erratic errata
Why doesn't DIAL or AbsoluteTimeout work?
Some people are getting stumped on why some Asterisk commands do not appear
to work from AGI.
Commands such as bsoluteTimeout or DIAL are Asterisk
Applications which have to be run using the AGI EXEC command. The AGI EXEC command should not be
confused with agi_exec, which executes AGI commands, not Asterisk
applications.
This means that you need to execute the AGI command EXEC to execute an
Asterisk application.
More information:
For example:
<?php $agi=new AGI();
/* The code below works */ $agi->agi_exec("EXEC AbsoluteTimeout 20"); // set the absolute timeout to 20 seconds $agi->agi_exec("EXEC DIAL SIP/261361@fwd.pulver.com"); /* The code below DOES NOT work $agi->agi_exec("AbsoluteTimeout 20"); // set the absolute timeout to 20 seconds $agi->agi_exec("DIAL SIP/261361@fwd.pulver.com");
*/ ?>
My AGI script isn't retrieving variables or is acting strangely
Make sure there is no leading or trailing white space in phpagi.php or your
AGI script. This includes blank lines.
If you have any blank lines or spaces after the last ?> closing tag in phpagi.php,
communications between your AGI script and Asterisk may fail.
Functions
<?php
$agi = new AGI($cfgfile="/etc/asterisk/phpagi.conf",$confarray=FALSE);
/* * creates a new AGI class. As part of the construction, phpagi also: * + Reads in the Asterisk request and stores the data in $agi->request * + Reads the configuration /etc/asterisk/phpagi.conf and stores the array in $agi->config * * * to specify an alternative configuration file, pass the file name to AGI() * the second parameter is an array of variables that are stored in $config['phpagi']. * */
?>
<?php /* Executes an Asterisk AGI command. */
$res = $agi->agi_exec("SET PRIORITY 5");
$res = $agi->agi_exec("EXEC DIAL sip/foo@foo.com");
/* * agi_exec returns an array containing: * * ['code'] = A 3 digit return code. * ['data'] = String data * [variable names] = individual variable=value pairs. */ ?>
<?php $res = $agi->agi_readresult($str=FALSE); /* * reads a response from asterisk (or parses the string '$str'; which * is intended for debugging purposes only). * * note: has multiline response support, but is bodgy. someone should fix it. * * * returns an array consisting of: */ array( "code" // numeric response code from asterisk (usually 200 if it worked), "result" // a numeric result code from asterisk (function specific) "data" // a string result returned from asterisk (ie: DATABASE GET) "$var" // any variable=value responses from asterisk (ie: STREAM FILE's endpos=1234) )
?>
<?php $res = $agi->agi_is_error($resparr); /* * returns TRUE or FALSE if the response $resparr (as returned from agi_readresult) * included a response code of 500, or a result code of -1 */ ?>
<?php $res = $agi->set_var("SOME_VAR","blah blah"); // set a variable in the dialplan
$codec = $agi->get_var("SIP_CODEC"); // get the value of SIP_CODEC ?>
<?php /* * AGI scripts can make requests to Asterisk to modify the dial plan * or run an Application. Responses to requests can be obtained using these * functions. */
$res = $agi->agi_response_code(); /* * returns the last response code received from asterisk */ $res = $agi->agi_response_result(); /* * returns the last response result recieved from asterisk */ $res = $agi->response_data(); /* * returns the last response text data received from asterisk */ $res = agi->response_var($var); /* * returns the value of "$var" from the last asterisk response, or FALSE if * $var was not returned. */ ?>
<?php $res = $agi->agi_getdtmf($len,$timeout,$terminator,$prompt=FALSE); /* * Plays back each file specified in $prompt (either a single file, or a group * of files as an array() * * Waits for $len DTMF tones to be entered, or until $terminator is pressed. * * Each DTMF digit must be entered after $timeout milliseconds. * * Returns an array() of digits entered. * * ie: */ ?>
<?php /* * returns the channel status of $channel as an array containing: * * * array( * "status" => status code (refer to agi reference) * "description" => human readable description of status * ) * */ $res=$agi->agi_channel_status($channel);
$res = $agi->hangup(); // hangup the current channel.
$res = $agi->set_callerid("6045551212"); // set the outgoing caller ID for this channel ?>
<?php $agi->conlog("This will display a message to the asterisk console if debugging is enabled.");
/* con_print_r will dump a variable to the asterisk console if debugging is enabled. potentially cpu unfriendly.*/ $arr=array( "some key"=>"some value" ); $agi->con_print_r($arr,"My array data");
// verbose will print a message to the console. Optional second parameter is the verbosity level. $agi->agi_verbose("This will display a message to the Asterisk console regardless of debugging"); ?>
<?php
$agi->saynumber("1234"); // speaks the number 1234 $agi->saydigits("1234"); // speaks the digits 1, 2, 3 and 4. $agi->saytime(); // speaks the current time.
$agi->text2wav("These are some words eh?"); // speaks the phrase "These are some words eh?" using Festival.
$agi->play("welcome"); // plays a file on the current channel.
/* Plays the prompt "say-something", then records up to 10000 milliseconds of audio to the file "somefile.gsm" */ $agi->recordfile("somefile","gsm",10000,"say-something");
?>
<?php /* Asterisk uses a database to store various bits of information.
Data is organized like so:
/FAMILY_NAME/Key Name/Some Value.
example:
/UserBalance/CustomerName/10.00 Key names can contain /'s:
/SIP/Registry/1006/192.168.5.1:5060:3600:1006
*/
// db_put($family,$key,$value) // stuff the caller id of the person calling me into the lastcalledme family.
$res=$agi->db_put("lastcalledme",$agi->request['agi_extension'],$agi->request['callerid']); // find out who last called me $res=$agi->db_get("lastcalledme",$agi->request['agi_extension']);
// delete the key $ret=$agi->db_del("lastcalledme",$agi->request['agi_extension']);
?>
<?php
// Using Asterisk's built in EnumLookup application
$res=$agi->agi_exec("EXEC EnumLookup 16049586111"); $agi->conlog("EnumLookup resolved the number to the VoIP URI: ".$agi->get_var("ENUM"));
// phpagi ENUM functions (CVS - Aug 29 2004)
/* * enum_lookup - performs an enum lookup and returns a sorted array. * * Array * ( * [0] => Array * ( * [order] => 100 * [prio] => 10 * [tech] => E2U+SIP * [URI] => sip/9586111@mutual.bcwireless.net * * ) * * ) * * NOTES: * - Presently requires external "dig" utility. PHP5 support for dns_get_record TBD * - Number passed to enum_lookup may or may not start with a '+' */ $enumres=$agi->enum_lookup("16049586111","e164.org");
if($enumres==FALSE){ // the query failed.
$agi->agi_play("enum-lookup-failed");
} else {
// something was returned, find an IAX or SIP record and dial it.
foreach($enumres as $key=>$row){
$tech = $row[tech]; $URI = $row[URI];
if(strstr($tech, "IAX") || strstr($tech, "SIP")) { $agi->agi_exec("DIAL \"$URI\""); $flush = trim(fgets($in,4096));
if($flush == "200 result=-1") $agi->set_var("PRIORITY", ($agi[priority] + 101) ); } } }
/* * enum_txtlookup - returns the value of a TXT record for a given phone number or FALSE if none found. * * NOTES: * - Presently requires external "dig" utility. PHP5 support for dns_get_record TBD * - Number passed to enum_lookup may or may not start with a '+' */
$res=$agi->enum_txtlookup("+16049586111","e164.org");
?>
<?php
$res = $agi->arr2str($arr); // convert array $arr to a string
$agi->goto($context,$ext='s',$pri=1); // moves in the dialplan to $context, default extension 's' and priority of 1.
$agi->agi_setlanguage($lang); // sets the current language to $lang. defaults to 'en'
$res=$agi->parse_callerid(); // parse a caller id string into distinct name and number elements. $agi->conlog("Callerid name is ".$res['name']." and number is ".$res['number']); ?>
Configuration
At construction time, phpagi will parse the contents of the INI style /etc/asterisk/phpagi.conf
and store the contents of the file as an array named $agi->config;
The format of the configuration file is:
[section]
variable=value
[other section]
foo=bar
and the config array will look something like:
array(
"section"=>array(
"variable"=>"value"
),
"other section"=>array(
"foo"=>"bar"
)
);
An example configuration file is
available.
To have phpagi parse a different file, pass the name of the file to the AGI constructor.
eg:
<?php $agi = new AGI("/some/other/file.conf"); ?>
Run-time variables can be specified as well. Pass an array of variables as the second
argument to the constructor. These values are stored in the above configuration
array within the element 'phpagi', therefor run-time configuration can
override the phpagi section of phpagi.conf.
<?php $cfgarray=array( "error_handler"=>"true", "good_beer"=>"winter solstace" );
$agi = new AGI(FALSE,$cfgarray); ?>
Here's a list of internal 'phpagi' variables.
Name | values | Description |
error_handler | "true"/"false" | Enable the phpagi error handler - logs php parse errors to asterisk | debug | "true"/"false" | Enable or disable debugging via conlog and conlog_print_r (defaults to "true") |
dig | | Full path to the 'dig' dns lookup utility (eg:
/usr/bin/dig |
Other variables:
Section | Name | Values | Description |
festival | text2wav | /usr/src/festival/bin/text2wave | Path to the text2wav script |
festival | tempdir | /var/lib/asterisk/sounds/tmp/ | Path to a temporary directory where text2wav can store files |
The Asterisk Request
When Asterisk calls the AGI script, it will pass a number of request variables to the script.
The variables are automatically read at phpagi construction time and are stored in
the variable $agi->request;
Example:
array(
'agi_request' => 'ping.php'
'agi_channel' => 'SIP/-080fc9d0'
'agi_language' => 'en'
'agi_type' => 'sip'
'agi_uniqueid' => '1069813784.9'
'agi_callerid' => 'Matthew
'agi_dnid' => 'unknown'
'agi_rdnis' => 'unknown'
'agi_context' => 'in-sip'
'agi_extension' => '*01'
'agi_priority' => '2'
'agi_enhanced' => '0.0'
'agi_accountcode' => ''
)
Obviousley the request passed will vary from call to call, and channel used. The example
above is from an incoming SIP call.
Examples
Example - Ping AP
#!/usr/local/bin/php -q <?php
require "phpagi.php";
$agi = new AGI(); $agi->agi_exec("ANSWER"); // Play the "Enter the host you wish to ping, followed by the pound sign" prompt // and then play the beep. $host=$agi->agi_getdtmf(20,3000,"#",array("ping","beep"));
// $host is an array loaded up with each character entered. // here we go through the array and turn it into a string. // could have used $agi->arr2str as well but i didn't.
foreach($host as $k) $ip.=$k;
// change the '*' to .
$ip=str_replace("*",".",$ip); /* Danger Will Robinson! This does NOT properly escape the ping command! * Someone could subvert your system if you don't fix this! - NO WARRANTY :P */ $execstr="/bin/ping -c 5 -q -w 9 $ip|grep transmitted"; // be polite. $agi->agi_exec("STREAM FILE thanks #"); $p=popen($execstr,"r"); if($p==FALSE){ $agi->conlog("Failed to ping $execstr"); exit; } while(!feof($p)){ $r=fgets($p,1024); if(!$r) break; $str.=$r; }
// a minor hack. $str=str_replace("ms","milli-seconds",$str); // have festival read back the ping results. $agi->text2wav("$ip - $str"); ?>
|