跳到主要内容

拨号计划配置与呼叫路由

📖 返回主文档

XML 拨号计划配置、呼叫路由逻辑和拨号计划变量的综合指南。

相关文档

核心文档

呼叫处理流程

  • 🔢 号码翻译 - E.164 规范化(发生在拨号计划之前)
  • 👥 Sh 接口 - 为拨号计划变量检索的用户数据
  • 📡 SS7 MAP - 拨号计划变量中的 MSRN/HLR 数据
  • 💳 在线计费 - 呼叫流程中的 OCS 授权

服务实现

  • ⚙️ 补充服务 - 在拨号计划中实现呼叫转移、CLI 阻止
  • 📞 语音信箱 - 拨号计划中的语音信箱路由和存储/检索
  • 🔊 TTS 提示 - 在拨号计划中使用播放提示

监控


拨号计划配置 / 呼叫路由

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 wiki 包含每个拨号计划应用程序的详细文档,包括所有参数和用例。

拨号计划变量

TAS 在 XML 拨号计划逻辑中设置的变量:

常见变量(所有呼叫类型)

初始设置:

  • destination_number - 翻译后的目的号码
  • tas_destination_number - 翻译后的目的号码
  • effective_caller_id_number - 翻译后的源号码

紧急呼叫

  • hangup_case - "none"
  • ims_private_identity - 私有用户身份
  • ims_public_identity - 公共用户身份
  • msisdn - 订阅者号码(去掉 +)
  • imsi - 私有身份中的 IMSI
  • ims_domain - 私有身份中的域

MT 呼叫(移动终止)

  • ims_private_identity - 私有用户身份
  • ims_public_identity - 公共用户身份
  • msisdn - 订阅者号码(去掉 +)
  • imsi - 私有身份中的 IMSI
  • ims_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 - 私有身份中的 IMSI
  • ims_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 函数检查两个条件:

  1. SIP URI 紧急服�� URN:检测 <urn:service:sos> 或任何包含 "service:sos" 的 URI
  2. 目的号码匹配:将 Caller-Destination-Number 与配置的 emergency_call_codes 进行比较

如果 任一条件 为真,则呼叫被分类为紧急。

代码参考: 请参见 lib/dialplan/authorization.ex

处理流程

呼叫流程详细信息:

  1. 呼叫到达 TAS
  2. 授权模块检查目的地与紧急模式的匹配
  3. 如果检测到紧急:
    • 呼叫类型设置为 :emergency
    • 使用 mo_emergency_dialplan.xml 模板
    • 通常绕过 OCS 授权
    • 呼叫路由到 PSAP 网关
  4. 使用 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 列表中。