通过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中,这样可以减少判断次数

相关推荐
柳杉11 分钟前
建议收藏 | 2026年AI工具封神榜:从Sora到混元3D,生产力彻底爆发
前端·人工智能·后端
仙俊红18 分钟前
spring的IoC(控制反转)面试题
java·后端·spring
小楼v30 分钟前
说说常见的限流算法及如何使用Redisson实现多机限流
java·后端·redisson·限流算法
与遨游于天地43 分钟前
NIO的三个组件解决三个问题
java·后端·nio
czlczl200209251 小时前
Guava Cache 原理与实战
java·后端·spring
Yuer20252 小时前
什么是 Rust 语境下的“量化算子”——一个工程对象的最小定义
开发语言·后端·rust·edca os·可控ai
短剑重铸之日2 小时前
《7天学会Redis》Day 5 - Redis Cluster集群架构
数据库·redis·后端·缓存·架构·cluster
计算机程序设计小李同学2 小时前
基于SSM框架的动画制作及分享网站设计
java·前端·后端·学习·ssm
+VX:Fegn08953 小时前
计算机毕业设计|基于springboot + vue小型房屋租赁系统(源码+数据库+文档)
数据库·vue.js·spring boot·后端·课程设计
Victor3563 小时前
Hibernate(43)Hibernate中的级联删除如何实现?
后端