目录浏览:
freeswitch.API
api = freeswitch.API();
-- get current time in milliseconds
time = api:getTime()
|
当从拨号计划(dialplan)中调用LUA脚本后,将会得到一个session对象。然而LUA脚本也能在命令行界面(CLI)被调用。无论是那种情况下,在LUA中,当创建完一个API对象后,就可以执行API命令了。
api = freeswitch.API();
reply = api:executeString("version");
|
在以上的代码段中,LUA变量将会从FreeSWTICH中接收到版本号。
也可以做一些复杂的操作,例如:
api = freeswitch.API();
sofia = api:executeString("sofia status");
|
LUA变量sofia将包含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
|
- -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中配置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");
|
当使用”SAY”时,需要设置三个额外的变量,否则你将会得到以下的错误:
> [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");
|
根据变量execute_on_answer创建一个新会话:
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")
|
在FreeSWITCH的命令行界面执行lua hello.lua即可返回hello world。
或者在拨号计划(dialplan)中调用它:
<action application="set" data="foo=${lua(hello.lua)}"/>
|
以上命令将信道变量foo设置为hello world
网页交互示例(调用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>
|
然后添加scripts目录下添加hook-test.lua:
-- 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")
|
查看FS控制台,拨打1234并挂断,你将看到相关信道的所有变量