asterisk dialplan定义在/etc/asterisk目录下名为extensions.conf的配置文件中。
dialplan由四个层次的组件构成:上下文、分机、优先级和应用。
一、上下文
dialplan有上下文构成,上下文将dialplan划分为完全独立的各个部分。一个上下文中定义的分机与其他上下文中定义的分机完全无关,除非明确允许他们之间可以交互。
上下文的定义:通过在extensions.conf文件中将名字放置在方括号([])中实现的。上下文名字由字母A~Z(大写和小写)、数字0~9、连字符和下划线组成。一个处理来电的上下文可以简单地命名为:
[incoming]
上下文名字最长为79个字符(80个字符减去1个终止符null)。
[incoming_company_A]
在dialplan的开头,有两个特殊的字段,分别命名为[general]和[globals]。尽管它们使用了上下文语法,但并不是上下文。不要将[general]、[globals]和[default]作为上下文的名字,除此之外,随便使用你喜欢的名字。
二、分机
在电信领域,分机一词通常是指一个数字标识符,当该标识符被拨打时,电话(或者语音邮件、队列等系统资源)产生振铃。在Asterisk中,分机的功能更加强大,因为它定义了一系列唯一的步骤(每个步骤又包含应用),Asterisk通过这些步骤处理相应的呼叫。
在每个上下文中,我们可以根据需要定义很多个(或几个)分机。当一个特定的分机被(一个入向信道)触发时,Asterisk执行该分机已定义的步骤。
分机的语法是exten一词,后面跟着等于和大于号组成的箭头。
exten =>
分机的名字可以是数字和字母的任意组合。
分机中的每一个步骤包含三个部分:
- 分机的名字(或数字)
- 优先级(每个分机可以包含多个步骤,每个步骤的编号被称为“优先级”)
- 在该步骤中执行的应用(或命令)
这三个部分用逗号隔开,类似这样:
exten => name,priority,application()
一个简单的示例:
exten => 123,1,Answer()
分机的名字是123,优先级是1,应用是Answer()。
三、优先级
每个分机可以包括多个步骤,称为优先级。优先级从1开始按顺序编号,每个优先级执行一个特定的应用。
exten => 123,1,Answer()
exten => 123,2,Hangup()
非数字编号的优先级
语法与上面类似,但做了些简化。在较老的Asterisk版本中,优先级编号带来了很多问题。
假设一个分机有15个优先级,现在需要在步骤2中添加一些内容:后面所有的优先级都必须手动重新编号,Asterisk无法处理编号缺失或编号错误的步骤。
Asterisk从1.2版本开始解决了这个问题:引入了优先级n,n代表“next”。当Asterisk遇到名为n的优先级时,就会获得前一个优先级的编号并加1。这样就使得dialplan的修改变得更容易,因为不需要对所有步骤重新编号。如,你的dialplan可能像这样:
exten => 123,1,Answer()
exten => 123,n,do something
exten => 123,n,do something else
exten => 123,n,do one last thing
exten => 123,n,Hangup()
注意:必须指定优先级1,否则你会发现重新加载的dialplan后无法找到这个分机。
"same => "操作符
只要分机没有变化,就只需要简单地输入same =>,后面跟着优先级和应用就可以了,不需要在每一行中输入完整的分机名:
exten => 123,1,Answer()
same => n,do something
same => n,do something else
same => n,do one last thing
same => n,Hangup()
优先级标签
优先级标签允许为分机中的优先级分配一个名字。使用其他方式引用优先级。当我们需要将呼叫从dialplan的其他地方转到另一个分机的某个优先级中。如果要为优先级分配一个文本标签,只需要将该标签添加到优先级后面的括号里,就像这样:
exten => 123,n(label),application()
注意:不要在n和(之间插入逗号,像这样:
exten => 555,n,(label),application() ;<-- THIS WON'T WORK
exten => 556,n(label),application() ;<-- This is what we want
这个错误会破坏你的dialplan,你会收到一个错误提示:找不到应用。
四、应用
每个应用在当前信道上执行特定的操作,例如播放声音、接受按键输入、检索数据库、拨打某个信道、挂断电话等。
Answer()、Playback()和Hangup()应用
Answer()
应用用于应答正在振铃的信道。Answer()告知信道将呼叫已接听的消息发回远端并使能媒体路径(在呼叫者和系统之间传递声音的网络流),Answer()不需要参数。虽然Answer()并不是必需的(甚至在某些情况下根本就不适合使用),但是在执行进一步操作之前,这是确保信道已连接的有效方法。
Playback()
应用用于在信道上播放事先录制好的声音文件。在播放过程中,用户的所有输入都会被忽略,这意味着你不应该在自动应答机中使用Playback(),除非你不想接受任何输入Asterisk中附带了很多专业的声音录制文件,可以在默认的声音目录(一般是/var/lib/asterisk/sounds)中找到这些文件。
如果要使用Playback(),请指定一个文件名作为参数。例如,Playback(filename)会播放一个名为filename.wav的声音文件(假设在默认的声音目录中存在该文件)。请注意,如果需要的话也可以包含文件的完整路径,例如:
Playback(/home/john/sounds/filename)
也可以使用相对路径:
Playback(custom/filename)
这个示例会播放默认声音目录中custom子目录中的filename.wav(可能是/var/lib/asterisk/sounds/en/custom/filename.wav)。
Hangup()
的作用与其名字所蕴含的意思完全相同:挂断处于活动状态的信道。当你想要结束当前呼叫时,应该在上下文的最后使用这个应用,以确保呼叫者不会以你无法预料的方式继续执行dialplan中的操作。Hangup()不需要任何参数,但是如果需要的话,也可以传递一个ISDN原因代码(例如Hangup(16)),这个代码会被转换成等同的SIP消息并发送到远端。
文章内容参考和来源于:《Asterisk权威指南(第5版)》