拨号计划配置与呼叫路由
📖 返回主文档
XML 拨号计划配置、呼叫路由逻辑和拨号计划变量的综合指南。
相关文档
核心文档
呼叫处理流程
- 🔢 号码翻译 - E.164 规范化(发生在拨号计划之前)
- 👥 Sh 接口 - 为拨号计划变量检索的用户数据
- 📡 SS7 MAP - 拨号计划变量中的 MSRN/HLR 数据
- 💳 在线计费 - 呼叫流程中的 OCS 授权
服务实现
监控
拨号计划配置 / 呼叫路由
TAS 使用与标准电信 XML 拨号计划格式兼容的 XML 拨号计划,变量由 TAS 填充。这意味着您可以根据需要定义自己的拨号计划,包含运营商的业务逻辑,但拥有所有必需的数据,例如存储库数据、SS7 路由信息、IMPI / IMPU 身份、拨号计划规范化等。
拨号计划写入 priv/templates,形式如下:
mo_dialplan.xml- 移动发起呼叫拨号计划mo_emergency_dialplan.xml- 移动发起紧急呼叫拨号计划mt_dialplan.xml- 移动终止呼叫拨号计划
您可以从 Web UI 内部查看拨号计划。
在 XML 被解析之前,TAS 设置了各种变量,这些变量在呼叫开始时以其当前值打印到日志中,对于定义您自己的呼叫逻辑非常有帮助。
FreeSWITCH XML 拨号计划基础
OmniTAS 使用与 FreeSWITCH 项目相同的 XML 呼叫路由系统,这允许灵活的呼叫路由以满足您的需求。
本节解释核心概念并提供实际示例。
基本结构
拨号计划由 扩展 组成,包含 条件 和 动作:
<extension name="description-of-what-this-does">
<condition field="${variable}" expression="regex-pattern">
<action application="app_name" data="parameters"/>
<anti-action application="app_name" data="parameters"/>
</condition>
</extension>
扩展 按从上到下的顺序进行评估。当条件匹配时,其动作执行。
条件和正则匹配
条件测试变量与正则表达式。如果正则表达式匹配,则执行动作;如果不匹配,则执行反向动作。
基本精确匹配:
<condition field="${tas_destination_number}" expression="2222">
<action application="log" data="INFO 正在拨打语音信箱接入号码"/>
</condition>
多个号码匹配:
<condition field="${tas_destination_number}" expression="^(2222|3444|3445)$">
<action application="log" data="INFO 正在拨打特殊服务"/>
</condition>
带捕获组的模式匹配:
<condition field="${tas_destination_number}" expression="^1(8[0-9]{9})$">
<!-- 匹配 1 后跟 8 和 9 个数字 -->
<action application="log" data="INFO 匹配免费电话: $1"/>
<action application="bridge" data="sofia/gateway/trunk/${tas_destination_number}"/>
</condition>
前缀匹配:
<condition field="${tas_destination_number}" expression="^00">
<!-- 匹配以 00 开头的任何号码(国际) -->
<action application="log" data="INFO 检测到国际呼叫"/>
</condition>
范围匹配:
<condition field="${msisdn}" expression="^5551241[0-9]{4}$">
<!-- 匹配 55512410000 到 55512419999 -->
<action application="log" data="INFO 订阅者在范围内"/>
</condition>
动作与反向动作
动作 在条件匹配时执行。反向动作 在条件不匹配时执行。
<condition field="${cli_withheld}" expression="true">
<!-- 如果 CLI 被隐藏则执行 -->
<action application="set" data="effective_caller_id_number=anonymous"/>
<action application="set" data="origination_privacy=hide_number"/>
<!-- 如果 CLI 未被隐藏则执行 -->
<anti-action application="log" data="DEBUG CLI 是正常的"/>
<anti-action application="set" data="effective_caller_id_number=${msisdn}"/>
</condition>
continue="true" 属性
默认情况下,当扩展的条件匹配时,拨号计划停止处理进一步的扩展。continue="true" 属性允许处理继续到下一个扩展。
没有 continue(默认行为):
<extension name="First-Check">
<condition field="${tas_destination_number}" expression="^(.*)$">
<action application="log" data="INFO 正在处理呼叫"/>
</condition>
</extension>
<extension name="Never-Reached">
<!-- 这永远不会执行,因为前一个扩展匹配 -->
<condition field="${tas_destination_number}" expression="^(.*)$">
<action application="log" data="INFO 这不会打印"/>
</condition>
</extension>
使用 continue="true":
<extension name="Print-Vars" continue="true">
<condition field="${tas_destination_number}" expression="^(.*)$">
<action application="info" data=""/>
</condition>
</extension>
<extension name="Check-Balance" continue="true">
<condition field="${hangup_case}" expression="OUTGOING_CALL_BARRED">
<action application="log" data="ERROR 余额不足"/>
<action application="hangup" data="${hangup_case}"/>
</condition>
</extension>
<extension name="Route-Call">
<!-- 这个扩展仍然会被评估 -->
<condition field="${tas_destination_number}" expression="^(.*)$">
<action application="bridge" data="sofia/gateway/trunk/${tas_destination_number}"/>
</condition>
</extension>
使用 continue="true" 用于:
- 日志记录/调试扩展
- 设置适用于多种场景的变量
- 不路由呼叫的验证检查
常见应用
呼叫控制
answer - 接听呼叫(发送 200 OK)
<action application="answer" data=""/>
hangup - 以特定原因终止呼叫
<action application="hangup" data="NORMAL_CLEARING"/>
<action application="hangup" data="USER_BUSY"/>
<action application="hangup" data="NO_ANSWER"/>
bridge - 将呼叫连接到另一个目的地
<!-- 桥接到外部网关 -->
<action application="bridge" data="sofia/gateway/trunk/+12125551234"/>
<!-- 桥接到具有编解码器偏���的内部分机 -->
<action application="bridge" data="{absolute_codec_string=AMR-WB,AMR,PCMA}sofia/internal/sip:user@domain.com"/>
<!-- 带超时的桥接 -->
<action application="bridge" data="{originate_timeout=30}sofia/gateway/trunk/${tas_destination_number}"/>
变量和通道数据
set - 设置通道变量
<action application="set" data="my_variable=my_value"/>
<action application="set" data="sip_h_X-Custom-Header=CustomValue"/>
<action application="set" data="effective_caller_id_number=anonymous"/>
unset - 移除通道变量
<action application="unset" data="sip_h_P-Asserted-Identity"/>
export - 设置变量并导出到 B-leg(桥接呼叫)
<action application="export" data="sip_h_X-Account-Code=ABC123"/>
媒体和提示
playback - 播放音频文件
<action application="playback" data="/sounds/en/us/callie/misc/8000/out_of_credit.wav"/>
<action application="playback" data="$${base_dir}/sounds/custom_prompt.wav"/>
sleep - 暂停指定的毫秒数
<action application="sleep" data="1000"/> <!-- 暂停 1 秒 -->
echo - 将音频回显给呼叫者(测试)
<action application="echo" data=""/>
conference - 将呼叫放入会议
<action application="conference" data="room-${destination_number}@wideband"/>
语音信箱
voicemail - 访问语音信箱系统
<!-- 为邮箱留语音信箱 -->
<action application="voicemail" data="default default ${msisdn}"/>
<!-- 使用授权检查语音信箱 -->
<action application="voicemail" data="check auth default default ${msisdn}"/>
日志记录和调试
log - 写入日志文件
<action application="log" data="INFO 正在处理来自 ${msisdn} 的呼叫"/>
<action application="log" data="DEBUG 目的地: ${tas_destination_number}"/>
<action application="log" data="ERROR 呼叫失败,原因: ${hangup_cause}"/>
info - 将所有通道变量转储到日志
<action application="info" data=""/>
其他应用
say - 文本转语音号码读取
<action application="say" data="en number iterated ${tas_destination_number}"/>
send_dtmf - 发送 DTMF 音调
<action application="send_dtmf" data="1234#"/>
实际示例
紧急服务路由:
<extension name="Emergency-911">
<condition field="${tas_destination_number}" expression="^(911|112)$">
<action application="log" data="ALERT 来自 ${msisdn} 的紧急呼叫"/>
<action application="answer" data=""/>
<action application="playback" data="/sounds/emergency_services_transfer.wav"/>
<action application="bridge" data="sofia/gateway/emergency_gw/${tas_destination_number}"/>
</condition>
</extension>
基于余额的条件路由:
<extension name="Check-Credit">
<condition field="${hangup_case}" expression="OUTGOING_CALL_BARRED">
<action application="answer" data=""/>
<action application="playback" data="/sounds/out_of_credit.wav"/>
<action application="hangup" data="CALL_REJECTED"/>
</condition>
</extension>
On-Net 与 Off-Net 路由:
<extension name="Route-Decision">
<condition field="${on_net_status}" expression="true">
<!-- On-net: 通过 TAS 路由 -->
<action application="log" data="INFO 路由到 on-net 订阅者"/>
<action application="bridge" data="sofia/internal/+${tas_destination_number}@10.179.3.60"/>
<anti-action application="log" data="INFO 路由到 off-net"/>
<anti-action application="bridge" data="sofia/gateway/trunk/+${tas_destination_number}"/>
</condition>
</extension>
匿名呼叫者 ID 处理:
<extension name="CLI-Privacy" continue="true">
<condition field="${cli_withheld}" expression="true">
<action application="set" data="effective_caller_id_name=anonymous"/>
<action application="set" data="effective_caller_id_number=anonymous"/>
<action application="set" data="origination_privacy=hide_number"/>
</condition>
</extension>
未接来电时的语音信箱:
<extension name="Try-Bridge-Then-VM">
<condition field="${tas_destination_number}" expression="^(555124115\d{2})$">
<action application="set" data="call_timeout=30"/>
<action application="bridge" data="sofia/internal/${tas_destination_number}@domain.com"/>
<!-- 如果桥接失败,则转到语音信箱 -->
<action application="log" data="INFO 桥接失败,路由到语音信箱"/>
<action application="answer" data=""/>
<action application="voicemail" data="default default ${tas_destination_number}"/>
</condition>
</extension>
号码范围路由:
<extension name="Local-Numbers">
<condition field="${tas_destination_number}" expression="^([2-9]\d{2})$">
<!-- 3 位本地分机 200-999 -->
<action application="log" data="INFO 本地分机: $1"/>
<action application="bridge" data="sofia/internal/$1@pbx.local"/>
</condition>
</extension>
<extension name="National-Numbers">
<condition field="${tas_destination_number}" expression="^555\d{7}$">
<!-- 国家移动号码 -->
<action application="log" data="INFO 国家移动呼叫"/>
<action application="bridge" data="sofia/gateway/national_trunk/${tas_destination_number}"/>
</condition>
</extension>
<extension name="International">
<condition field="${tas_destination_number}" expression="^00\d+$">
<!-- 以 00 开头的国际呼叫 -->
<action application="log" data="INFO 国际呼叫"/>
<action application="bridge" data="sofia/gateway/intl_trunk/${tas_destination_number}"/>
</condition>
</extension>
进一步文档
有关每个应用程序的完整详细信息:
- FreeSWITCH 拨号计划文档: https://freeswitch.org/confluence/display/FREESWITCH/Dialplan
- FreeSWITCH mod_dptools: https://freeswitch.org/confluence/display/FREESWITCH/mod_dptools (完整应用程序参考)
- 正则表达式参考: https://freeswitch.org/confluence/display/FREESWITCH/Regular+Expression
- 通道变量: https://freeswitch.org/confluence/display/FREESWITCH/Channel+Variables
FreeSWITCH wiki 包含每个拨号计划应用程序的详细文档,包括所有参数和用例。
拨号计划变量
TAS 在 XML 拨号计划逻辑中设置的变量:
常见变量(所有呼叫类型)
初始设置:
destination_number- 翻译后的目的号码tas_destination_number- 翻译后的目的号码effective_caller_id_number- 翻译后的源号码
紧急呼叫
hangup_case- "none"ims_private_identity- 私有用户身份ims_public_identity- 公共用户身份msisdn- 订阅者号码(去掉 +)imsi- 私有身份中的 IMSIims_domain- 私有身份中的域
MT 呼叫(移动终止)
ims_private_identity- 私有用户身份ims_public_identity- 公共用户身份msisdn- 订阅者号码(去掉 +)imsi- 私有身份中的 IMSIims_domain- 私有身份中的域call_forward_all_destination- CFA 目的地或 "none"call_forward_not_reachable_destination- CFNRc 目的地scscf_address- S-CSCF 地址或 "none"scscf_domain- S-CSCF 域或 "none"no_reply_timer- 无应答超时hangup_case- "none" 或 "UNALLOCATED_NUMBER"msrn- PRN 中的 MSRN(如果漫游)或 SRI 中的转发号码(如果呼叫转移处于活动状态)tas_destination_number- 路由目的地覆盖(设置为 MSRN 或转发号码)
MO 呼叫(移动发起)
hangup_case- "none"、"OUTGOING_CALL_BARRED" 或 "UNALLOCATED_NUMBER"ims_private_identity- 私有用户身份ims_public_identity- 公共用户身份msisdn- 订阅者号码(去掉 +)imsi- 私有身份中的 IMSIims_domain- 私有身份中的域allocated_time- OCS 分配的时间(如果启用在线计费)cli_withheld- "true" 或 "false" 字符串on_net_status- "true" 或 "false" 字符串(目的地是否在网内)msrn- 漫游订阅者的 MSRN(如果适用)tas_destination_number- MSRN 覆盖(如果漫游)
紧急呼叫
紧急呼叫通过 emergency_call_codes 配置参数控制,并在呼叫授权期间自动检测。
配置
在您的 config/runtime.exs 文件中配置紧急呼叫代码:
config :tas,
emergency_call_codes: ["911", "912", "913", "sos"],
# ... 其他配置
配置详细信息:
emergency_call_codes(必需):表示紧急服务号码的字符串列表- 这些代码在 SIP 紧急 URN(例如
<urn:service:sos>)之外进行检查 - 系统对目的号码执行 精确匹配 比较
- 常见代码包括:"911"(美国)、"112"(欧盟)、"000"(澳大利亚)、"999"(英国)、"sos"
紧急检测的工作原理
Tas.Dialplan.Authorization.is_emergency_call?/2 函数检查两个条件:
- SIP URI 紧急服�� URN:检测
<urn:service:sos>或任何包含 "service:sos" 的 URI - 目的号码匹配:将
Caller-Destination-Number与配置的emergency_call_codes进行比较
如果 任一条件 为真,则呼叫被分类为紧急。
代码参考: 请参见 lib/dialplan/authorization.ex
处理流程
呼叫流程详细信息:
- 呼叫到达 TAS
- 授权模块检查目的地与紧急模式的匹配
- 如果检测到紧急:
- 呼叫类型设置为
:emergency - 使用
mo_emergency_dialplan.xml模板 - 通常绕过 OCS 授权
- 呼叫路由到 PSAP 网关
- 呼叫类型设置为
- 使用
call_type: emergency标签记录指标
拨号计划路由
在 priv/templates/mo_emergency_dialplan.xml 中定义紧急呼叫的路由。该模板确定如何根据您的市场需求将呼叫路由到 PSAP(公共安全应答点)网关或 SIP URI。
示例紧急拨号计划:
<extension name="Emergency-SOS">
<condition field="${destination_number}" expression="^(911|912|913|sos)$">
<action application="log" data="ALERT 来自 ${msisdn} 的紧急呼叫"/>
<action application="answer" data=""/>
<action application="bridge" data="sofia/gateway/psap_gw/${destination_number}"/>
</condition>
</extension>
最佳实践
- 始终在紧急代码列表中包含 "sos" 以兼容 SIP URN
- 包括您管辖区内的所有本地紧急号码(例如,911、112、000、999)
- 定期使用呼叫模拟器测试紧急路由
- 绕过 OCS 以确保紧急呼叫始终连接(通过
skipped_regex配置) - 配置 PSAP 网关 以实现高可用性和冗余
- 监控紧急呼叫指标 以确保系统可靠性
从 On-Net 移动发起呼叫到 On-Net 移动终止订阅者
您可以通过类似以下方式从您的 拨号计划路由到您的 拨号计划:
<action application="bridge" data="{absolute_codec_string=AMR-WB,AMR,PCMA,PCMU,originate_retries=1,originate_timeout=60,sip_invite_call_id=${sip_call_id}}sofia/internal/+${tas_destination_number}@10.179.3.60" />
其中 10.179.3.60 是 TAS IP(它将呼叫路由回 TAS) - 只需确保 TAS IP 在您的 allowed_sbc_source_ips 列表中。