什么是asterisk
Asterisk是用于构建通信应用程序的开源框架。asterisk将普通计算机变成通信服务器。Asterisk为IP PBX系统,VoIP网关,会议服务器和其他自定义解决方案提供动力。全球的小型企业,大型企业,呼叫中心,运营商和政府机构都使用它。星号是免费和开源的。星号由Sangoma赞助。
![](https://img.haomeiwen.com/i1791542/5d9a25b3d330d505.png)
如今,在170多个国家/地区中,超过100万个基于asterisk的通信系统正在使用。几乎整个《财富》 1000强客户列表都使用Asterisk。Asterisk通常由系统集成商和开发人员部署,可以成为完整的商务电话系统的基础,或用于增强或扩展现有系统,或弥合系统之间的鸿沟。
使用php创建agi脚本
编写一个AGI脚本以从Internet下载天气报告,并将温度,风向和风速传回给呼叫者:
#!/usr/bin/php -q
<?php
第一行告诉系统使用PHP解释器运行此脚本。 - q
选项关闭HTML错误消息。您应该确保第一行和打开的PHP标记之间没有多余的行,因为它们会混淆Asterisk。
//获取天气
$weatherURL="http://www.nws.noaa.gov/data/current_obs/KMDQ.xml";
This tells our AGI script where to go to get the current weather conditions. In this example, we’re getting the weather for Huntsville, Alabama. Feel free to visit the web site listed above for a complete list of stations throughout the United States of America.[123]
# 不要让程序运行超过60秒
set_time_limit(60);
在这里,我们告诉PHP不要让该程序运行超过60秒。如果耗时过长,我们就终止程序。
#关闭输出缓冲
ob_implicit_flush(false);
此命令将关闭输出缓冲,这意味着所有数据将立即发送到AGI接口,并且不会被缓冲。
#关闭错误报告,因为它很可能会干扰
#AGI接口
error_reporting(0);
此命令会关闭所有错误报告,因为它可能会干扰AGI接口。
# #根据需要创建文件句柄
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'));
}
这部分代码确保我们有打开的文件句柄 对于STDIN
,STDOUT
和STDERR
,将处理Asterisk和我们的脚本之间的所有通信。
# 检索所有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]);
}
接下来,我们将阅读Asterisk传递给我们的所有AGI变量。使用fgetsPHP中的命令读取数据STDIN,我们将每个变量保存在名为的哈希中$agi。请记住,我们可以在AGI脚本的逻辑中使用这些变量。
# print all AGI variables for debugging purposes
foreach($agi as $key=>$value)
{
fwrite(STDERR,"-- $key = $value\n");
fflush(STDERR);
}
在这里,我们将变量打印回去以STDERR进行调试。
#获取网页内容
$weatherPage=file_get_contents($weatherURL);
这行代码从国家气象局检索XML文件,并将内容放入名为的变量中$weatherPage。稍后将使用此变量来提取所需的天气预报。
#通过正则匹配获取温度
if (preg_match("/<temp_f>([0-9]+)<\/temp_f>/i",$weatherPage,$matches))
{
$currentTemp=$matches[1];
}
此部分代码使用以下preg_match命令从天气预报中提取温度(以华氏度为单位)。
#获取风向
if (preg_match("/<wind_dir>North<\/wind_dir>/i",$weatherPage))
{
$currentWindDirection='northerly';
}
elseif (preg_match("/<wind_dir>South<\/wind_dir>/i",$weatherPage))
{
$currentWindDirection='southerly';
}
elseif (preg_match("/<wind_dir>East<\/wind_dir>/i",$weatherPage))
{
$currentWindDirection='easterly';
}
elseif (preg_match("/<wind_dir>West<\/wind_dir>/i",$weatherPage))
{
$currentWindDirection='westerly';
}
elseif (preg_match("/<wind_dir>Northwest<\/wind_dir>/i",$weatherPage))
{
$currentWindDirection='northwesterly';
}
elseif (preg_match("/<wind_dir>Northeast<\/wind_dir>/i",$weatherPage))
{
$currentWindDirection='northeasterly';
}
elseif (preg_match("/<wind_dir>Southwest<\/wind_dir>/i",$weatherPage))
{
$currentWindDirection='southwesterly';
}
elseif (preg_match("/<wind_dir>Southeast<\/wind_dir>/i",$weatherPage))
{
$currentWindDirection='southeasterly';
}
通过使用preg_match(位于wind_dir标签中)可以找到风向,并将其分配给变量 $currentWindDirection。
#grab wind speed
if (preg_match("/<wind_mph>([0-9.]+)<\/wind_mph>/i",$weatherPage,$matches))
{
$currentWindSpeed = $matches[1];
}
最后,我们将获取当前的风速并将其分配给 $currentWindSpeed变量。
# 告诉来电者当前情况
if ($currentTemp)
{
fwrite(STDOUT,"STREAM FILE temperature \"\"\n");
fflush(STDOUT);
$result = trim(fgets(STDIN,4096));
checkresult($result);
fwrite(STDOUT,"STREAM FILE is \"\"\n");
fflush(STDOUT);
$result = trim(fgets(STDIN,4096));
checkresult($result);
fwrite(STDOUT,"SAY NUMBER $currentTemp \"\"\n");
fflush(STDOUT);
$result = trim(fgets(STDIN,4096));
checkresult($result);
fwrite(STDOUT,"STREAM FILE degrees \"\"\n");
fflush(STDOUT);
$result = trim(fgets(STDIN,4096));
checkresult($result);
fwrite(STDOUT,"STREAM FILE fahrenheit \"\"\n");
fflush(STDOUT);
$result = trim(fgets(STDIN,4096));
checkresult($result);
}
if ($currentWindDirection && $currentWindSpeed)
{
fwrite(STDOUT,"STREAM FILE with \"\"\n");
fflush(STDOUT);
$result = trim(fgets(STDIN,4096));
checkresult($result);
fwrite(STDOUT,"STREAM FILE $currentWindDirection \"\"\n");
fflush(STDOUT);
$result = trim(fgets(STDIN,4096));
checkresult($result);
fwrite(STDOUT,"STREAM FILE wx/winds \"\"\n");
fflush(STDOUT);
$result = trim(fgets(STDIN,4096));
checkresult($result);
fwrite(STDOUT,"STREAM FILE at \"\"\n";)
fflush(STDOUT);
$result = trim(fgets(STDIN,4096));
checkresult($result);
fwrite(STDOUT,"SAY NUMBER $currentWindSpeed \"\"\n");
fflush(STDOUT);
$result = trim(fgets(STDIN,4096));
checkresult($result);
fwrite($STDOUT,"STREAM FILE miles-per-hour \"\"\n");
fflush(STDOUT);
$result = trim(fgets(STDIN,4096));
checkresult($result);
}
现在我们已经收集了数据,我们可以将AGI命令发送到Asterisk(在检查过程中检查结果),该命令会将当前的天气情况传递给调用者。这将通过使用STREAM FILE
和来实现 SAY NUMBER
AGI命令。
我们之前已经说过,然后再说一遍:调用AGI命令时,必须传递所有必需的参数。在这种情况下,STREAM FILE
和SAY NUMBER
命令都需要第二个参数。我们将传递反斜杠字符转义的空引号。
您还应该注意,fflush
每次写入时,我们都会调用该命令STDOUT
。尽管这可以说是多余的,但是确保AGI命令没有被缓冲并立即发送到Asterisk并没有什么害处。
function checkresult($res)
{
trim($res);
if (preg_match('/^200/',$res))
{
if (! preg_match('/result=(-?\d+)/',$res,$matches))
{
fwrite(STDERR,"FAIL ($res)\n");
fflush(STDERR);
return 0;
}
else
{
fwrite(STDERR,"PASS (".$matches[1].")\n");
fflush(STDERR);
return $matches[1];
}
}
else
{
fwrite(STDERR,"FAIL (unexpected result '$res')\n");
fflush(STDERR);
return -1;
}
}
每当我们调用AGI命令时,它都会检查Asterisk返回的结果。
经过上面的步骤,我们就实现了一个拨打接听天气的程序。
网友评论