Dialplan编程其实是在extensions.conf文件中来完成的。主要目的就是完成对来电和去电的处理。所有的代码都是在一个”context“下面
以“exten =>” 开头的。
语法如下:
exten => extension_name,priority(label),Application(parameters)
注解:
extension_name: 是当前extension的名称,可以是数字,字母或是动态模式的匹配的许多号码。其实在Astertisk中应该说为“指令”列为准确。
Priority:通常是正数。它是一个extension中的每个命令行的排序号码。第一个可执行命令的priority值为“1”。因此当Asterisk将一个呼叫转入一个extension时,它将首先寻找priority值为1的命令。如果没有优先值为1的行,那么这个extension将不会匹配这个拨入的号码。当执行完优先值为1的命令之后,Asterisk将把priority的值增加到2,然后继续执行优先级为2的这个extension。除非命令本身决定下一个要执行的优先值。如果extension中没有定义下一个priority,Asterisk将完成对这个 extension的处理,即使是存在一个比丢失的命令的优先级更高的命令。还有一点就是可以为Priority来设置一个Label,在后面可以很方便的用goto(label)来跳到这个地方。在编程的时候,往往会记不住这么多的编号,这时可以使用n来代替extension的优先级,前提是必须存在优先级为1的extension。
Application(Parameters):这个Application就是Asterisk的核心了,这里的“应用”还可以跟很多参数。下面主要说的也就是这些个“应用”
下面就来说一下Asterisk中常用的应用:
Answer() 应答;没有参数。
Hangup() 挂机;没有参数。
Playback() 是给拨打者回放一段音乐,音乐的文件名要填在后面的那个()里。注意:这里的文件名,不能带后缀。默认的音乐文件存放的位置是
/var/lib/asterisk/sound/下面。这个文件可以是绝对路径,也可以是相对路径,相对路径是相对于音乐文件存放的目录来说的。
Background() 作用和Playback的一样,都是播放音乐,但是,Background在播放音乐的时候会等待用户的输入,如果用户输入后,会停止播放音乐并
跳转到与用户输入相对应的那个extension中去。利用这个可以来做一个语音导航。如果用户长时间没有输入任何号码则会被视为超时,
默认超时时间是10秒,然后会自动的进入到名称为“t”(timeout)的extension中去,如果用户在输入的号码不存在,那么会自动进入到名称为
“i”(invalid)的extension中去。
WaitExten():如果你希望 Asterisk 在播放完语音提示后继续等待用户输入一段时间,你可以使用WaitExten()。 WaitExten()一般跟在 Background()之后
使用, 其作用是等待用户的 DTMF 输入,如果你希望为 WaitExten()指定等待用户响应的时间(以取代默认的超时时间
注9) ,只需要简单的将代表秒数的数字代入 WaitExten(),像这样:
same => n,WaitExten(5); We recommend always passing a time argument to WaitExten()
Background()和 WaitExten()都允许用户输入 DTMF 数字。然后 Asterisk 会尝试在当前 context中寻找与这个数字匹配的extension。
如果寻找到了, Asterisk就会将呼叫传递给这个extension。
Goto():该Application有三个参数,都放在括号内,每个参数之间用“,”来分开。这三个参数分别是:(context,extension,priority),当然前面两个参数不是必须
的,如果只有两个参数:那么就是说跳转到当前的context中的某个extension中的相应的priority中去。如果只有一个参数,则是跳转到当前extension中
的某个priority去。
Dial() 有4个参数,是用来振铃相应的通道,当用户接通后,并桥接相应的通道。
第一个参数是:被叫地
格式为:
呼叫采用的技术/资源地(通常是通道的名称或编号),
exten=>123,1,dial(Zap/1)----就是当执行123这个extensions的时候就对Zap/1振铃。
exten=>123,1,dial(Zap/1&Zap/2&Zap/3) ----可以同时对多个通道进行振铃,各个通道之间用&分开。
到一个 SIP 设备的呼叫的被叫地是SIP/1234,而到一个 IAX 设备的呼叫的被叫地是 IAX/fred
第二个参数是:超时, 单位为秒。 如果给定了超时参量, Dial( ) 会一直对被叫地进行呼叫,直到超时后才放弃。如果没有指定超时时间,
Dial( )会一直呼叫该通道,直到有人接听,或者主叫挂机。现在我们把这一个 10 秒的超时加到 xtension 中:
exten => 123,1,Dial(Zap/1,10)
如果呼叫在超时之前被接听,通道就被桥接,拨号方案完成,如果被叫地没有应答, Dial( ) 会继续到该 extension 的下一个 priority。但是,
如果被叫通道忙 ,Dial( )将转到 priority n+101,如果其存在的话(其中的 n 是 Dial( )被调用的priority)。这样我们就能够以不同于被叫地忙的方
式来处理未接听电话。 ----这里要注意:我做的时候是它并不能自己跳到n+101那个priority去,要使用Gotoif()对变量DIALSTATUS进行一个判断,如果是变量的值
是“BUSY”则进入到n+101去。
exten=>123,1,dial(Zap/1,10)
exten=>123,2,Playback(nobody)
exten=>123,3,Hangup()
exten=>123,102,Playback(busy)
exten=>123,103,Hangup()
解析:如果被叫没有接通,则播放nobody后,挂机。如果被叫忙,则播放busy后,挂机。
第三个参数是:可选择的字符串,它包含一个或多个能够影响Dial( )应用行为的字符。选项地的列表太长,不能在这里逐一列出。最常用的一个是
字母 r。如果把字母 r 作为第 3 个参量,在通知被叫通道有来电的这段时间内,主叫方会听到振铃声音
exten=>123,1,dial(Zap/1,10,r) ---这里多了个r
exten=>123,2,Playback(nobody)
exten=>123,3,Hangup()
exten=>123,102,Playback(busy)
exten=>123,103,Hangup()
需求:当外部打入时,接受用户的输入,如果是101则打给john,如果是102就打给jane,并且还要有异常处理。
exten=>s,1,Answer()
exten=>s,2,Background(hello)
exten=>101,1,dial(Zap/1,10,r)
exten=>101,2,Playback(nobody)
exten=>101,3,Hangup()
exten=>101,102,Playback(busy)
exten=>101,103,Hangup()
exten=>102,1,dial(Zap/2,10,r)
exten=>102,2,Playback(nobody)
exten=>102,3,Hangup()
exten=>102,102,Playback(busy)
exten=>102,103,Hangup()
exten=>i,1,Playback(invalid_input)
exten=>i,2,Goto(s,1)
exten=>t,1,Playback(timeout)
exten=>t,2,Hangup()
如果你将 m 作为 Dial()的第三个参数, 主叫听到的回铃音会被 hold music 取代 (译者注:就是咱们的“彩铃”功能了)。
举例如下:
exten => 102,1,Dail(DAHDI/1,10,m)
T:表示允许主叫用户按“#”键转接呼叫;
t:表示允许被叫用户按“#”来转接呼叫;
w:用户按“*”开始录音;
r:表示为被叫用户产生振铃声。
第四个参数是:URL。Dial( )应用的最后一个参量是 URL。如果被叫通道支持在呼叫的同时接受URL,那么所指定的 URL 将被发
送(例如,如果你有一个能够接受 URL 的 IP 电话,它将会显示在显示屏上,同样,如果使用的是软电话,URL 会在屏幕上弹
出来。) 这个参量很少使用。如果要在 FXO Zap 通道上产生一个去话,可以使用下面的语法在那个通道上拨号:
exten => 123,1,Dial(Zap/4/5551212)
这个例子在 Zap/4 通道上拨号码 555-1212。对于其它类型的通道,如 SIP 和IAX,简单的把被叫地作为资源,见下面两行:
exten => 123,1,Dial(SIP/1234)
exten => 124,1,Dial(IAX2/[email protected])
注意:任何的参量都可以为空。例如,假设要指定一个选项,但不是超时,
只要保留超时参量为空,如下所示:
exten => 123,1,Dial(Zap/1,,r)
Congestion() 该应用是播放“忙音”,让用户知道对方无应答或是振铃超时等原因。
SayNumber(${var}) 可以把变量var的值给读出来。
SayDigits()应用和SayNumber()应用的作用是一样的。
二、设置变量:
1、设置全局变量:设置全局变量有两种方法:
方法一:在名为global的context中去定义,定义方法如下:
[global]
jhon=sip/8003
smith=sip/8002
方法二:在extension中使用SetGlobalVar()来定义全局变量:
exten => s,1,SetGlobalVar(A=1)
或者
exten => s,1,Set(A=1,g)
这个g就是global的意思。
2、设置通道变量:
通道变量与特定的呼叫相关的变量(如 Caller*IDnumber),与全局变量不同,通道变量只能在当前呼叫存在其间定义,并只能用于参与该呼
叫的通道。有很多的预先定义的通道变量可以用于拨号方案,在 Asterisk 源程序的中doc 子目录下 README 文件中有详细的说明。通道变
量使用 Set( )应用来设置 :
exten => 123,1,Set(MAGICNUMBER=42)
3、环境变量的引用:
在Dialplan中我们还可以引用OS中定义的环境变量。引用的方法如下:
${ENV(var)} //这个引用的时候要加一个ENV()
4、Dialplan中变量的引用:
${var}
5、保留的字符:[ ] $ " /
如果要使用保留字符的时候,使用/前置,如:
exten => 1234,1,Set(AMOUNT="/$10.00")
•系统定义的一些变量:
${ANSWEREDTIME} :通话时长(以秒为单位)
${BLINDTRANSFER} :盲转的通道名称(The name of the channel on the other side of a blind transfer.)
${CHANNEL} :当前通道名称
${CONTEXT} :当前的上下文
${EPOCH} :当前的Unix时间(从Unix“epoch"运行开始的总秒数,1970,1,1,0点)
${EXTEN} :当前的被叫号码
三、匹配模式:
X 表示匹配0-9之间的任意一个数字
Z 表示匹配1-9之间的任意一个数字
N 表示匹配2-9之间的任意一个数字
. 表示匹配一个或多个字符
[15�\7] 匹配指定范围的一个数字。在这个例子中的样式要求匹配一个 1,以及 5,6,7 中的任意一个数字
! (叹号) 通配符;匹配零个或多个字符,不论它们是什么
还有一种说法是这个“!”表示:“只要清楚的不满足context中其他的类型匹配,就会执行此匹配对应的动作。 (this is known as 'overlap dialing'). 感觉像却缺省路由。
”
注意:要使用匹配模式必须以“_”开头,匹配的表达式,放在extensions名称的位置。
例如:公司里的分机全部是以8开头的四位号码,那么就这一条语句就可以搞定公司内部的所有电话互打。
exten => _8XXX,1,Dial(sip/${EXTEN},10,r)
注:这个${EXTEN} 是引用的一个通道变量,表示当前你所拨打的号码。
再如:公司的拨打外线都是通过加9出去的,那么可以这么来做:
exten => _9NXXXXXX,1,Dial(DAHDI/g0/${EXTEN:1})
注:${EXTEN:n}表示对输入的数字进行截取。n是要去掉的位数,从左边开始,如果n是负数的话,那就表示只保留最后n位数字
${EXTEN}变量还有一种表达式${EXTEN:x:y},其中 x 是起始位置(去掉这个位置及这个位置以前的数字),y 是返回的数字个数。给定下列字符串:
94169671111
我们可以利用${EXTEN:x:y}抽取下列数字:
l ${EXTEN:1:3} 得到 416
l ${EXTEN:4:7} 得到 9671111
l ${EXTEN:�\4:4} 将从倒数第 4 个数字开始,得到 1111
l ${EXTEN:2:�\4} 将从跳过 2 个数字开始,并不包括最后的 4 个数字,得到 16967
l ${EXTEN:�\6:�\4} 将倒数第 6 个数字开始,并不包括最后 4 个数字,得到 67
l ${EXTEN:1} 将返回第 1 个数字之后的全部数字,得到 4169671111(如果返回的数
字个数为空的话,它就返回剩余的全部数字)
这是一个非常强大的表达式,但是大部分这些变化并不常用。在大多数情况下,你将使用${EXTEN}(或者${EXTEN:1},如果你需要
去掉外线识别码) 。
四、表达式:
在asterisk中表达式要使用“$[]”给括起来,也就是 $[表达式]
例如:
$[${num} + 1] 将变量num的值加1
$[${num} / 3] 将变量num的值除以3
看下面的一个exten
exten=>321,1,set(num=3)
exten=>321,2,set(newnum=$[${num} + 1])
exten=>321,3,SayNumber(${newnum})
要注意的是:运算符要和数字之间隔开。
五、运算符:
Boolean operators(布尔型运算符)
这些运算符是求一个语句的真假值。在计算机术语中,基本上语句就是是和否(0 或者非 0,开或者关,等等) 。Boolean 运算符是:
或运算:
expr 1 | expr2
如果 expr1 的值是真值,那么运算符将赋 expr1 的值,否则将赋 expr2 的值(这个运算符称作“或”)
与运算:
expr 1 & expr2
如果两个表达式的值都为 true,运算符将赋值为 expr1。否则赋值为 0(这个运算符称作“与”)
expr 1 {=,>,>=,<,<=,|=} expr2
如果自变量都是整数,这些运算符将得到一个整数的比较结果;否则,它们将得到字符串的结果。如果给定的关系是正确地,这个结果是 1,否则就是0。
数学运算符
要执行一次计算吗?你需要这些:
expr1{+, -} expr2
这些运算符能得到整数自变量的加法或者减法地结果
expr1{*,/,%} expr2
这些运算符能分别得到整数自变量的乘法、除法或是余数的结果
六、拨号函数的使用:
拨号方案函数有以下基本语法:
FUNCTION_NAME(argument)
非常像变量,你可以类似上面引用函数名,但是你如果要引用函数的值,就要用美元符号“$”放在前面,用花括号“{}”括起函数表达式。
${FUNCTION_NAME(argument)}
例如:把自定义的变量的长度给读出来:
exten=12,1,set(test=abcdef)
exten=12,2,SayNumber($LEN(${test}))
LEN() 这个函数能计算出它的自变量的字符串长度。
七、条件分支
GotIf()使用一种特别的语法,经常叫做条件语法。
GotoIf(expression?destination1:destination2) //这个“?:”和.NET里是一样的用法。
GotoIfTime()就设计为查看一个系统的时间并用它来决定是否跟随不同的分支。
GotoIfTime(时间,星期,日期,月份?)
Monday Tuesday Wednesday Thursday Friday Saturday Sunday
Mon Tue Wed Thu Fri Sat Sun
January February March April May Jun July August September October November December
Jan Feb Mar Apr May Jul Aug Sep Oct Nov Dec
八、While 循环:
While()循环
exten => 1013,1,Answer()
exten => 1013,n,Set(i=1)
exten => 1013,n,While($[${i} < 10])
exten => 1013,n,SayNumber(${i})
exten => 1013,n,Wait(1)
exten => 1013,n,Set(i=$[${i} + 1])
exten => 1013,n,EndWhile()
exten => 1013,n,Hangup()
九、语音邮件:
语音邮件配置在配置文件 voicemail.conf 中配置和定义。这个文件包含语音邮件系统设置的分类,这样就可以客户化配置语音
邮件系统到你想要的状态。 在voicemail.conf 中, 覆盖所有的可用的可选项将是一个需要大量工作的过程, 但是示例配置已经配非常
好的注释过,而且很容易模仿着配置
正像拨号方案上下文可以分别保持你的拨号方案的不同部分一样, 语音邮件上下文允许从一个到另外一个邮箱,来定义不同的设
置。这就允许你为几个不同的公司或是办公室在同一个服务器定义不同的语音邮件设置。 语音邮件的上下文和拨号方案的上下文的定义方
法相同,使用方括号括住上下文名称。在我们的例子中,我们使用[default]作为语音邮件的上下文。
创建邮箱
在每一个语音邮件上下文中,我们定义不同的邮箱。定义邮箱的语法如下:
Mailbox=> password, name[,email[ , pager_email [, option ] ] ]
我们解释一下邮箱定义的每一部分:
Mailbox
这是邮箱的号码。它通常符合关联设置的扩展号码。
Password
这是邮箱主人用来访问自己的语音邮箱的数字密码。 如果使用者改变了她的密码,系统会升级在 voicemail.conf 文件中
的相应字段。
Name
这是邮箱主人的名字。 公司目录使用这个字段的文字使得主要用户拼写用户名。
Email
这是邮箱所有者的 email 地址。Asterisk 能发送语音邮件通知(包括语音邮件消息本身)到特定的邮箱。
Pager_email
这是邮箱所有者的呼机或是蜂窝电话的 email 地址。Asterisk 可以发送一个短的语音邮件通知消息到这个特定的 email 地址。
Options
这是一个选项列表,能设置邮箱所有者的时区等。 这有九个有效的选项:attach , servermail, tz , saycid, review,operator,
callback, dialout,和 exitcontext。这些选项应该是按照 option=value 格式成对出现,使用管道符号“|”分隔。 tz 选项设置用户
的时区到 voicemail.conf 的前面定义过的[zonemessage]中,其他八个选项在整个语音邮件范围内用同样的名字设置。
例如:我们设置语音邮件邮箱给 john 和 smith。 我们设置john的密码是1234,smith的密码是 4444 (记住, 这些是设置在voicemail.conf
中而不是 exensions.conf 中):
#vi /etc/asterisk/voicemail.conf
[default]
8001 => 1234,john sam,[email protected]
8002 => 4444,john smith,[email protected]
接下来要做的就是把语音邮件添加到拨号方案中去:(修改的是extensions.conf)
VoiceMail()应用将主叫方呼叫送到特定的邮箱,因此他能留下一个消息。邮箱应该被指定为 mailbox@context 形式, 在这的 context 是
语音邮件的上下文。邮箱号码后面也可以被加上前缀 b 或者 u,但是要用“,”隔开。如果是字母 b,主叫方将听到邮箱所有者忙音的消息。如果字母 u 使用,主叫方将
听到邮箱所有者的用户不可用的消息(如果存在的话) 。
[internal]
exten => _8XXX,1,Answer()
exten => _8XXX,2,Dial(sip/${EXTEN},10,r)
same => n,Gotoif($[${DIALSTATUS}=BUSY]?103) 当使用dial()时,系统会根据接通的状态来给DIALSTATUS来赋值。可以根据这个变量的值来进行语音留言。
same => n,VoiceMail(${EXTEN}@default,u)
same => n,Hangup()
same => 103,VoiceMail(${EXTEN}@default,b)
same => n,Hangup()
最后就是让用户能够接收语音邮件:
用户能够检索他们的语音邮件消息,改变他们的语音邮件选项,以及通过使用 VoicemailMain()应用记录他们的语音邮件问候语。在它的典型情况中,
VoicemailMain()以无任何变量形式调用。
可以在[internal]中增加一个8999的extension来让所有的用户都可以拨打这个8999来接收自己的语音邮件:
[internal]
exten => 8999,1,VoicemailMain() ---这个VoicemailMain()括号里还可以设置一个@default也就是voicemail.conf中的context。
这样语音邮件就完成了。!!
十、通话录音功能:
Monitor(format,path,options)
format:是录音时的格式,最好选择wav,如果选择的是alaw的话,那么在录音之后,会生成两个文件:一个“-in”,一个“-out”。但是,如果选择
录制的格式为wav的话,录制好后,就只有一个wav的文件,系统会自动把这两个文件合成一个文件(前提是options为“m”)。
path:是录音文件的存放路径。
options:是录制时的一些参数:常用的有“m”,也就是让系统在录制完成后,自动的把这两个文件合成一个文件,但是录制时候的文件的格式要选择正确。
还有一个是“b”,这个参数是说,只有当通道桥接通以后才开始录音,也就是当两个人开始讲话的时候才录音的。
文件的名称可以这样来定义:exten => 1,1,set(filename=${STRFTIME(${EPOCH},,%Y-%m-%d-%T)})
十一、宏的使用:
宏:就是一种子程序。简单示例:
[macro-incoming] //宏的context名称都是以macro-开头,后面跟上宏名称。
exten => s,1,Dial(SIP/${MACRO_EXTEN},10) //在宏中,一些系统变量的名称要以MACRO开头。
exten => s,n,VoiceMail(${MACRO_EXTEN}) //在宏中,分机名称一律只能设为s[sales]
exten => _2XXX,1,Macro(incoming) //调用宏时使用Macro()参数加上宏名称即可。
[building-mgr]
exten => _2XXX,1,Macro(incoming,ARG1,ARG2,......) //引用宏可以给宏加参数。