首页 > 新闻 > 专家观点 >

《FreeSWITCH: VoIP实战》:拨号计划- Dialplan

2012-08-17 15:51:59   作者:杜金房   来源:CTI论坛   评论:0  点击:


  可以看到,由于我们呼叫的是 1235,它在第三行测试 My Echo Test 的 1234 的时候失败了,接在接下来测试 1235的时候成功了,便执行相对应的 Action - info 这个APP。它的作用就是把所有 Channel Variables 都打印到 Log 中。

  所有的 Channel Variable 都是可以在 Dialplan 中访问的,使用格式是 ${变量名},如 ${destination_number}。将下列配置加入 Dialplan 中(存盘,reloadxml 不用再说了吧?):

<extension name="Accessing Channel Variable">
  <condition field="destination_number" expression="^1236(\d+)$">
    <action application="log" data="INFO Hahaha, I know you called ${destination_number}"/>
    <action application="log" data="INFO The Last few digists is $1"/>
    <action application="log" data="ERR This is not actually an error, just jocking"/>
    <action application="hangup"/>
  </condition>
</extension>

这次我们呼叫 1236789,看看结果:

Processing Seven <1000>->1236789 in context default
parsing [default->Echo Test] continue=false
Regex (FAIL) [Echo Test] destination_number(1236789) =~ /^echo|1234$/ break=on-false
parsing [default->Show Channel Variable] continue=false
Regex (FAIL) [Show Channel Variable] destination_number(1236789) =~ /^1235$/ break=on-false
parsing [default->Accessing Channel Variable] continue=false
Regex (PASS) [Accessing Channel Variable] destination_number(1236789) =~ /^1236(\d+)$/ break=on-false
Action log(INFO Hahaha, I know you called ${destination_number})
Action log(NOTICE The Last few digists is 789)
Action log(ERR This is not actually an error, just jocking)
Action hangup()

[DEBUG] switch_core_state_machine.c:157 sofia/internal/1000@192.168.7.10 Standard EXECUTE

EXECUTE sofia/internal/1000@192.168.7.10 log(INFO Hahaha, I know you called 1236789)
[INFO] mod_dptools.c:1152 Hahaha, I know you called 1236789
EXECUTE sofia/internal/1000@192.168.7.10 log(NOTICE The Last few digists is 789)
[NOTICE] mod_dptools.c:1152 The Last few digists is 789
EXECUTE sofia/internal/1000@192.168.7.10 log(ERR This is not actually an error, just jocking)
[ERR] mod_dptools.c:1152 This is not actually an error, just jocking
EXECUTE sofia/internal/1000@192.168.7.10 hangup()

   跟前面一样,我们还是从绿色的行开始看。这一次,1236789 匹配了正则表达式 ^1236(\d+),并将 789 存储在变量 $1 中。然后在 8-11 行看到它解析出的四个 Action(三个 log 一个 hangup)。到这里为止,Channel 的状态一直没有变,还处在路由查找的阶段。在所有 Dialplan 解析完成后,Channel 状态才进行 Standard Execute 阶段。理解这一点是非常重要的,我们后面再做详细说明,但是在这里你要记住路由查找(解析)和执行分属于不同的阶段。当 Channel 状态进入执行阶段后,它才开始依次执行所有的 Action。log() 的作用就是将信息写到 Log 中,它的第一个参数是 leglevel,就是 Log 的级别,有 INFO、Err、DEBUG等,不同的级别在彩色的终端上能以不同的颜色显示。(详细的级别请参考http://wiki.freeswitch.org/wiki/Mod_logfile#Log_Levels)。

  你肯定看到彩色的 Log 了,同时也看到了用 $ 表示的 Channel Variable 被替换成了相应的值。

  同时你也看到,这次实验我们特意增加了几个 Action。一个 Action 通常有两个参数,一个是 application,代表要执行的 APP,另一个是 data,就是 APP 的参数,当 APP 没有参数时,data也可能省略。

  一个 Action 必须是一个合法的 XML 标签,在前面,你看到的 context,extension 等都是成对出现的,如 。但由于 Action 比较简单,一般彩用简写的形式来关闭标签,即 。注意大于号前面的“/”,如果不小漏掉,在 reloadxml 时将会出现类似“+OK [[error near line 3371]: unexpected closing tag ]” 的错误,而实际的错误位置又通常不是出错的那一行。这是在编辑 XML 文件时经常遇到的问题,又比较难于查找。因此在修改时要多加小心,并推荐使用具有语法高亮的功能的编辑器来编辑。

   读到这里,你或许还有疑问,既然我们在 info APP 的输出里没看到 destination_number这一变量,它到底是从哪里来的呢?是这样的,它在 info 中的输出是 Caller-Destination-Number,但你在引用的时候就需要使用 destination_number。还有一些变量,在 info 中的输出是 variable_xxxx,如 variable_domain_name,而实际引用时要去掉 variable_ 前缀。不要紧张,这里有一份对照表: http://wiki.freeswitch.org/wiki/Channel_Variables#Info_Application_Variable_Names_.28variable_xxxx.29

测试条件 - Conditions
动作与反动作 - Action & Anti-Action
工作机制进阶
实例解析
...

  以上的论述应该涵盖了 Dialplan 的所有概念,当然,要活学活用,还需要一些经验。下面,我们讲几个真实的例子。这些例子大部分来自默认的配置文件。

   Local_Extension

  我们要看的第一个例子是 Local_Extension。 FreeSWITCH 默认的配置提供了 1000 - 1019 共 20 个 SIP 账号,密码都是 1234 。

<extension name="Local_Extension">
    <condition field="destination_number" expression="^(10[01][0-9])$">
    //actions
    </condition>
</extension>

   这个框架说明,用正则表达式 (10[01][0-9])$ 来匹配被叫号码,它匹配所有 1000 - 1019 这 20 个号码。

  这里我们假设在 SIP 客户端上,用 1000 和 1001 分别注册到了 FreeSWITCH 上,则 1000 呼叫 1001 时,FreeSWITCH 会建立一个 Channel,该 Channel 构成一次呼叫的 a-leg(一条腿)。初始化完毕后,Channel 进入 ROUTING 状态,即进入 Dialplan。由于被叫号码 1001 与这里的正则表达式匹配,所以,会执行下面这些 Action。另外,由于我们在正则表达式中使用了 “( )”,因此,匹配结果会放入变量 $1 中,因此,在这里,$1 = 1001。

<action application="set" data="dialed_extension=$1"/>
<action application="export" data="dialed_extension=$1"/>

  set 和 export 都是设置一个变量,该变量的名字是 dialed_extension,值是 1001。

  关于 set 和 export 的区别我们在前面已经讲过了。这里再重复一次: set 是将变量设置到当前的 Channel 上,即 a-leg。而 export 则也将变量设置到 b-leg 上。当然,这里 b-leg 还不存在。所以在这里它对该 Channel 的影响与 set 其实是一样的。因此,使用 set 完全是多余的。但是除此之外,export 还设置了一个特殊的变量,叫 export_vars,它的值是dialed_extension。所以,实际上。上面的第二行就等价于下面的两行:

<action application="set" data="dialed_extension=$1"/>
<action application="set" data="export_vars=dialed_extension"/>

<!-- bind_meta_app can have these args <key> [a|b|ab] [a|b|o|s] <app> -->
<action application="bind_meta_app" data="1 b s execute_extension::dx XML features"/>
<action application="bind_meta_app" data="2 b s record_session::$${recordings_dir}/${caller_id_number}.${strftime(%Y-%m-%d-%H-%M-%S)}.wav"/>
<action application="bind_meta_app" data="3 b s execute_extension::cf XML features"/>
<action application="bind_meta_app" data="4 b s execute_extension::att_xfer XML features"/>

bind_meta_app 的作用是在该 Channel 是绑定 DTMF。上面四行分别绑定了 1、2、3、4 四个按键,它们都绑定到了 b-leg上。注意,这时候 b-leg 还不存在。所以,请记住这里,我们下面再讲。

<action application="set" data="ringback=${us-ring}"/>

设置回铃音是美音(不同国家的回铃音是有区别的),${us-ring} 的值是在 vars.xml 中设置的。

<action application="set" data="transfer_ringback=$${hold_music}"/>

设置呼叫转移时,用户听到的回铃音。

<action application="set" data="call_timeout=30"/>

设置呼叫超时。

<action application="set" data="hangup_after_bridge=true"/>
<!--<action application="set" data="continue_on_fail=NORMAL_TEMPORARY_FAILURE,USER_BUSY,NO_ANSWER,TIMEOUT,NO_ROUTE_DESTINATION"/> -->
<action application="set" data="continue_on_fail=true"/>

这些变量影响呼叫流程,详细说明见下面的 bridge。

<action application="hash" data="insert/${domain_name}-call_return/${dialed_extension}/${caller_id_number}"/>
<action application="hash" data="insert/${domain_name}-last_dial_ext/${dialed_extension}/${uuid}"/>
<action application="hash" data="insert/${domain_name}-last_dial_ext/${called_party_callgroup}/${uuid}"/>
<action application="hash" data="insert/${domain_name}-last_dial_ext/global/${uuid}"/>

相关阅读:

分享到: 收藏

专题