FreeSWITCH脚本与自动化:从入门到实战的进阶指南
一、脚本语言选择与核心语法解析
FreeSWITCH支持Lua、Perl、Python等多种脚本语言,其中Lua因其轻量级、高效性和与FreeSWITCH核心的深度集成成为首选。Lua脚本通过mod_lua模块加载,执行环境与FreeSWITCH事件系统无缝对接。
1.1 Lua脚本基础结构
一个典型的Lua脚本包含以下要素:
-- 初始化会话变量session:answer()local caller_id = session:getVariable("caller_id_number")-- 条件分支处理if caller_id == "1001" thensession:streamFile("/var/lib/freeswitch/sounds/vip_welcome.wav")elsesession:streamFile("/var/lib/freeswitch/sounds/standard_welcome.wav")end-- 挂断前执行session:hangup("NORMAL_CLEARING")
关键API方法包括:
session:answer():应答呼叫session:getVariable():获取通道变量session:streamFile():播放音频文件session:execute():执行拨号计划命令
1.2 XML脚本与Dialplan集成
XML脚本通过<action>标签定义处理逻辑,与拨号计划(Dialplan)深度集成:
<extension name="office_hours"><condition field="destination_number" expression="^1000$"><action application="answer"/><action application="lua" data="check_time.lua"/><action application="bridge" data="user/1001@$${domain}"/></condition></extension>
XML脚本的优势在于可视化配置和复杂条件组合,适合构建标准化的IVR流程。
二、自动化场景设计与实现
2.1 呼叫中心自动化
通过脚本实现ACD(自动呼叫分配)逻辑:
-- 技能组路由示例local skills = {["sales"] = {priority=1, agents={"1001","1002"}},["support"] = {priority=2, agents={"1003","1004"}}}function route_call(skill)local group = skills[skill]for _, agent in ipairs(group.agents) doif freeswitch.API():execute("sofia", "contact "..agent.."@"..freeswitch.getGlobalVariable("domain")) ~= "" thensession:execute("bridge", "user/"..agent.."@"..freeswitch.getGlobalVariable("domain"))return trueendendreturn falseend
关键优化点:
- 实时状态检查(
sofia contact) - 多级技能组回退机制
- 负载均衡算法集成
2.2 IVR系统自动化
构建动态IVR菜单系统:
-- 多级菜单实现local menu_tree = {["1"] = {file="/sounds/menu_sales.wav", action="sales_queue"},["2"] = {file="/sounds/menu_support.wav", action="support_queue"},["#"] = {file="/sounds/menu_repeat.wav", action="repeat"}}function play_menu()while true dosession:streamFile("/sounds/main_menu.wav")local digits = session:getDigits(5, "#", 3000)if menu_tree[digits] thenif digits == "#" thencontinueelsesession:streamFile(menu_tree[digits].file)if menu_tree[digits].action == "sales_queue" thensession:execute("enqueue", "sales_queue")breakendendelsesession:streamFile("/sounds/invalid_entry.wav")endendend
高级功能实现:
- TTS动态内容生成
- DTMF超时处理
- 菜单选项动态加载
三、性能优化与调试技巧
3.1 脚本执行效率优化
- 预加载常用资源:
local preloaded_sounds = {welcome = freeswitch.Sound():new("/sounds/welcome.wav"),hold = freeswitch.Sound():new("/sounds/hold_music.wav")}
- 异步操作处理:
-- 使用freeswitch.AsyncAPI进行非阻塞操作local async = freeswitch.AsyncAPI()async:execute("sleep", "5000", function()session:streamFile("/sounds/after_delay.wav")end)
3.2 调试与日志系统
- 日志分级输出:
freeswitch.consoleLog("INFO", "Call from: "..caller_id.."\n")freeswitch.consoleLog("ERR", "Bridge failed: "..tostring(err).."\n")
- 实时变量监控:
# 在FS CLI中执行fs_cli -x "sofia status profile internal reg"fs_cli -x "show channels"
四、实战案例:智能路由系统
4.1 系统架构设计
[SIP Trunk] → [FreeSWITCH] → [Lua Router] → [Agent Groups]│↓[DB Lookup]
4.2 核心代码实现
-- 数据库连接配置local dbh = freeswitch.DBH("mysql", "host=localhost;dbname=callcenter;user=fsuser;password=fspass")function get_agent_by_skill(skill)local stmt = dbh:prepare("SELECT extension FROM agents WHERE skill = ? AND status = 'available' ORDER BY priority LIMIT 1")stmt:execute(skill)local row = stmt:fetch({}, "a")stmt:finalize()return row and row.extension or nilend-- 主处理函数function main(session, args)local number = session:getVariable("destination_number")local skill = determine_skill(number) -- 自定义技能判断逻辑local agent = get_agent_by_skill(skill)if agent thensession:execute("bridge", "user/"..agent.."@"..freeswitch.getGlobalVariable("domain"))elsesession:execute("playback", "/sounds/no_agents.wav")session:hangup("NO_ANSWER")endend
4.3 部署注意事项
- 数据库连接池配置
- 脚本缓存策略(
mod_lua的lua_script_cache参数) - 错误处理机制(重试次数、fallback路由)
五、进阶方向与资源推荐
5.1 高级主题探索
- 事件套接字(Event Socket)编程
- 与Web框架集成(如Flask+FreeSWITCH ESL)
- 机器学习驱动的路由决策
5.2 学习资源
- 官方文档:
mod_lua章节 - 社区项目:SignalWire/FSLua示例库
- 书籍推荐:《FreeSWITCH Cookbook》第5章
通过系统掌握脚本编程与自动化技术,开发者能够构建出高效、灵活的通信解决方案。建议从简单IVR系统入手,逐步扩展到复杂路由场景,最终实现全流程自动化。