通过Lua脚本多个网关循环外呼

前情提要:

在文章 freeswitch+freeswitch+语音网关拨打电话 中配置了多个网关。

当前的做法:在/usr/local/freeswitch/conf/dialplan/public.xml使用destination_number的尾号去进行匹配<condition field="destination_number" expression="^(\d*[02468])$">

这种做法存在的问题:

符合规则的尾号不能被同时打,因为一个网关只能支持拨打一个电话

解决方案:

在《FreeSWITCH权威指南》一书中,有一个通过Lua脚本多个网关循环外呼的案例

编写lua脚本

在freeswitch/script文件夹下编写auto_retry_gw.lua脚本

lua 复制代码
retries = 0
bridge_hangup_cause = 0
gateways = {
    {
        name = "gw2",                   -- 第一个网关名称
        caller_id_number = "559947",     -- 网关1的主叫号码
        caller_id_name = "559947"        -- 网关1的主叫名称
    },
    {
        name = "gw3",                   -- 第二个网关名称
        caller_id_number = "559948",     -- 网关2的主叫号码
        caller_id_name = "559948"        -- 网关2的主叫名称
    },
    {
        name = "gw4",                   -- 第三个网关名称
        caller_id_number = "559944",     -- 网关3的主叫号码
        caller_id_name = "559944"        -- 网关3的主叫名称
    },
    {
        name = "gw5",                   -- 第四个网关名称
        caller_id_number = "559945",     -- 网关4的主叫号码
        caller_id_name = "559945"        -- 网关4的主叫名称
    },
    {
        name = "gw6",                   -- 第四个网关名称
        caller_id_number = "559946",     -- 网关4的主叫号码
        caller_id_name = "559946"        -- 网关4的主叫名称
    }
    -- ... 可以继续添加更多网关配置
}
-- 呼叫的号码
dest = argv[1]

-- 循环外呼
function call_retry()
    freeswitch.consoleLog("notice", "Calling [" ..dest.. "] FROM lua\n")
    retries = retries + 1
    if not session.ready() then
         return;
    end
    -- 设置主叫号码
    session:setVariable("effective_caller_id_number", gateways[retries].caller_id_number)
    session:setVariable("effective_caller_id_name", gateways[retries].caller_id_name)
    -- 拼接呼叫字符串
    dial_string = "sofia/gateway/" ..gateways[retries].name .. "/" ..dest;
    freeswitch.consoleLog("notice", "Dialing [" ..dial_string.. "]\n");
    session:execute("bridge", dial_string);
    bridge_hangup_cause = session:getVariable("bridge_hangup_cause") or session:getVariable("originate_disposition");
    -- NORMAL_CLEARING 表示除了正常接通,都去循环呼叫
    if(retries < 4 and bridge_hangup_cause ~= "NORMAL_CLEARING") then
        freeswitch.consoleLog("notice", "On calling [" ..dial_string.. "] hangup. Cause:[" ..bridge_hangup_cause.. "].Retry: " ..retries.. "\n");
        session.sleep(1000);
        call_retry();
    else
        freeswitch.consoleLog("notice", "Retry Exceed, Now hangup!\n");
    end
end

session:preAnswer();
-- 有了这两个配置表示一个呼叫失败,继续呼叫下一个
session:setVariable("hangup_after_bridge", "true");
session:setVariable("continue_on_fail", "true");
call_retry();

在fs_cli中测试lua脚本

bash 复制代码
-- 需要使用下面的命令测试
originate {dest=017858661999}loopback/1234 &lua(test.lua)
  • &lua(test.lua 017858661999) 的方式行不通,会接收不到
  • lua test.lua 017858661999 能接收到,但是session会为空
  • 获取dest的方式修改为dest = session:getVariable("dest")

在拨号计划中使用

将/usr/local/freeswitch/conf/dialplan/public.xml中的拨号计划配置修改为如下图:

优化方向

把正在通话的号码加入到内存hash中,这样可以减少判断次数

相关推荐
郑州光合科技余经理5 分钟前
同城电商系统:库存变更怎么同步到订单
java·开发语言·前端·后端·uni-app·php·ai编程
我叫黑大帅18 分钟前
Go日志库工程选型与逃逸分析评测报告
后端·面试·go
IT_陈寒3 小时前
JavaScript闭包的这个坑,我居然今天才爬出来
前端·人工智能·后端
Thneonl3 小时前
消息队列选型决策树:RabbitMQ vs Kafka vs Redis Streams
后端·架构
晚安日记wanna3 小时前
大厂禁 JOIN 的真正原因,拆到第四层才清楚
数据库·后端·面试
dd聊技术3 小时前
LLM 说"你这篇和已有文章 92% 相似",我去查了——它编的
后端
行百里er4 小时前
Redis 持久化——RDB 快照 vs AOF 日志
redis·后端
Ysx5 小时前
踩了 5 次"本地全绿、生产失效"之后,我把交付流程做成了 SOP
后端·程序员
pippocao5 小时前
王者荣耀日志组件BqLog为什么这么快之2——从环形队列到自适应数据总线
后端