FreeSwitch LUA API ——Non-Session API

目录浏览:

  • 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()

当从拨号计划(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. 1.在每次遍历时,回调函数将获得一个以表的形式表示的行数据对于每一行的语法为:{ ["column_name_1"]= "value_1", ["column_name_2"] = "value_2" }.
  1. 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("[email protected]",

                 "[email protected]",

                 "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(""[,""]);

 

-- 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/[email protected]");

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)中调用它:

以上命令将信道变量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("FreeSWITCH Command Portal");

stream:write("

FreeSWITCH Command Portal

");

stream:write("

");

stream:write("");

stream:write("



");

 

command = env:getHeader("command");

 

if (command) then

   api = freeswitch.API();

   reply = api:executeString(command);

 

   if (reply) then

      stream:write("
Command Result

" .. reply .. "
\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来测试这个特性

  

    

    

    

    

                      

                              

然后添加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并挂断,你将看到相关信道的所有变量


翻译出处:https://freeswitch.org/confluence/display/FREESWITCH/mod_lua

注:译者翻译能力有限,欢迎指明


你可能感兴趣的:(freeSwitch,LUA)