广告 《大道至简,给所有人看的编程课》 🔥

《FreeSWITCH案例大全》

5.4 用lua实现一个专门用来“接听”群呼电话的FreeSWITCH

wandoubaba / 2023-06-01

5.4.1 场景描述

我们在用FreeSWITCH开发电话群呼功能时,少不了需要测试,用什么方法测试呢?准备一批真实的被叫号码肯定是不现实了。其实我们完全可以准备另外一台专门用来“接听”电话的FreeSWITCH,可以把开发机或测试机上的FreeSWITCH发起的外呼全部都送到这台专门用来接听电话的FreeSWITCH上,具体怎么送?比如被叫FreeSWITCH的主机名是fs40吧,那么我们就在主叫FreeSWITCH上做一个名叫“to40“的gateway就好了,用to40网关做群呼测试,那么所有的呼叫就都会送到fs40这个FreeSWITCH上了。

接下来,问题又来了,当被叫发现来电话了之后,可能会接听吧,也有可能会拒接吧,接听后可能会在听几秒后挂断电话吧,那么我们是不是可以在被叫FreeSWITCH上模拟出这种随机性呢?

当然,我们就在被叫FreeSWITCH上用一个lua脚本实现随机接听或拒接、接听随机时长后主动挂断电话的功能。

5.4.2 编写脚本

在FreeSWITCH安装目录的 scripts目录下创建脚本文件,假设文件名为 random_answer.lua,脚本内容:

--[[
    这是一个模拟被叫的脚本
    可按照指定比率接听或拒接电话
    接听电话后可在随机时间后挂断电话
    接听电话后执行echo应用
    接听电话后保存mp3通话录音
]]

-- 随机决定 answer 或 reject
local function random_call()
    -- 随机决定 answer 或 reject
    local random_number = math.random(1, 3) -- 生成 1-3 的随机数
    if random_number ~= 1 then -- 66.7% 的概率 answer
        -- 设置最长时间
        -- 生成 1-25 的随机数作为会话的最长时间
        local session_term = math.random(1, 25)
        -- 延迟 随机 秒钟后挂断通话
        session:execute("sched_hangup", "+" .. session_term)
        -- 设置录音文件名
        local record_time = os.time()
        local record_dir =  os.date("%Y%m%d", record_time)
        local record_filename = os.date("%Y%m%d%H%M%S", record_time).."-"..session:getVariable("caller_id_number").."-"..session:getVariable("destination_number")..".mp3"
        session:execute("record_session", "$${recordings_dir}/"..record_dir.."/"..record_filename)
        -- 接听电话
        session:answer()
        -- 执行echo
        session:execute('echo')
    else -- 33.3% 的概率 reject
        freeswitch.consoleLog("info", "Reject call\n")
        session:execute("respond", "486")
    end
end

-- 执行随机决定
random_call()

5.4.3 做dialplan

如果我们在主叫FreeSWITCH上通过external方式实现的把呼叫全部送到被叫FreeSWITCH上,那么我们就要在被叫FreeSWITCH上做pulbic的拨号计划;而如果我们是让主叫FreeSWITCH做为被叫FreeSWITCH的一个注册分机的话,就要在被叫FreeSWITCH的default中做拨号计划。

这里我们以public为例,在conf/dialplan/public中创建一个名为random_answer.xml的文件,文件内容如下:

<include>
    <extension name="random_answer">
        <!-- 假设约定被叫号码以000开头的都是测试电话 -->
        <condition field="destination_number" expression="^000(.*)$">
            <action application="lua" data="random_answer.lua"/>
        </condition>
    </extension>
</include>

fs_cli中执行reloadxml,使配置生效。

5.4.4 呼叫测试

需要在主叫FreeSWITCH做一个可以送到被叫FreeSWITCH的gateway,在conf/sip_profiles/external中创建名为call_test.xml的文件,内容如下:

<?xml version='1.0' encoding='utf-8'?>
<include>
    <gateway name="to40">
        <param name="username" value="to40" />
        <param name="realm" value="被叫FS的地址" />
        <param name="proxy" value="被叫FS的地址:external端口号" />
        <param name="register" value="false" />
        <param name="expire-seconds" value="60" />
        <param name="retry-seconds" value="60" />
    </gateway>
</include>

在主叫FreeSWITCH的fs_cli中执行sofia profile external rescan使新建的gateway生效。

先用originate命令发一个外呼试一下:

freeswitch@debian> bgapi originate {ignore_early_media=true}sofia/gateway/to40/00088 &playback($${hold_music})

正常情况下我们应该能在被叫FreeSWITCH的日志或控制台中看到来电记录,多外呼几次,我们可以看到,有的电话被接听,有的电话被拒接,被接听的电话都会在持续了一个随机时长后由被叫挂断,说明我们的这个模拟被叫的FreeSWITCH已经做好了。

如果主叫发起呼叫的并发量很大的话,我们就要把被叫FreeSWITCH的允许并发会话数调大,否则就会出现“呼损”的情况,当然,“呼损”现象也是群呼的一种结果,也是需要应对的。



本书版权所有 © 杜金房及各位贡献者 2016-2023,仅供在线阅读,谢绝一切形式转载。 本书还在写作中,持续更新。 如果你也想写上几句,欢迎加入我们。 | 返回首页 |