FreeSwitch LUA API ——Non-Session API
2016-07-12 16:33
721 查看
目录浏览:
Non-Session API
freeswitch.API
freeswitch.bridge
freeswitch.consoleCleanLog
freeswitch.consoleLog
freeswitch.Dbh
freeswitch.email
freeswitch.Event
freeswitch.EventConsumer
freeswitch.getGlobalVariable
freeswitch.IVRMenu
freeswitch.msleep
freeswitch.Session
stream:write
API commands
Web page interaction (via mod_xml_rpc)
Example: Call Control
Special Case: env object
freeswitch.API
当从拨号计划(dialplan)中调用LUA脚本后,将会得到一个session对象。然而LUA脚本也能在命令行界面(CLI)被调用。无论是那种情况下,在LUA中,当创建完一个API对象后,就可以执行API命令了。
在以上的代码段中,LUA变量将会从FreeSWTICH中接收到版本号。
也可以做一些复杂的操作,例如:
LUA变量sofia将包含sofia status命令的所有输出。
freeswitch.bridge
freeswitch.consoleCleanLog
freeswitch.consoleLog
向FreeSWITCH记录器记录一些数据,参数为log级别,消息
freeswitch.Dbh
作用:从FreeSWITCH中获得一个ODBC或者sqlite句柄,并且可以在用该句柄执行SQL语句。
这种方法的优点是充分利用了由FreeSWITCH提供的连接池,即当创建的LUASQL env:connect()的TCP连接增加时,对于每个连接的速度不会有太大的影响。
工作流程如下:
-freeswitch.Dbh(odbc://my_db:uname:passwd):从连接池中获得一个ODBC的句柄-freeswitch.Dbh("sqlite://my_db"):从连接池中获得一个SQLITE句柄 (如果不存在也会自动创建)。-dbh:connected():检查句柄时候还与数据保持连接,如果是则返回true,否则返回false-dbh:test_reactive("test_sql","drop_sql", "reactive_sql"):运行test.sql,如果失败则执行drop_sql和reactive.sql(适用于初始化表创建的目的)-dbh:query("query", function()):将“query”当做一个字符串执行,从数据库中返回的结果的每一行都会调用LUA的回调函数进行处理。
1.在每次遍历时,回调函数将获得一个以表的形式表示的行数据对于每一行的语法为:{ ["column_name_1"]= "value_1", ["column_name_2"] = "value_2" }.
2.如果回调函数返回一个非0值,将终止循环
dbh:affected_rows() :除了select操作外,返回对应操作受影响的行数dbh:release() (可选) :释放句柄至连接池中,供其他线程的重复使用。当dbh超出作用范围或者被垃圾回收机制回收(例如脚本返回)时该操作也将被自动执行。在长期运行的脚本中,及时释放连接是十分有必要的。
freeswitch.email
作用:发送一封邮件(可带附件)
需要注意的是,如果要用该功能,需要在服务器上安装MTA,当然还需要在switch.conf.xml中配
fe60
置mailer-app
语法:
参数说明:
freeswitch.Event
作用:生效(firing)一个普通事件my::event
freeswitch.EventConsumer
作用:处理(consume)FreeSWITCH的事件
用法:
示例:
freeswitch.getGobalVariable
作用:检索一个全局变量
freeswitch.IVRMenu
当使用”SAY”时,需要设置三个额外的变量,否则你将会得到以下的错误:
这三个变量为:
freeswitch.msleep
作用:通知脚本休眠一段时间(单位:毫秒)
注意:不要用在基于会话的脚本中,否则坏事将发生
freeswitch.Session
作用:创建一个新会话(session)
根据变量execute_on_answer创建一个新会话:
stream:write
作用:你可以根据LUA FreeSWITCH API命令,在LUA中写FreeSWITCH API命令并运行LUA脚本,还可以带一些参数。然后就可以在命令行中得到你写的流对象对应的结果。例如,在scripts中放入hello.lua脚本,然后在命令行中调用该脚本。
在FreeSWITCH的命令行界面执行lua hello.lua即可返回hello world。
或者在拨号计划(dialplan)中调用它:
以上命令将信道变量foo设置为hello world
网页交互示例(调用mod_xml_rpc)
示例:呼叫控制
SpecialCase:env object(特殊案例:环境对象)
当将LUA脚本当做挂断钩子(hangup hook)调用时,将产生一个包含刚刚失去连接的信道中所有的信道变量的特殊对象——env
添加一个extension来测试这个特性
然后添加scripts目录下添加hook-test.lua:
查看FS控制台,拨打1234并挂断,你将看到相关信道的所有变量
翻译出处:https://freeswitch.org/confluence/display/FREESWITCH/mod_lua
注:译者翻译能力有限,欢迎指明
Non-Session API
freeswitch.API
freeswitch.bridge
freeswitch.consoleCleanLog
freeswitch.consoleLog
freeswitch.Dbh
freeswitch.email
freeswitch.Event
freeswitch.EventConsumer
freeswitch.getGlobalVariable
freeswitch.IVRMenu
freeswitch.msleep
freeswitch.Session
stream:write
API commands
Web page interaction (via mod_xml_rpc)
Example: Call Control
Special Case: env object
freeswitch.API
api = freeswitch.API(); -- get current time in milliseconds time = api:getTime() |
api = freeswitch.API(); reply = api:executeString("version"); |
也可以做一些复杂的操作,例如:
api = freeswitch.API(); sofia = api:executeString("sofia status"); |
freeswitch.bridge
session1 = freeswitch.Session("sofia/internal/1001%192.168.1.1"); session2 = freeswitch.Session("sofia/internal/1002%192.168.1.1"); freeswitch.bridge(session1, session2); |
freeswitch.consoleCleanLog
freeswitch.consoleCleanLog("This Rocks!!!\n"); |
freeswitch.consoleLog
向FreeSWITCH记录器记录一些数据,参数为log级别,消息
freeswitch.consoleLog("info", "lua rocks\n"); freeswitch.consoleLog("notice", "lua rocks\n"); freeswitch.consoleLog("err", "lua rocks\n"); freeswitch.consoleLog("debug", "lua rocks\n"); freeswitch.consoleLog("warning","lua rocks\n"); |
freeswitch.Dbh
作用:从FreeSWITCH中获得一个ODBC或者sqlite句柄,并且可以在用该句柄执行SQL语句。
这种方法的优点是充分利用了由FreeSWITCH提供的连接池,即当创建的LUASQL env:connect()的TCP连接增加时,对于每个连接的速度不会有太大的影响。
工作流程如下:
local dbh = freeswitch.Dbh("dsn","user","pass") -- when using ODBC (deprecated) -- OR -- local dbh = freeswitch.Dbh("core:my_db") -- when using sqlite (deprecated, if you have to use this to make it work you should upgrade your FS installation) -- OR -- local dbh = freeswitch.Dbh("sqlite://my_db") -- sqlite database in subdirectory "db" -- OR -- local dbh = freeswitch.Dbh("odbc://my_db:uname:passwd") -- connect to ODBC database assert(dbh:connected()) -- exits the script if we didn't connect properly dbh:test_reactive("SELECT * FROM my_table", "DROP TABLE my_table", "CREATE TABLE my_table (id INTEGER(8), name VARCHAR(255))") dbh:query("INSERT INTO my_table VALUES(1, 'foo')") -- populate the table dbh:query("INSERT INTO my_table VALUES(2, 'bar')") -- with some test data dbh:query("SELECT id, name FROM my_table", function(row) stream:write(string.format("%5s : %s\n", row.id, row.name)) end) dbh:query("UPDATE my_table SET name = 'changed'") stream:write("Affected rows: " .. dbh:affected_rows() .. "\n") dbh:release() -- optional |
1.在每次遍历时,回调函数将获得一个以表的形式表示的行数据对于每一行的语法为:{ ["column_name_1"]= "value_1", ["column_name_2"] = "value_2" }.
2.如果回调函数返回一个非0值,将终止循环
dbh:affected_rows() :除了select操作外,返回对应操作受影响的行数dbh:release() (可选) :释放句柄至连接池中,供其他线程的重复使用。当dbh超出作用范围或者被垃圾回收机制回收(例如脚本返回)时该操作也将被自动执行。在长期运行的脚本中,及时释放连接是十分有必要的。
freeswitch.email
作用:发送一封邮件(可带附件)
需要注意的是,如果要用该功能,需要在服务器上安装MTA,当然还需要在switch.conf.xml中配
fe60
置mailer-app
语法:
freeswitch.email(to, from, headers, body, file, convert_cmd, convert_ext) |
参数 | 是否必要 | 作用 |
to | 是 | 一个有效的收件人地址 |
from | 是 | 一个有效的发件人地址 |
headers | 是 | 标题名 |
body | 否 | 正文 |
file | 否 | 附件 |
convert_cmd | 否 | 发送前转换成其他格式 |
convert_ext | 否 | 替换文件(file)的拓展名 |
freeswitch.email("receiver@bar.com", "sender@foo.com", "subject: Voicemail from 1234\n", "Hello,\n\nYou've got a voicemail, click the attachment to listen to it.", "message.wav", "mp3enc", "mp3") |
freeswitch.Event
作用:生效(firing)一个普通事件my::event
local event = freeswitch.Event("custom", "my::event"); event:addHeader("My-Header", "test"); event:fire(); -- Send an event MESSAGE to a receiver function FSMan:fire(nameHeader, header, body) local myEvent = freeswitch.Event("MESSAGE"); nameHeader = Utils:trim(nameHeader); header = Utils:trim(header); body = Utils:trim(body); if (nameHeader == false ) then nameHeader="Generic_Name_Header" end if (header == false) then header="Header_Generic" end if (body == false) then body="Body_Generic" end myEvent:addHeader(nameHeader, header); myEvent:addBody(body); myEvent:fire(); end |
freeswitch.EventConsumer
作用:处理(consume)FreeSWITCH的事件
用法:
con = freeswitch.EventConsumer("<event_name>"[,"<subclass type>"]); -- pop() returns an event or nil if no events con:pop() -- pop(1) blocks until there is an event con:pop(1) -- pop(1,500) blocks for max half a second until there is an event con:pop(1,500) |
con = freeswitch.EventConsumer("all"); session = freeswitch.Session("sofia/default/dest@host.com"); while session:ready() do session:execute("sleep", "1000"); for e in (function() return con:pop() end) do print("event\n" .. e:serialize("xml")); end end -- or while session:ready() do for e in (function() return con:pop(1,1000) end) do print("event\n" .. e:serialize("xml")) end end -- You may subscribe to specific events if you want to, and even subclasses con = freeswitch.EventConsumer("CUSTOM"); con = freeswitch.EventConsumer("CUSTOM","conference::maintenance"); -- wait for a specific event but continue after 500 ms function poll() -- create event and listener local event = freeswitch.Event("CUSTOM", "ping::running?") local con = freeswitch.EventConsumer("CUSTOM", "ping::running!") -- add text ad libitum event:addHeader("hi", "there") -- fire event event:fire() -- and wait for reply but not very long if con:pop(1, 500) then print("reply received") return true end print("no reply") return false end |
freeswitch.getGobalVariable
作用:检索一个全局变量
my_globalvar = freeswitch.getGlobalVariable("varname") |
freeswitch.IVRMenu
hash = { ["main"] = undef, ["name"] = "top", ["greet_long"] = "phrase:demo_ivr_main_menu", ["greet_short"] = "phrase:demo_ivr_main_menu_short", ["invalid_sound"] = "ivr/ivr-that_was_an_invalid_entry.wav", ["exit_sound"] = "voicemail/vm-goodbye.wav", ["confirm_macro"] = "undef", ["confirm_key"] = "undef", ["confirm_attempts"] = "3", ["inter_digit_timeout"] = "2000", ["digit_len"] = "1", ["timeout"] = "10000", ["max_failures"] = "3" } top = freeswitch.IVRMenu(hash["main"], hash["name"], hash["greet_long"], hash["greet_short"], hash["invalid_sound"], hash["exit_sound"], hash["confirm_macro"], hash["confirm_key"], hash["confirm_attempts"], hash["inter_digit_timeout"], hash["digit_len"], hash["timeout"], hash["max_failures"]); top:bindAction("menu-exec-app", "playback /tmp/swimp.raw", "2"); top:execute(session, "top"); |
> [ERR] mod_lua.cpp:182 Error in IVRMenu expected 16..16 args, got 13 stack traceback: > [C]: in function 'IVRMenu' > /usr/local/freeswitch/scripts/ivr.lua:19: in main chunk |
["tts_engine"] = "flite", ["tts_voice"] = "rms", ["max_timeouts"] = "2" |
freeswitch.msleep
作用:通知脚本休眠一段时间(单位:毫秒)
注意:不要用在基于会话的脚本中,否则坏事将发生
-- Sleep for 500 milliseconds freeswitch.msleep(500); |
freeswitch.Session
作用:创建一个新会话(session)
local session = freeswitch.Session("sofia/10.0.1.100/1001"); session:transfer("3000", "XML", "default"); |
local session = freeswitch.Session("[execute_on_answer=info notice]sofia/10.0.1.100/1001"); |
stream:write
作用:你可以根据LUA FreeSWITCH API命令,在LUA中写FreeSWITCH API命令并运行LUA脚本,还可以带一些参数。然后就可以在命令行中得到你写的流对象对应的结果。例如,在scripts中放入hello.lua脚本,然后在命令行中调用该脚本。
stream:write("hello world") |
或者在拨号计划(dialplan)中调用它:
<action application="set" data="foo=${lua(hello.lua)}"/> |
网页交互示例(调用mod_xml_rpc)
-- -- lua/api.lua -- -- enable mod_xml_rpc and try http://127.0.0.1:8080/api/lua?lua/api.lua in your webbrowser -- stream:write("Content-Type: text/html\n\n"); stream:write("<title>FreeSWITCH Command Portal</title>"); stream:write("<h2>FreeSWITCH Command Portal</h2>"); stream:write("<form method=post><input name=command size=40> "); stream:write("<input type=submit value=\"Execute\">"); stream:write("</form><hr noshade size=1><br>"); command = env:getHeader("command"); if (command) then api = freeswitch.API(); reply = api:executeString(command); if (reply) then stream:write("<br><B>Command Result</b><br><pre>" .. reply .. "</pre>\n"); end end env:addHeader("cool", "true"); stream:write(env:serialize() .. "\n\n"); |
示例:呼叫控制
-- -- call control lua script -- dialA = "sofia/gateway/fs1/9903" dialB = "user/1001" legA = freeswitch.Session(dialA) dispoA = "None" while(legA:ready() and dispoA ~= "ANSWER") do dispoA = legA:getVariable("endpoint_disposition") freeswitch.consoleLog("INFO","Leg A disposition is '" .. dispoA .. "'\n") os.execute("sleep 1") end -- legA while if( not legA:ready() ) then -- oops, lost leg A handle this case freeswitch.consoleLog("NOTICE","It appears that " .. dialA .. " disconnected...\n") else legB = freeswitch.Session(dialB) dispoB = "None" while(legA:ready() and legB:ready() and dispoB ~= "ANSWER") do if ( not legA:ready() ) then -- oops, leg A hung up or got disconnected, handle this case freeswitch.consoleLog("NOTICE","It appears that " .. dialA .. " disconnected...\n") else os.execute("sleep 1") dispoB = legB:getVariable("endpoint_disposition") freeswitch.consoleLog("NOTICE","Leg B disposition is '" .. dispoB .. "'\n") end -- inner if legA ready end -- legB while if ( legA:ready() and legB:ready() ) then freeswitch.bridge(legA,legB) else -- oops, one of the above legs hung up, handle this case freeswitch.consoleLog("NOTICE","It appears that " .. dialA .. " or " .. dialB .. " disconnected...\n") end end -- outter if legA ready |
SpecialCase:env object(特殊案例:环境对象)
当将LUA脚本当做挂断钩子(hangup hook)调用时,将产生一个包含刚刚失去连接的信道中所有的信道变量的特殊对象——env
添加一个extension来测试这个特性
<extension name="lua-env-hangup-hook-test"> <condition field="destination_number" expression="^(1234)$"> <action application="answer"/> <action application="set" data="api_hangup_hook=lua hook-test.lua"/> <action application="set" data="my_custom_var=foobar"/> <action application="sleep" data="10000"/> <action application="hangup"/> </condition> </extension> |
-- hook-test.lua -- demonstrates using env to look at channel variables in hangup hook script -- See everything dat = env:serialize() freeswitch.consoleLog("INFO","Here's everything:\n" .. dat .. "\n") -- Grab a specific channel variable dat = env:getHeader("uuid") freeswitch.consoleLog("INFO","Inside hangup hook, uuid is: " .. dat .. "\n") -- Drop some info into a log file... res = os.execute("echo " .. dat .. " >> /tmp/fax.log") res = os.execute("echo YOUR COMMAND HERE >> /tmp/fax.log") -- If you created a custom variable you can get it also... dat = env:getHeader("my_custom_var") freeswitch.consoleLog("INFO","my_custom_var is '" .. dat .. "'\n") |
翻译出处:https://freeswitch.org/confluence/display/FREESWITCH/mod_lua
注:译者翻译能力有限,欢迎指明
相关文章推荐
- Android Manifest 用法
- 什么是 GraphQL?
- Spark RDD API详解(一) Map和Reduce
- Spring Boot 开发微服务
- lwn拾遗:[sn3218 led drivers]-api解释-1
- 页面元素查找之Selectors API
- Linux C函数参考手册(PDF版)
- 一个小型js框架myJSFrame附API使用帮助
- 详解Lua中的表的概念及其相关操作方法
- C# partial关键字说明
- Lua编程示例(二):面向对象、metatable对表进行扩展
- 详细分析交换机、路由器、集线器的区别和联系
- PowerShell打开或关闭光驱
- 把Lua编译进nginx步骤方法
- 批处理的api WMIC学习体会有感第1/2页
- 批处理 API实现文件下载的代码第1/2页
- Lua脚本自动生成APK包
- Lua中的元表(metatable)、元方法(metamethod)详解
- Lua中的metatable介绍