freeswitch学习笔记:将电话路由到Lua脚本


在快速测试的情况下,可以直接使用如下的originate命令在FreeSWITCH中外呼一路通话,并在电话的本端执
行Lua脚本:
originate user/1000 &lua(test.lua)
其中,lua是一个App,它的参数就是脚本的名字,脚本的默认路径在安装路径的scripts目录下,当然你也可
以指定一个绝对路径,如/tmp/test.lua。
在Dialplan XML中,使用下列配置便可将进入Dialplan的电话(Channel)交给Lua脚本接管。
<action application="lua" data="test.lua"/>
当然,除此之外,也可以直接使用uuid_transfer命令直接配合inline Dialplan将一个Channel路由到Lua脚
本,如:
uuid_transfer <uuid> lua:/tmp/test.lua inline
总之,这里的Lua是一个标准的App,在任何可以使用App的地方都可以使用它(如上面介绍的各种场景,以及
后面要介绍的Event Socket等。甚至在Lua脚本中也可以再次使用lua App来调用下一个Lua脚本)。
16.2.3 Session相关函数
在Lua环境中,FreeSWITCH会自动生成一个session对象(实际上是一个Table),因而可以在Lua脚本中使用
Lua类似面向对象的语法特性编程,如以下脚本放播放欢迎声音 [6]:
--
session:answer()
--
session:sleep(1000)
--
session:streamFile("/tmp/hello-lua.wav")
--
session:hangup()
大部分与Session有关的函数都是跟FreeSWITCH中的App是一一对应的,如上面的answer、hangup等。有一点
要特别说明:streamFile对应playback这个App。如果在Lua中没有对应的函数,也可以通过session:execute()函
数来执行相关的App,如session:execute("playback","/tmp/sound.wav")与
session:streamFile("/tmp/sound.wav")是等价的 [7]。
需要注意,Lua脚本执行完毕后默认会挂断电话,所以上面的Hello Lua例子中不需要明确的
session:hangup()。如果想在Lua脚本执行完毕后继续执行Dialplan中的后续流程,则需要在脚本开始处先设置不
要自动挂机,语法如下:
session:setAutoHangup(false)
例如下列场景,test.lua执行完毕后(假设没有session:hangup(),主叫也没有挂机),如果没有
setAutoHangup(false),则后续的playback动作得不到执行。
<extension name="test-lua">
<condition field="destination_number" expression="^1234$">
<action application="answer"/>
<action application="lua" data="test.lua"/>
<action application="playback" data="lua-script-complete.wav"/>
</condition>
</extension>
下面,我们来讲与Ssession相关的几个常用的函数:
·getVariable。取得变量的值,如:
local moh = session:getVariable("hold_music")
local dest_number = session:getVariable("context")
local dest_number = session:getVariable("destination_number")
local cid_name = session:getVariable("caller_id_name")
local cid_number = session:getVariable("caller_id_number")
local ani = session:getVariable("ani")
local uuid = session:getVariable("uuid")
·getUUID。取得当前Session的UUID,下列两行是等价的:
local uuid = session:get_uuid(]);
local uuid = session:getVariable("uuid")
·setVariable。设置通道变量,等价于Dialplan App里的set:
session:setVariable("varname", "varval")
·hangup。挂断当前通话:
session:hangup();
也可以同时指定挂断原因,如以下函数将在挂断时向对方返回用户忙:
session:hangup("USER_BUSY")
·ready。检查Session是否可正常使用,如果已经挂机就会返回false。
在写脚本时,如果有循环,一定需要经常检测session:ready()是否为true,否则Session挂机后Lua脚本可能
仍然在死循环地运行。
while (session:ready() == true) do
-- do something here
end
·streamFile:放音,相当于Dialplan App里的playback。
session:streamFile("/tmp/test.wav")
·recordFile:录音,相当于Dialplan App里的record,参数是:
file_name [,max_len_secs] [,silence_threshold] [,silence_secs]
其中,各参数含义如下:
·file_name:录音文件名。
·max_len_secs:录音最长的秒数。
·silence_threashold:一个声音阈值,如果声音小于该值,就认为是静音。
·silence_secs:如果静音时长大于一定秒数,则停止录音。
例如,以下函数将对当前的Channel录音,并存放到/tmp/test_record.wav中:
session:recordFile("/tmp/test_record.wav")
·read。类似于Dialplan App中的read,用于播放一个声音并获取DTMF。它的5个参数与read含义相同:
<min digits><max digits><file to play><inter-digit timeout><terminators>
6.4节介绍的身份证号的例子用Lua改写如下:
digits = session:read(15, 18, "/tmp/input-id-card.wav", "5000", "#");
session:("log", "INFO ID Card Number: ".. digits .."\n");
读者可以发现Lua中的read比Dialplan App中的read少了一个参数。由于session:read()能返回值,因此那个
参数就不需要了,实际收到的DTMF会返回到本例的digits变量中。
·playAndGetDigits。与Dialplan App中的play_and_get_digits类似,它的参数格式是:
<min_digits>, <max_digits>, <max_attempts>, <timeout>, <terminators>,<prompt_audio_files>,
<input_error_audio_files>,<digit_regex>, [variable_name], [digit_timeout],
[transfer_on_failure])
其中,大部分参数都很直观,也跟play_and_get_digits中类似。其中timeout是收齐所有号的超时值,而
digit_timeout是允许的两次按键之音的时间间隔最大值,最后transfer_on_failure指明如果失败后是否转到
Dialplan中的一个Extension上去,它的格式应该是一个Dialplan三要素的格式串,如“failed XML
dialplan”。
我们把6.4节中的身份证号的例子重写如下:
digits = session:playAndGetDigits(15, 18, 3, 10000, "#",
"/tmp/input-id-card.wav", "/tmp/invalid_num.wav",
"^\\d{15}|\\d{17}[0-9\\*]$")
session:execute("log", "INFO ID Card Number: ".. digits .."\n");
·setInputCallback。在放音或录音时,用户按下的DTMF可以用于触发一些功能。所以在这些状态下,Lua
支持如果收到DTMF等外部输入时,则调用相关的回调函数。setInputCallback的作用就是设置(安装)一个回调函
数。
01 function onInputCBF(s, type, obj, arg)
02 if (type == "dtmf") then
03 freeswitch.consoleLog("INFO",
04 "Got DTMF: " .. obj.digit .. " Duration: " .. obj.duration .. "\\n")
05 if (obj.digit == "3") then
06 return 'break'
07 end
08 end
09 return ''
10 end
11 session:setInputCallback('onInputCBF', '');
12 session:streamFile("local_stream://moh");
其中,第1行,我们定义了一个回调函数onInputCBF,并在第11行使用setInput-Callback将该函数绑定到该
Session上。第12行执行streamFile实现一直不停地播放等待音乐。当用户按下话机上的键时,FreeSWITCH就会回
调上面指定的回调函数。下面我们来看一下该函数的内容。
回调函数一共有4个参数,在这里我们只关注type和obj两个参数。在此,由于我们的回调函数是由DTMF触发
的,因此这里的type值为“dtmf”。obj是一个Table,它的两个Key分别是digit和duration,分别表示DTMF的链
值和时长。
上面的例子中第2行测试该回调是否是由DTMF引起,如果是,就打印相关DTMF信息。在第5行测试如果用户按
了3的话,就返回break。返回break会停止当前正在执行的App(在这里我们正在播放保持音乐),如果后面没有
其他脚本语句的话,Lua App就会退出。如果返回空值(空字符串,如第9行),则它什么也不做。
如果我们顺序按1、2、3,则上面例子在控制台上的输出结果如下:
[INFO] switch_cpp.cpp:1288 Got DTMF: 1
[INFO] switch_cpp.cpp:1288 Got DTMF: 2
[INFO] switch_cpp.cpp:1288 Got DTMF: 3
除DTMF外,回调还可能由其他的输入引起,如在进行语音识别的时候识别到相关关键词,这里我们就不多介
绍了。
另外,使用unsetInputCallback函数也可以取消刚才设置的回调函数,在此我们就不多讲了。更多与Session
相关的函数可以参考相关的wiki文档:http://wiki.freeswitch.org/wiki/Mod_lua。

猜你喜欢

转载自blog.csdn.net/irizhao/article/details/88684089
今日推荐