AGI

De Wiki Officiel Asterisk-France.

Sommaire

Introduction

Les AGIs peuvent être écris en php, perl, python, java, C, ou tout autre language.

Les AGIs peuvent être de deux types :
- AGI : le type par défaut.
- FastAGI : utilisé pour faire tourner un AGI sur une autre machine du même réseau.

Les AGIs sont appelés depuis le dialplan.
La communication avec Asterisk s'effectue via les fichiers stdin et stdout.


Les Fonctions

Pour connaitre la liste des fonctions utilisables dans les AGIs, vous devez vous connecter à la console d'Asterisk et faire : agi show


Execution de l'AGI

L'AGI est envoyé par Asterisk depuis le dialplan. L'appel à un AGI se fait par :

exten => s,n,AGI([<interpreteur>,]"<script_agi>"[,var1[,var2[,..]]])

Exemple :

exten => s,n,AGI(/usr/bin/php,"/var/lib/asterisk/agi-bin/test_php.agi")

Exemple avec paramètres :

exten => s,n,AGI(/usr/bin/php,"/var/lib/asterisk/agi-bin/test_php.agi",${Myvar1},${Myvar2})

il est possible de ne pas préciser l'interpréteur (suivant la version d'Asterisk) ni le chemin de l'agi si celui-ci se trouve dans le repertoire paramètré dans /etc/asterisk/asterisk.conf entrée astagidir (par defaut : /var/lib/asterisk/agi-bin).


PHP

AGI simple

Voici un exemple utilisant le langage PHP, l'AGI est appelé depuis le dialplan. le script php doit être dans le repertoire /var/lib/asterisk/agi-bin et doit avoir les droits d'exécution pour Asterisk.

Script (test_php.agi) :

#!/usr/bin/php -q
<?php
// limite le temps d'execution du script a 60 secondes 
set_time_limit(60);

// supprime le "buffering" sur les sorties
ob_implicit_flush(false);

// supprime l'affichage des erreurs pour éviter que celles-ci interferent avec Asterisk
error_reporting(0);

// creation des fichiers STDIN, STDOUT et STDERR si besoin
if(!defined('STDIN')) define('STDIN', fopen('php://stdin', 'r'));
if(!defined('STDOUT')) define('STDOUT', fopen('php://stdout', 'w'));
if(!defined('STDERR')) define('STDERR', fopen('php://stderr', 'w'));

// # retrieve all AGI variables from Asterisk
// récupération des variables envoyés par Asterisk au lancement de l'AGI.
while(!feof(STDIN))
{
  $temp = trim(fgets(STDIN,4096));
  if (($temp == "") || ($temp == "\n")) break;
  $s = split(":",$temp);
  $name = str_replace("agi_","",$s[0]);
  $agi[$name] = trim($s[1]);
}

// l'ordre que l'on envoi à Asterisk, dans cette exemple, on met "bonjour" dans "Myvar"
fwrite(STDOUT,"SET VARIABLE Myvar Bonjour\n");
// force l'envoi de l'ordre. Pas réellement nécessaire puisse que la bufferisation
// est désactivée, mais conseillé.
fflush(STDOUT);
exit();
?>


Dialplan :

[AGI_PHP]
exten => s,1,Set(Myvar=Test)
exten => s,n,NoOp(Myvar=${Myvar})
exten => s,n,AGI(/usr/bin/php,"/var/lib/asterisk/agi-bin/test_php.agi")
exten => s,n,NoOp(Myvar=${Myvar})


Affichage CLI :

   -- Executing [s@AGI_PHP:1] Set("SIP/201-08fe4158", "Myvar=Test") in new stack
   -- Executing [s@AGI_PHP:2] NoOp("SIP/201-08fe4158", "Myvar=Test") in new stack
   -- Executing [s@AGI_PHP:3] AGI("SIP/201-08fe4158", 
"/usr/bin/php,"/var/lib/asterisk/agi-bin/test_php.agi"") in new stack
   -- Launched AGI Script /usr/bin/php
   -- <SIP/201-08fe4158>AGI Script /usr/bin/php completed, returning 0
   -- Executing [s@AGI_PHP:4] NoOp("SIP/201-08fe4158", "Myvar=Bonjour") in new stack
   -- Executing [s@AGI_PHP:5] Hangup("SIP/201-08fe4158", "") in new stack


AGI avec paramètres

Voici un autre exemple avec passage de paramètres Script (test_php_var.agi) :

#!/usr/bin/php -q
<?php
// limite le temps d'execution du script a 60 secondes 
set_time_limit(60);

// supprime le "buffering" sur les sorties
ob_implicit_flush(false);

// supprime l'affichage des erreurs pour éviter que celles-ci interferent avec Asterisk
error_reporting(0);

// creation des fichiers STDIN, STDOUT et STDERR si besoin
if(!defined('STDIN')) define('STDIN', fopen('php://stdin', 'r'));
if(!defined('STDOUT')) define('STDOUT', fopen('php://stdout', 'w'));
if(!defined('STDERR')) define('STDERR', fopen('php://stderr', 'w'));

// # retrieve all AGI variables from Asterisk
// récupération des variables envoyés par Asterisk au lancement de l'AGI.
while(!feof(STDIN))
{
  $temp = trim(fgets(STDIN,4096));
  if (($temp == "") || ($temp == "\n")) break;
  $s = split(":",$temp);
  $name = str_replace("agi_","",$s[0]);
  $agi[$name] = trim($s[1]);
}

// l'ordre que l'on envoi à Asterisk, dans cette exemple, on met le resultat
// de la multiplication de "arg1" par "arg2" dans "Myvar"
fwrite(STDOUT,"SET VARIABLE Myvar ".($agi[arg_2]*$agi[arg_3])."\n");
// force l'envoi de l'ordre. Pas réellement nécessaire puisse que la bufferisation
// est désactivée, mais conseillé.
fflush(STDOUT);
exit();
?>


Dialplan :

[AGI_PHP_VAR]
exten => s,1,Set(Myvar=Test)
exten => s,n,Set(Myvar1=2)
exten => s,n,Set(Myvar2=3)
exten => s,n,NoOp(Myvar=${Myvar})
exten => s,n,AGI(/usr/bin/php,"/var/lib/asterisk/agi-bin/test_php_var.agi",${Myvar1},${Myvar2})
exten => s,n,NoOp(Myvar=${Myvar})


Affichage CLI :

   -- Executing [s@AGI_PHP_VAR:1] Set("SIP/201-08fdd448", "Myvar=Test") in new stack
   -- Executing [s@AGI_PHP_VAR:2] Set("SIP/201-08fdd448", "Myvar1=2") in new stack
   -- Executing [s@AGI_PHP_VAR:3] Set("SIP/201-08fdd448", "Myvar2=3") in new stack
   -- Executing [s@AGI_PHP_VAR:4] NoOp("SIP/201-08fdd448", "Myvar=Test") in new stack
   -- Executing [s@AGI_PHP_VAR:5] AGI("SIP/201-08fdd448", 
"/usr/bin/php,"/var/lib/asterisk/agi-bin/test_php_var.agi",2,3") in new stack
   -- Launched AGI Script /usr/bin/php
   -- <SIP/201-08fdd448>AGI Script /usr/bin/php completed, returning 0
   -- Executing [s@AGI_PHP_VAR:6] NoOp("SIP/201-08fdd448", "Myvar=6") in new stack
   -- Executing [s@AGI_PHP_VAR:7] Hangup("SIP/201-08fdd448", "") in new stack


AGI et base de données

Voici un exemple avec récupération de valeur depuis une base de données Mysql.
Dans cet exemple, la base s'appelle asterisk et la table s'appelle testagi.

Table testagi :

CREATE DATABASE IF NOT EXISTS asterisk;
USE asterisk;

DROP TABLE IF EXISTS `testagi`;
CREATE TABLE `testagi` (
 `ID` int(11) NOT NULL auto_increment,
 `Nom` varchar(16) NOT NULL default ,
 `Code` varchar(10) NOT NULL default ,
 PRIMARY KEY  (`ID`)
);

Contenu table testagi :

INSERT INTO `testagi` (`Nom`,`Code`) VALUES ('usertest','1234');

Script (test_php_sql.agi) :

#!/usr/bin/php -q
<?php
// limite le temps d'execution du script a 60 secondes 
set_time_limit(60);

// supprime le "buffering" sur les sorties
ob_implicit_flush(false);

// supprime l'affichage des erreurs pour éviter que celles-ci interferent avec Asterisk
error_reporting(0);

// creation des fichiers STDIN, STDOUT et STDERR si besoin
if(!defined('STDIN')) define('STDIN', fopen('php://stdin', 'r'));
if(!defined('STDOUT')) define('STDOUT', fopen('php://stdout', 'w'));
if(!defined('STDERR')) define('STDERR', fopen('php://stderr', 'w'));

// # retrieve all AGI variables from Asterisk
// récupération des variables envoyés par Asterisk au lancement de l'AGI.
while(!feof(STDIN))
{
  $temp = trim(fgets(STDIN,4096));
  if (($temp == "") || ($temp == "\n")) break;
  $s = split(":",$temp);
  $name = str_replace("agi_","",$s[0]);
  $agi[$name] = trim($s[1]);
}

// ouverture de la base
$DataBase = 'asterisk';
$HostBase = '127.0.0.1';
$UserBase = 'Asterisk';
$PwdBase  = 'password';
$Table = 'testagi';

$db = mysql_connect($HostBase, $UserBase, $PwdBase);
if(!$db) exit(1);
mysql_select_db($DataBase, $db);

// recuperation du code
$SQLstr="Select Code from $Table where Nom='".$agi[arg_2]."'";
$Res = mysql_query($SQLstr, $db);
$tresult = mysql_fetch_array($Res);
@mysql_free_result($Res, $db);
@mysql_close($db);

// l'ordre que l'on envoi à Asterisk, dans cette exemple, on met le code de l'utilisateur
fwrite(STDOUT,"SET VARIABLE usercode ".$tresult['Code']."\n");

// force l'envoi de l'ordre. Pas réellement nécessaire puisse que la bufferisation
// est désactivée, mais conseillé.
fflush(STDOUT);
exit();
?>


Dialplan :

[AGI_PHP_SQL]
exten => s,1,Set(UserName=usertest)
exten => s,n,NoOp(UserName=${UserName})
exten => s,n,Set(usercode="")
exten => s,n,AGI(/usr/bin/php,"/var/lib/asterisk/agi-bin/test_php_sql.agi",${UserName})
exten => s,n,NoOp(usercode=${usercode})
exten => s,n,Hangup()


Affichage CLI :

   -- Executing [s@AGI_PHP_SQL:1] Set("SIP/201-08fe1928", "UserName=usertest") in new stack
   -- Executing [s@AGI_PHP_SQL:2] NoOp("SIP/201-08fe1928", "UserName=usertest") in new stack
   -- Executing [s@AGI_PHP_SQL:3] Set("SIP/201-08fe1928", "usercode=""") in new stack
   -- Executing [s@AGI_PHP_SQL:4] AGI("SIP/201-08fe1928", 
"/usr/bin/php,"/var/lib/asterisk/agi-bin/test_php_sql.agi",usertest") in new stack
   -- Launched AGI Script /usr/bin/php
   -- <SIP/201-08fe1928>AGI Script /usr/bin/php completed, returning 0
   -- Executing [s@AGI_PHP_SQL:5] NoOp("SIP/201-08fe1928", "usercode=1234") in new stack
   -- Executing [s@AGI_PHP_SQL:6] Hangup("SIP/201-08fe1928", "") in new stack


Annexe

Pour simplifier la programmation d'AGI en php, il existe un module nommé : PHPAGI, téléchargeable sur : http://phpagi.sourceforge.net/

Exemple :

<?
require 'phpagi.php';
$agi = new AGI();
$agi->set_variable("Myvar", "Bonjour");
?>