Asterisk Manager Interface主要提供AST系统监控以及管理功能,它可以要求AST做一些事情,例如发起一个新呼叫。
需要的配置:
manager.conf
;
; 打开AMI并本地访问
[general]
enabled = yes
webenabled = yes
bindaddr = 127.0.0.1
;
; 创建用户hello,密码world
;
[hello]
secret=world
上面的配置打开了http访问,这个需要配置http.conf(注意这个不是apache的httpd.conf)但是我安装的ASteriskNow并没有这个http.conf配置文件,也没打开http访问,常见的还是使用tcp访问,默认端口是5038。
如果没发现这个文件http.conf,可以自己加一个:
[general]
enabled=yes
bindaddr=0.0.0.0
bindport=8088
prefix=gui ;这个前缀用于http请求的url前缀
enablestatic=yes
这样的话请求AMI应该是:
http://localhost:8088/gui/rawman?action=login&username=hello&secret=world
然后重新加载:CLI>core reload
如果登陆不成功,还要看manager.conf中deny设置是否禁止了你的ip访问。
协议:
主要有两种协议:
Manager events 只从AST到AMI客户端的单项事件
Manager actions AMI客户端请求AMI会得到返回Action Response。
对于http连接,事件需要通过poll来获取。
下面是开源AMI客户端库。
Adhearsion Ruby http://adhearsion.com/
StarPy Python http://starpy.sourceforge.net/
Asterisk-Java Java http://asterisk-java.org/
介绍几个有用的AMI应用:
Asterisk GUI这个包含在AsteriskNow中 ,参见http://www.asterisk.org/asterisknow/developers/gui-guide
第二十一章 AGI
内置的dialplan写法可能有很多不便之处(如果你熟知一门编程语言的话),使用AGI则可以使用其他编程语言来控制呼叫流程,但是这么做还是离不开native dialplan的参与。
例如
exten => 500,1,AGI(hello-world.sh)
这里就调用了shell脚本的AGI
打开AGI调试:
*CLI> agi set debug on
AGI变种
Process-Based AGI:
最简单的AGI,调用方式AGI(command[,arg1[,arg2[,...]]]) command可以使绝对路径,相对路径,arg1…是AGI需要传入的参数。
执行AGI时,与AST交互的方式是通过stdin 和 stdout来进行的。
有点:简单
缺点:太简单,高并发时建议使用FastAGI
EAGI (Enhanced AGI)
相对于AGI,除了stdin和stdout外还可以获得单向只读语音流(app_jack提供获得AST之外音频流的功能)。
*CLI> core show application EAGI
优点:简单
缺点:性能消耗比Process-Based AGI高
DeadAGI
这个已被废弃,不要使用。
FastAGI—AGI over TCP
使用tcp连接,不再是每个call一个进程,提高效率。
exten => 1234,1,AGI(agi://192.168.1.199:4573,arg1,arg2,arg3)
FASTAGI支持srvrecord
exten => 1234,1,AGI(hagi://shifteight.org)
优点:效率较好
缺点:实现FASTAGI Server比较复杂
Async AGI—AMI-Controlled AGI
异步AGI,可以使AMI调用AGI。
exten => 1234,1,AGI(async:agi)
这种方式的流程是,当执行上面一句时,会等待,然后,在AMI客户端中向·这个通道发命令,以这样的方式来执行。
对于要执行AGI的影虎需要在manager.conf中指明权限
[hello]
secret = world
read = agi ;有读权限
write = agi ;有写权限
优点:AMI可使用AGI
缺点:最复杂的一种用法
会话过程
调用AGI或EAGI后,会话建立,自定义参数(如agi_arg_0)和固有参数(如agi_request)会传入:
对于Async AGI,开始时AMI会发送事件Manage Events,例如:
Event: AsyncAGI
Privilege: agi,all
SubEvent: Start
Channel: SIP/0000FFFF0001-00000000
Env: agi_request%3A%20async%0Aagi_channel%3A%20SIP%2F0000FFFF0001-00000000%0A \
agi_language%3A%20en%0Aagi_type%3A%20SIP%0Aagi_uniqueid%3A%201285219743.0%0A \
agi_version%3A%201.8.0-beta5%0Aagi_callerid%3A%2012565551111%0A \
agi_calleridname%3A%20Julie%20Bryant%0Aagi_callingpres%3A%200%0A \
agi_callingani2%3A%200%0Aagi_callington%3A%200%0Aagi_callingtns%3A%200%0A \
agi_dnid%3A%20111%0Aagi_rdnis%3A%20unknown%0Aagi_context%3A%20LocalSets%0A \
agi_extension%3A%20111%0Aagi_priority%3A%201%0Aagi_enhanced%3A%200.0%0A \
agi_accountcode%3A%20%0Aagi_threadid%3A%20-1339524208%0A%0A
一旦会话开始,AGI就可以发送命令和获得回应,命令的执行是序列化的,一个执行完毕才会执行下一个。
AGI会话的终止
各种AGI的行为不一样:
Process-based AGI/FastAGI:
会话挂断会通知AGI程序来做后续处理。(1.4之前是直接中断,不会通知)
Process-based AGI 会发SIGHUP 信号
FASTAGI会发HANGUP信号。
可以通过这样来禁止发送SIGHUP /HANGUP信号:
;
; Don’t send SIGHUP to an AGI process
; or the "HANGUP" string to a FastAGI server.
;
exten => 500,1,Set(AGISIGHUP=no)
same => n,AGI(my-agi-application)
如果禁用,则相当于DeadAGI模式,会话其实结束了,但仍可以执行。不过只能执行不需要交互的命令,具体看每个命令的文档说明。
对于Async AGI,如果会话中断,会发中断提示,如果想要主动中断会话,AMI客户端需要发送ASYNCAGI BREAK命令。
AGI各种开发语言库:
Adhearsion Ruby http://adhearsion.com/
StarPy Python http://starpy.sourceforge.net/
Asterisk-Java Java http://asterisk-java.org/
Asterisk-perl Perl http://asterisk.gnuinter.net/
PHPAGI PHP http://phpagi.sourceforge.net/
第二十五章 web 接口
这一章介绍了有名的相关项目:
坐席管理
http://www.asternic.org/ Flash Operator Panel 免费
http://www.fop2.com/ Flash Operator Panel2 15个以上收费
http://www.cdr-stats.org/ Call Detail Records 分析统计工具
http://www.asterisk2billing.org/ 计费系统 A2Billi ng
第十八章 外部服务
使用XMPP
需要res_jabber模块,默认是没有安装的,如果要支持gtalk的话,需要chan_gtalk,chan_jingle(这两个依赖res_jabber)
centos上需要iksemel:
yum install iksemel-devel openssl-devel
现在假设res_jabber安装好了,需要配置 jabber.conf
[general]
debug=no
autoprune=no
autoregister=yes
auth_policy=accept
[asterisk]
type=client
serverhost=talk.google.com ;这里连到了gtalk
username=asterisk@shifteight.org ;xmpp用户名
secret=<super_secret_password> ;xmpp密码
port=5222
usetls=yes
usesasl=yes
status=available
statusmessage="Ohai from Asterisk"
dialplan:
exten => 106,1,Verbose(2,Example using the Local channel) ;一开始就呼叫dialplan
same => n,Dial(Local/jabber@${CONTEXT}/n&Local/dial@${CONTEXT}/n)
exten => jabber,1,Verbose(2,Send an XMPP message and expect a response) ;接到呼叫发送xmpp消息
; *** This line should not have any line breaks
same => n,JabberSend(asterisk,leif.madsen@gmail.com,Incoming call from
${CALLERID(all)}. Press 2 to send to voicemail.) ;消息不能换行
same => n,Set(JabberResponse=${JABBER_RECEIVE(asterisk,leif@shifteight.org,6)})
same => n,GotoIf($["${JabberResponse}" = "2"]?voicemail,1)
same => n,Hangup()
exten => dial,1,Verbose(2,Calling our desk)
same => n,Dial(SIP/0000FFFF0002,15)
same => n,Goto(voicemail,1)
exten => voicemail,1,Verbose(2,VoiceMail)
same => n,Answer()
; *** This line should not have any line breaks
same => n,Set(VoiceMailStatus=${IF($[${ISNULL(${DIALSTATUS})}
| "${DIALSTATUS}" = "BUSY"]?b:u)})
same => n,Playback(silence/1)
same => n,VoiceMail(100@lmentinc,${VoiceMailStatus})
same => n,Hangup()
这个例子是通过发送xmpp消息来让xmpp用户来选择。
与skype整合
可以通过skype发、接消息,呼叫好友
LDAP整合
TextToSpeech
Festival 和 Cepstral 引擎