FreeSWITCH环境Lua API参考手册

Lua API Reference

关于

本页面提供Lua的FreeSWITCH API文档。

API Sessions

以下的方法可以被应用到已存在的sessions。

session:answer

对一路会话的应答。

session:answer();  

session:answered

检查会话是否已经标记为已应答(在应答呼叫后的任何时间都为true)

session:answered();  

session:bridged

检查当前会话的channel是否已经桥接到另外一个channel上。

if (session:bridged() == true) do  
    -- Do something  
end  

session:check_hangup_hook

session:collectDigits

session:consoleLog

从会话中将某些内容记录到FreeSWITCH记录器中。 参数是日志级别和消息。

session:consoleLog("info",   "lua rocks\n");  
session:consoleLog("notice", "lua rocks\n");  
session:consoleLog("err",    "lua rocks\n");  
session:consoleLog("debug",  "lua rocks\n");  
session:consoleLog("warning","lua rocks\n");  

session:destroy

销毁会话并释放资源。 这是在脚本结束时完成,但如果你的脚本包含无限循环,则可以使用它来终止会话。

session:execute

session:execute(app, data);

local mySound = "/usr/local/freeswitch/sounds/music/16000/partita-no-3-in-e-major-bwv-1006-1-preludio.wav";  
session:execute("playback", mySound); 

注意:在一个execute期间,回调无法执行的。

session:flushDigits

session:flushEvents

session:get_uuid

session:get_uuid()

session:getDigits

Get digits:

  • getdigits has three arguments: max_digits, terminators, timeout
  • max_digits: maximum number of dtmf tones that will be collected
  • terminators: buffer of characters that will terminate the digit collection
  • timeout: timeout in milliseconds allowed for no input or after last digit is pressed and terminator isn't
  • interdigit: if no input is received timeout specified previously will be use, once input is received this becomes the new timeout. (optional default 0)
  • return: buffer containing collected digits
  • the method blocks until one of the exit criteria is met.**
session:consoleLog("info", "Got dtmf: ".. digits .."\n");

session:getState

获取呼叫状态。例如:"CS_EXECUTE"。呼叫状态在"switch_types.h"头文件中描述。

state=session:getState();

session:getVariable

获取系统参数,例如参数${hold_music}

    --[[ events obtained from "switch_channel.c"
     regards Monroy from Mexico
    ]]  
    session:getVariable("context");
    session:getVariable("destination_number");
    session:getVariable("caller_id_name");
    session:getVariable("caller_id_number");
    session:getVariable("network_addr");
    session:getVariable("ani");
    session:getVariable("aniii");
    session:getVariable("rdnis");
    session:getVariable("source");
    session:getVariable("chan_name");
    session:getVariable("uuid");

session:hangup

你可以挂断一个会话,并且提供挂断原因(参照:挂断原因代码表)。

session:hangupCause

您可以找到已应答呼叫(被叫)的挂机原因或主叫发起呼叫未完成的原因。(参照:挂断原因代码表)。

-- Initiate an outbound call
obSession = freeswitch.Session("sofia/192.168.0.4/1002")
 
-- Check to see if the call was answered
if obSession:ready() then
    -- Do something good here
else    -- This means the call was not answered ... Check for the reason
    local obCause = obSession:hangupCause()
    freeswitch.consoleLog("info", "obSession:hangupCause() = " .. obCause )
    if ( obCause == "USER_BUSY" ) then              -- SIP 486
       -- For BUSY you may reschedule the call for later
    elseif ( obCause == "NO_ANSWER" ) then
       -- Call them back in an hour
    elseif ( obCause == "ORIGINATOR_CANCEL" ) then   -- SIP 487
       -- May need to check for network congestion or problems
    else
       -- Log these issues
    end
end

基于挂断原因的再次呼叫示例。
代码中的是Lua示例,它根据挂断原因重试发起呼叫。 它重试了3次并在两个不同的网关之间交替:

max_retries1 = 3;
retries = 0;
ostr = "";
repeat  
    retries = retries + 1;
    if (retries % 2) then ostr = originate_str1;
    else ostr = originate_str12; end
    freeswitch.consoleLog("notice", "*********** Dialing Leg1: " .. ostr .. " - Try: "..retries.." ***********\n");
    session1 = freeswitch.Session(ostr);
    local hcause = session1:hangupCause();
    freeswitch.consoleLog("notice", "*********** Leg1: " .. hcause .. " - Try: "..retries.." ***********\n");
until not ((hcause == 'NO_ROUTE_DESTINATION' or hcause == 'RECOVERY_ON_TIMER_EXPIRE' or hcause == 'INCOMPATIBLE_DESTINATION' or hcause == 'CALL_REJECTED' or hcause == 'NORMAL_TEMPORARY_FAILURE') and (retries < max_retriesl1))

注意:originate_str1和originate_str12是2个不同网关的拨号字符串。

session:hangupState

session:insertFile

session:insertFile(<orig_file>, <file_to_insert>, <insertion_sample_point>)

将一个文件插入另一个文件。所有三个参数都是必需的。第三个参数是抽样,并且是要插入file_to_insert 的orig_file 中的样本数。生成的文件将以会话的采样率写入,并将替换orig_file。因为位置是在样本中给出的,所以您需要知道文件的采样率,以正确计算文件中X秒的样本数。例如,要将文件插入到采样率为8000Hz的.wav文件中两秒钟,您将使用16000作为insertion_sample_point参数。
请注意,此方法需要具有有效会话对象的活动channel,因为它需要采样率和会话的编解码器信息。
举例:

-- On a ulaw channel, insert bar.wav one second into foo.wav:
session:insertFile("foo.wav", "bar.wav", 8000)

-- Prepend bar.wav to foo.wav:
session:insertFile("foo.wav", "bar.wav", 0)

-- Append bar.wav to foo.wav:
session:insertFile("bar.wav", "foo.wav", 0)

session:mediaReady

session:originate

session:originate已弃用,请用以下结构代替:

new_session = freeswitch.Session("sofia/gateway/gatewayname/18001234567", session);

下面的代码仅用于历史记录; 请不要继续使用它。

-- this usage of originate is deprecated, use freeswitch.Session(dest, session)
new_session = freeswitch.Session();
new_session.originate(session, dest[, timeout]);

dest:拨号计划目的地址。 例如:“sofia/internal/1000@10.0.0.1”或“sofia/gateway/my_sip_provider/my_dest_number”。
注意:session.originate至少需要2个参数。

session:playAndGetDigits

播放文件并收集DTMF数字。 数字与正则表达式匹配。 不匹配的数字或超时可以触发播放包含错误消息的音频文件。 可选参数允许您在失败时转移到扩展名,并将输入的数字存储到通道变量中。

语法
digits = session:playAndGetDigits (
      min_digits, max_digits, max_attempts, timeout, terminators,
      prompt_audio_files, input_error_audio_files,
      digit_regex, variable_name, digit_timeout,
      transfer_on_failure);

参数

参数名 描述
min_digits 所需的数字最少位数。
max_digits 允许的最大位数。
max_attempts 本函数等待数字的次数(即超时次数),在数字未到达前重复播放prompt_audio_file。
timeout 等待数字的时间(以毫秒为单位)。
terminators 包含导致此函数终止的数字列表的字符串。
prompt_audio_file 要播放的初始音频文件。 如果数字在播放过程中到达,则播放停止。 每次超时后都会重播此文件,超时次数最多为max_attempts。
input_error_audio_file 收到与digit_regex不匹配的数字时播放的音频文件。 播放此文件时,将丢弃接收的数字。 如果未使用此功能,请指定空字符串。
digit_regex 用于验证接收数字的正则表达式。
variable_name (可选)用于存储接收数字的通道变量。
digit_timeout (可选)数字间超时(以毫秒为单位)。 提供后,在输入每个数字后重置超时时钟,从而为移动受限的用户提供缓慢输入数字而不会导致超时的能力。 如果未指定,则digit_timeout设置为timeout。
transfer_on_failure (可选)如果发生故障,此功能会将会话转移到拨号方案中的分机。 语法是“extension-name [dialplan-id [context]]”。

争议

  • 当所有超时和重试计数都用尽时,此函数返回空字符串。
  • 当达到允许的最大位数时,即使未输入终结符,该函数也会立即返回。
  • 如果用户忘记按下其中一个终结符,但输入正确,则在下一次超时后返回数字。
  • 必须先处理会话才能处理任何数字。 如果您未接听电话,音频仍会播放,但不会收到任何数字。

示例
此示例使FreeSWITCH播放prompt.wav并侦听2到5位数字,以#键结尾。 如果用户没有输入任何内容(或者除了数字之外的其他内容,如*键),则会播放error.wav,并且该过程会再重复2次。

digits = session:playAndGetDigits(2, 5, 3, 3000, "#", "/prompt.wav", "/error.wav", "\\d+");
session:consoleLog("info", "Got DTMF digits: ".. digits .."\n");

这次,我们只需要一个数字,它必须是1,3或4。如果用户在三次尝试后不符合要求,它们将被转移到“default“的XML拨号计划中的操作员扩展名。
如果用户按下正确的键,则该数字返回给调用者,并且将通道变量“digits_received”设置为相同的值。

digits = session:playAndGetDigits(1, 1, 3, 3000, "", "/menu.wav", "/error.wav", "[134]", "digits_received", 3, "operator XML default");
session:consoleLog("info", "Got DTMF digits: ".. digits .."\n");

提醒:如果需要匹配正则表达式中的*键,则必须引用两次:

digits = session:playAndGetDigits(2, 5, 3, 3000, "#", "/sr8k.wav", "", "\\d+|\\*");

session:preAnswer

预先回答会话。

session:preAnswer();

session:read

播放文件并获取数字。

digits = session:read(5, 10, "/sr8k.wav", 3000, "#");                                                                                                           
session:consoleLog("info", "Got dtmf: ".. digits .."\n");

session:read有5个参数:<min digits> <max digits> <要播放的文件> <inter-digit timeout> <terminators>
以下显示了如何确定如果有终结器的话,按下的是哪个终结器:

session:setVariable("read_terminator_used", "");
digits = session:read(5, 10, "/sr8k.wav", 3000, "*#");
terminator = session:getVariable("read_terminator_used");
session:consoleLog("info", "Got dtmf: " .. digits .. " terminator: " .. terminator .. "\n");

session:ready

  • 检查会话是否仍处于活动状态(在呼叫启动和挂断之间的任何时间都为true)
  • 如果正在转移呼叫,ready将返回false。 最重要的是你应该总是检查会话:在任何循环上准备就绪,并在整个脚本中定期,如果返回false则退出。

有关不是ready的详细信息,请参阅 session:hangupCause。

while (session:ready() == true) do                                                                                                                              
    -- do something here                                                                                                                                              
end

session:recordFile

语法是ends_by_silence = session:recordFile(file_name,max_len_secs,silence_threshold,silence_secs);
silence_secs是在结束录制之前容忍的沉默量。
如果录制由其他内容结束,则ends_by_silence为0,例如输入回调获取dtmf

function onInputCBF(s, _type, obj, arg)
    local k, v = nil, nil
    local _debug = true
    if _debug then
        for k, v in pairs(obj) do
            printSessionFunctions(obj)
            print(string.format('obj k-> %s v->%s\n', tostring(k), tostring(v)))
        end
        if _type == 'table' then
            for k, v in pairs(_type) do
                print(string.format('_type k-> %s v->%s\n', tostring(k), tostring(v)))
            end
        end
        print(string.format('\n(%s == dtmf) and (obj.digit [%s])\n', _type, obj.digit))
    end
    if (_type == "dtmf") then
        return 'break'
    else
        return ''
    end
end
 
recording_dir = '/tmp/'
filename = 'myfile.wav'
recording_filename = string.format('%s%s', recording_dir, filename)
 
if session:ready() then
    session:setInputCallback('onInputCBF', '');
    -- syntax is session:recordFile(file_name, max_len_secs, silence_threshold, silence_secs)
    max_len_secs = 30
    silence_threshold = 30
    silence_secs = 5
    test = session:recordFile(recording_filename, max_len_secs, silence_threshold, silence_secs);
    session:consoleLog("info", "session:recordFile() = " .. test )
end

session:sayPhrase

播放语音短语宏。
session:sayPhrase(macro_name [,macro_data] [,language]);

  • macro_name:(字符串)要说的说话宏的名称。
  • macro_data:(字符串)可选。 要传递给say宏的数据。
  • language:(字符串)可选。 要说宏的语言(即“en”或“fr”)。 默认为“en”。

要捕获事件或DTMF,请将其与session:setInputCallback结合使用。

示例:

function key_press(session, input_type, data, args)
  if input_type == "dtmf" then
    session:consoleLog("info", "Key pressed: " .. data["digit"])
    return "break"
  end
end
if session:ready() then
  session:answer()
  session:execute("sleep", "1000")
  session:setInputCallback("key_press", "")
  session:sayPhrase("voicemail_menu", "1:2:3:#", "en")
end

与setInputCallback一起使用时,返回值和含义如下:

  • true或“true”: 使提示继续说话。
  • 任何其他字符串值都会中断提示。

session:sendEvent

session:setAutoHangup

默认情况下,lua脚本在执行完毕后会挂断电话。 如果你需要在lua脚本执行完之后在拨号方案中运行下一个操作,则需要将setAutoHangup设置为false。 默认值是true。

session:setAutoHangup(false);

session:setHangupHook

在你的lua代码中,你可以使用setHangupHook来定义会话挂断时要调用的函数。

function myHangupHook(s, status, arg)
    freeswitch.consoleLog("NOTICE", "myHangupHook: " .. status .. "\n")
    -- close db_conn and terminate
    db_conn:close()
    error()
end
 
blah="w00t";
session:setHangupHook("myHangupHook", "blah")

退出脚本的其他可能性(并抛出错误)

return "exit";

或者

return "die";

或者

s:destroy("error message");

session:setInputCallback

function my_cb(s, type, obj, arg)
   if (arg) then
      io.write("type: " .. type .. "\n" .. "arg: " .. arg .. "\n");
   else
      io.write("type: " .. type .. "\n");
   end
   if (type == "dtmf") then
      io.write("digit: [" .. obj['digit'] .. "]\nduration: [" .. obj['duration'] .. "]\n");
   else
      io.write(obj:serialize("xml"));
      e = freeswitch.Event("message");
      e:add_body("you said " .. obj:get_body());
      session:sendEvent(e);
   end
end
blah="w00t";
session:answer();
session:setInputCallback("my_cb", "blah");
session:streamFile("/tmp/swimp.raw");

在将文件流式传输到通道之外使用时,返回值“true”或“undefined”被接受为true(继续音频流),其他任何内容都将被评估为false(这将停止流)。

注意:每个返回值都应该是STRING。

返回值 影响(流式传输音频时)
"speed" Unknown
"volume" Unknown
"pause" 停止音频播放,直到获得下一个输入。 获得另一个输入后,它继续播放。
"stop" Unkown
"truncate" Unkown
"restart" Unkown
"seek" Unkown
"true" 等到音频结束。
"false" 立即停止音频。
None/NULL 不要返回None/NULL。 它会造成类型错误问题。 特别是python。

session:setVariable

在会话上设置变量:

session:setVariable("varname", "varval");

session:sleep

session:sleep(3000);

  • 这将允许回调DTMF,而session:execute(“sleep”,“5000”)则不会。

session:speak

session:set_tts_params("flite", "kal");
session:speak("Please say the name of the person you're trying to contact");

session:say

播放预先录制的声音文件,包括数字,日期,货币等内容。请参阅拨号计划工具say中有关于say的app信息。
参数:<lang><say_type><say_method>
示例:

session:say("12345", "en", "number", "pronounced");

session:streamFile

将文件不停歇地流式传输到会话。

session:streamFile("/tmp/blah.wav");

从sample_count开始,将文件无限流式传输到会话中?(原文此处打了问号)

session:streamFile("/tmp/blah.wav", <sample_count>);

session:transfer

转移当前会话。 参数是extensions,dialplan和context。

session:transfer("3000", "XML", "default");

你执行的lua脚本将立即停止,如果您不希望您的呼叫断开连接,请确保你设置session:setAutoHangup(false)。
如果你执行session:execute(“transfer”,“3000 XML default”),则Lua脚本的执行将继续,即使该调用现在大部分都在您的控制范围之外,并且桥接很可能会失败。

session:unsetInputCallback

session:waitForAnswer

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,839评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,543评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,116评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,371评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,384评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,111评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,416评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,053评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,558评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,007评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,117评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,756评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,324评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,315评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,539评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,578评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,877评论 2 345

推荐阅读更多精彩内容