Asterisk Gateway Interface ( AGI ) là một chuẩn giao tiếp với Asterisk . AGI cho phép Astersik gọi thực thi một chƣơng trình ngoài để mở rộng nhiều chức năng của Astersik nhƣ điều khiến các kệnh thoại , phát âm thanh , đọc số DTMF , liên kết với cơ sở dữ liệu …. Các chƣơng trình ngoài đƣợc gọi là AGI Script , ta có thể lập trình ra các AGI Script bằng nhiều ngôn ngữ lập trình khác nhau nhƣ Perl, PHP, C, C#, Java.
Trong lập trình giao tiếp với Asterisk, cần phân biệt hai khái niệm API và AGI. API là giao diện lập trình ứng dụng, thƣờng đƣợc cung cấp dƣới dạng đầu vào là các lời gọi hàm đến một thƣ viện nào đó của ứng dụng. Còn AGI thực chất cung cấp cho lập trình viên một kênh giao tiếp với Asterisk thông qua các con trỏ file (file Pointer) là STDIN, STDOUT, STDERR. Vì vậy công việc lập trình cũng trở nên đơn giản hơn vì không phải đính kèm với một thƣ viện nào của Asterisk.
Khi bắt đầu mỗi script, Asterisk sẽ truyền các biến môi trƣờng và giá trị của nó đến AGI script. Ví dụ:
agi_request: quangtangamnhac.php agi_channel: Zap/1-1
Chương IV : Xây dựng trung tâm quà tặng âm nhạc trên nền Asterisk agi_language: vi agi_callerid: agi_context: default agi_extension: 123 agi_priority: 2
Sau khi truyền các biến này thì Asterisk sẽ gửi một dòng trống để dánh dấu kết thúc các biến môi trƣờng và chuyển quyền điều khiển cho script.
Trong file cấu hình extensions.conf, ta gọi script nhƣ sau:
[default] exten => 123,1,Answer( ) exten => 123,2,AGI(quatangamnhac.php) File quatangamnhac.php #!/usr/bin/php -q <?php { $link=mysql_connect("localhost","root","quangngai");
if(!$link){die("Could not connect to MySQL");}
mysql_select_db("kuhan",$link) or die ("could not open db".mysql_error()); $parm_error_log = '/tmp/qtangamnhac.log'; $parm_debug_on = 1; $parm_temp_dir = '/tmp'; $parm_call_dir = '/var/spool/asterisk/outgoing'; $parm_maxretries = 3; $parm_waittime = 60; $parm_retrytime = 60;
Chương IV : Xây dựng trung tâm quà tặng âm nhạc trên nền Asterisk
$parm_wakeupcallerid = 'quatangamnhac'; $parm_chan_ext = 0;
// --- // END CONFIG PARMS
//---
GLOBAL $stdin, $stdout, $stdlog, $result, $parm_debug_on, $parm_test_mode; // These setting are on the WIKI pages http://www.voip-info.org
ob_implicit_flush(false); set_time_limit(30); error_reporting(0);
$stdin = fopen( 'php://stdin', 'r' ); $stdout = fopen( 'php://stdout', 'w' ); if ($parm_debug_on)
{
$stdlog = fopen( $parm_error_log, 'w' ); fputs( $stdlog, "---Start---\n" );
}
// ASTERISK * Sends in a bunch of variables, This accepts them and puts them in an array
// http://www.voip-info.org/tiki-index.php?page=Asterisk%20AGI%20php while ( !feof($stdin) )
{
$temp = fgets( $stdin ); if ($parm_debug_on)
Chương IV : Xây dựng trung tâm quà tặng âm nhạc trên nền Asterisk
fputs( $stdlog, $temp );
// Strip off any new-line characters $temp = str_replace( "\n", "", $temp ); $s = explode( ":", $temp ); $agivar[$s[0]] = trim( $s[1] ); if ( ( $temp == "") || ($temp == "\n") ) { break; } } $channel = $agivar[agi_channel];
if (preg_match('.^([a-zA-Z]+)/([0-9]+)([0-9a-zA-Z-]*).', $channel, $match) ) {
$sta = trim($match[2]); $chan = trim($match[1]); }
$callerid = $agivar[agi_callerid];
if (preg_match('/<([ 0-9]+)>/', $callerid, $match) ) {
$cidn = trim($match[1]); }
else {
Chương IV : Xây dựng trung tâm quà tặng âm nhạc trên nền Asterisk { $cidn = trim($match[1]); } else $cidn = -1; }
// Check if we have an outstanding Wakeup Call file if ( $parm_chan_ext )
$dir_check = "$chan.$sta.call"; else
$dir_check = "ext.$cidn.call"; if ($parm_debug_on)
fputs( $stdlog, "Checking Directory [$parm_call_dir] Check=[$dir_check]\n" );
$outc=0;
$dir_handle = opendir( $parm_call_dir ); while( $file = readdir($dir_handle ) ) {
if ($parm_debug_on)
fputs( $stdlog, "File=$file\n" ); if (strstr( $file, $dir_check ) ) $out[$outc++] = $file; }
Chương IV : Xây dựng trung tâm quà tặng âm nhạc trên nền Asterisk
//========================================================== ===============
// This is where we interact with the caller. Answer the phone and so on
//========================================================== ===============
$rc = execute_agi( "ANSWER "); sleep(1);
if ( !$rc[result] )
$rc = execute_agi( "STREAM FILE chaomung \"\" "); $rc[result] = 0;
while ( !$rc[result] ) {
$rc = execute_agi( "STREAM FILE auth-thankyou \"0123456789\" "); if ( !$rc[result] )
$rc = execute_agi( "STREAM FILE nhapgio \"0123456789\" "); // If we get here, they haven't pressed anything yet.
if ( !$rc[result] )
$rc = execute_agi( "GET DATA beep 15000 4"); if ( $rc[result] != -1 )
{
if ($parm_debug_on)
fputs( $stdlog, "We have num digits:" . strlen( $rc[result]) . "- $rc[result] \r\n\r\n" );
Chương IV : Xây dựng trung tâm quà tặng âm nhạc trên nền Asterisk
if ( strlen( $rc[result] ) == 2 ) {
$num= $rc[result]-48;
while ( strlen($num) < 4 && $rc[result] > 0 ) {
$rc = execute_agi( "WAIT FOR DIGIT 15000"); if ( $rc[result] >= 48 && $rc[result] <= 57 ) $num .= $rc[result] - 48; else $rc[result] = 0; } if (strlen($num) == 4 ) $rc[result] = $num; } if ($parm_debug_on)
fputs( $stdlog, "Checking Results [$rc[result]] \r\n\r\n" );
if ( $rc[result] > 2359 || strlen( $rc[result]) < 4 || substr($rc[result],2,2) > 59 || $rc[result] < 0)
{
$rc[result] = 0;
$rc = execute_agi( "STREAM FILE auth-thankyou \"\" "); }
Chương IV : Xây dựng trung tâm quà tặng âm nhạc trên nền Asterisk
if (strlen( $rc[result] ) == 4 && $rc[result] == 0 ) $rc[result] = -2; // Special 00:00 time
} }
if ( $rc[result] == -2 ) $rc[result] = '0000'; else if ( $rc[result] == -1 )
exit; // The user hung up // Save the time entered
$wtime = $rc[result];
// We don't know who the user is, so if its less than 1300 it could be AM or PM, so prompt
// them for am pm
if ( $wtime != -1 && $wtime < 1300 ) {
$rc[result] = 0; while ( !$rc[result] ) {
if ( !$rc[result] )
$rc = execute_agi( "GET DATA sangchieu 15000 1"); }
switch( $rc[result] ) {
Chương IV : Xây dựng trung tâm quà tặng âm nhạc trên nền Asterisk
if ( $wtime > 1159 ) $wtime -= 1200; $rc[result] = 0; break;
case '2': // Set to PM should be equal or over 1200 if ( $wtime < 1159 ) $wtime += 1200; $rc[result] = 0; break; } } $rc[result] = 0; while ( !$rc[result] ) {
$rc = execute_agi( "STREAM FILE soduocgoi \"0123456789\" "); if ( !$rc[result] )
$rc = execute_agi( "GET DATA beep 15000 4"); $sogoi = $rc[result];
}
$rc[result] = 0;$BADFLAG=0 ; while (( !$rc[result] )||(!$BADFLAG)) {
$rc = execute_agi( "STREAM FILE date \"0123456789\" "); if ( !$rc[result] )
Chương IV : Xây dựng trung tâm quà tặng âm nhạc trên nền Asterisk
$rc = execute_agi( "GET DATA beep 15000 8"); $rc[result] = trim($rc[result]); $rc[result] = ltrim($rc[result]); if (substr($rc[result],4,4)<date("Y")) : $BADFLAG=1 ; endif ; if (substr($rc[result],4,4)>2020) : $BADFLAG=1 ; endif; if (substr($rc[result],0,2)<01) : $BADFLAG=1 ; endif ; if (substr($rc[result],0,2)>12) : $BADFLAG=1 ; endif ; if ((substr($rc[result],0,2)<date("m"))&&(substr($rc[result],4,4)<date("Y"))) : $BADFLAG=1 ; endif ; if (substr($rc[result],2,2)<01) : $BADFLAG=1 ; endif ; if (substr($rc[result],2,2)>31) : $BADFLAG=1 ; endif ;
Chương IV : Xây dựng trung tâm quà tặng âm nhạc trên nền Asterisk if ((substr($rc[result],0,2)<date("m"))&&(substr($rc[result],2,2)<date("d"))&&(substr ($rc[result],4,4)<date("Y"))) : $BADFLAG=1 ; endif ; if ($BADFLAG) $BADFLAG=0; else $BADFLAG=1; $ngaythang = $rc[result]; } $rc[result] = 0; while ( !$rc[result] ) {
$rc = execute_agi( "STREAM FILE nhapmsbh \"0123456789\" "); if ( !$rc[result] ){
$rc = execute_agi( "GET DATA beep 15000 4"); $msbh = $rc[result];
$row=mysql_query("select mabh from mabaihat where mabh='$msbh'"); $rows = mysql_fetch_array($row); if($rows){ $rc[result]=1; } else $rc[result]=0; }
Chương IV : Xây dựng trung tâm quà tặng âm nhạc trên nền Asterisk
}
$rc[result] = 0; // if ( !$rc[result] )
// $rc = execute_agi( "STREAM FILE loighiam"); if ( !$rc[result])
$rc = execute_agi( "RECORD FILE /var/lib/asterisk/sounds/do- an/$wtime.$ngaythang.$sogoi gsm \"0123456789\" -1");
// At this point we have a millitary time in the $wtime variable if ( $parm_chan_ext ) { $wakefile = "$parm_temp_dir/$wtime.$chan.$sta.call"; $callfile = "$parm_call_dir/$wtime.$chan.$sta.call"; } else { $wakefile = "$parm_temp_dir/$wtime.$ngaythang.$sogoi.call"; $callfile = "$parm_call_dir/$wtime.$ngaythang.$sogoi.call"; } if ($parm_debug_on)
fputs( $stdlog, "Wakeup File [$wakefile]\n" ); // Open up a wakeup file to write it out.
$wuc = fopen( $wakefile, 'w'); if ( $wuc )
Chương IV : Xây dựng trung tâm quà tặng âm nhạc trên nền Asterisk
// Delete any old Wakeup call files this one will override for ($i=0; $i < $outc; $i++ )
{
if( file_exists( "$parm_call_dir/$out[$i]" ) ) {
if ($parm_debug_on)
fputs( $stdlog, "Unlinking Old File [$parm_call_dir/$out[$i]]\n" ); unlink( "$parm_call_dir/$out[$i]" );
} }
if ( $parm_chan_ext )
fputs( $wuc, "channel: $chan/$sta\n" ); else
fputs( $wuc, "channel: SIP/$sogoi\n" );
fputs( $wuc, "maxretries: $parm_maxretries\n"); fputs( $wuc, "retrytime: $parm_retrytime\n"); fputs( $wuc, "waittime: $parm_waittime\n"); fputs( $wuc, "callerid: $parm_wakeupcallerid\n");
fputs( $wuc, "Extension: 10\n"); fputs( $wuc, "context: guiqua\n");
fputs( $wuc, "Set: MSG=" . $wtime . "." . $ngaythang . "." . $sogoi . "\n" );
fputs( $wuc, "Set: MABH=" . $msbh . "\n" ); fclose( $wuc );
Chương IV : Xây dựng trung tâm quà tặng âm nhạc trên nền Asterisk
$w = getdate();
$w['hours'] = substr( $wtime, 0, 2 ); $w['minutes'] = substr( $wtime, 2, 2 ); $w['day'] = substr( $ngaythang, 2, 2 ); $w['mon'] = substr( $ngaythang, 0, 2 ); $w['year'] = substr( $ngaythang, 4, 4 );
$time_wakeup = mktime( substr( $wtime, 0, 2 ), substr( $wtime, 2, 2 ), 0, substr( $ngaythang, 0, 2 ), substr( $ngaythang, 2, 2 ), substr( $ngaythang, 4, 4 ));
$time_now = time( ); if ($parm_debug_on)
fputs( $stdlog, 'time_wakeup=' . date('l dS \of F Y h:i:s A', $time_wakeup) . " ($time_wakeup) | time_now=" . date('l dS \of F Y h:i:s A',$time_now) . " ($time_now)\n" );
if ($parm_debug_on)
fputs( $stdlog, 'Setting WAKEUP file to =' . date('l dS \of F Y h:i:s A', $time_wakeup) . " - $time_wakeup\n" );
touch( $wakefile, $time_wakeup, $time_wakeup ); rename( $wakefile, $callfile )
} else {
if ($parm_debug_on)
fputs( $stdlog, "Error opening file [$wakefile]\n" ) $rc = execute_agi( "STREAM FILE auth-thankyou \"\" "); if ( !$rc[result] )
Chương IV : Xây dựng trung tâm quà tặng âm nhạc trên nền Asterisk
$rc = execute_agi( "STREAM FILE goodbye \"\" "); if ( !$rc[result] )
$rc = execute_agi( "HANGUP"); exit;
}
if ( $cidn && $parm_chan_ext == 0 ) {
$rc = execute_agi( "STREAM FILE auth-thankyou \"\" "); if ( !$rc[result] )
$rc = execute_agi( "STREAM FILE auth-thankyou \"\" "); if ( !$rc[result] )
$rc = execute_agi( "SAY DIGITS $sogoi \"\" ") } say_wakeup( $wtime ); $rc[result] = 0; // } break; if ( !$rc[result] )
$rc = execute_agi( "STREAM FILE auth-thankyou \"\" "); if ($parm_debug_on)
fclose($stdlog); exit;
}
Chương IV : Xây dựng trung tâm quà tặng âm nhạc trên nền Asterisk
// This will say military time in AM/PM format function say_wakeup( $wtime )
{
GLOBAL $stdin, $stdout, $stdlog, $parm_debug_on; $pm = 0; if ($wtime > 1159 ) { $wtime -=1200; $pm = 1; } if ($wtime <= 59 ) $wtime += 1200 if ( strlen( $wtime ) == 3 ) $wtime = '0' . $wtime; $h = substr( $wtime, 0, 2 ); $h1 = substr( $wtime, 0, 1 ); $h2 = substr( $wtime, 1, 1 ); $m = substr( $wtime, 2, 2 ); $m1 = substr( $wtime, 2, 1); $m2 = substr( $wtime, 3, 1); if ($parm_debug_on)
fputs( $stdlog, "Wakeup time is set to $wtime\n" );
$rc = execute_agi( "STREAM FILE rqsted-wakeup-for \"\" "); if ( !$rc[result] )
Chương IV : Xây dựng trung tâm quà tặng âm nhạc trên nền Asterisk
{
if ( $h1 == 0 )
$rc = execute_agi( "SAY NUMBER $h2 \"\""); else
$rc = execute_agi( "SAY NUMBER $h \"\""); if ( !$rc[result] )
{
if ($m == 0 )
$rc = execute_agi( "STREAM FILE digits/oclock \"\" "); else
{
if ( $m1 == 0 ) {
$rc = execute_agi( "STREAM FILE digits/oh \"\" "); $rc = execute_agi( "SAY NUMBER $m2 \"\" "); }
else
$rc = execute_agi( "SAY NUMBER $m \"\""); }
if ( !$rc[result] ) {
if ( $pm )
$rc = execute_agi( "STREAM FILE digits/p-m \"\" "); else
Chương IV : Xây dựng trung tâm quà tặng âm nhạc trên nền Asterisk
$rc = execute_agi( "STREAM FILE digits/a-m \"\" "); }
} } }
//---
// This function will send out the command and get // the response back
function execute_agi( $command ) {
GLOBAL $stdin, $stdout, $stdlog, $parm_debug_on; fputs( $stdout, $command . "\n" );
fflush( $stdout ); if ($parm_debug_on)
fputs( $stdlog, $command . "\n" ); $resp = fgets( $stdin, 4096 );
if ($parm_debug_on) fputs( $stdlog, $resp );
if ( preg_match("/^([0-9]{1,3}) (.*)/", $resp, $matches) ) {
if (preg_match('/result=([-0-9a-zA-Z]*)(.*)/', $matches[2], $match)) {
$arr['code'] = $matches[1]; $arr['result'] = $match[1];
Chương IV : Xây dựng trung tâm quà tặng âm nhạc trên nền Asterisk
if (isset($match[3]) && $match[3]) $arr['data'] = $match[3]; return $arr; } else { if ($parm_debug_on)
fputs( $stdlog, "Couldn't figure out returned string, Returning code=$matches[1] result=0\n" ); $arr['code'] = $matches[1]; $arr['result'] = 0; return $arr; } } else { if ($parm_debug_on)
fputs( $stdlog, "Could not process string, Returning -1\n" ); $arr['code'] = -1; $arr['result'] = -1; return $arr; } } ?>
Chương IV : Xây dựng trung tâm quà tặng âm nhạc trên nền Asterisk