You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Asterisk 11(Elastix 2.5)区分CANCELLED与NOANSWERED呼叫咨询

区分Asterisk CDR中的主叫取消与被叫未接听呼叫

首先明确:Asterisk默认的CDR确实会把主叫主动取消(CANCELLED)和被叫未接听(NOANSWERED)都标记为NoAnswer,但完全可以通过自定义CDR字段结合通道变量来实现区分,你之前尝试的DIALSTATUS思路是对的,问题大概率出在变量捕获的时机或者CDR配置上。

下面是具体的可行方案:

1. 利用DIALSTATUS变量精准标记呼叫状态

DIALSTATUS是Asterisk在Dial动作完成后生成的通道变量,它能准确返回呼叫的最终状态:

  • CANCEL:主叫在被叫接听前主动取消呼叫
  • NOANSWER:被叫超时未接听
  • ANSWER:呼叫正常接通
  • BUSY:被叫占线

你需要在extensions.conf的拨号上下文里,在Dial动作执行完成后,根据DIALSTATUS的值设置自定义CDR字段,示例代码如下:

[your-dial-context]
exten => _X.,1,NoOp(Incoming call from ${CALLERID(num)} to ${EXTEN})
; 执行拨号动作,超时时间设为30秒
exten => _X.,n,Dial(SIP/${EXTEN},30)
; 根据DIALSTATUS设置自定义CDR字段call_disposition
exten => _X.,n,Set(CDR(call_disposition)=${DIALSTATUS})
; 可以把值映射成你想要的命名,比如把CANCEL改成CANCELLED,NOANSWER改成NOANSWERED
exten => _X.,n,GotoIf($["${DIALSTATUS}" = "CANCEL"]?map_cancelled)
exten => _X.,n,GotoIf($["${DIALSTATUS}" = "NOANSWER"]?map_noanswered)
exten => _X.,n,Goto(end)

exten => _X.,n(map_cancelled),Set(CDR(call_disposition)=CANCELLED)
exten => _X.,n,Goto(end)

exten => _X.,n(map_noanswered),Set(CDR(call_disposition)=NOANSWERED)
exten => _X.,n,Goto(end)

exten => _X.,n(end),Hangup()

2. 配置CDR数据库存储自定义字段

接下来需要确保你的CDR配置(比如cdr_adaptive_odbc.conf,对应Elastix常用的ODBC存储方式)能把这个自定义字段写入数据库:

  1. 修改CDR配置文件:找到你的CDR数据库配置段,在table参数里添加call_disposition字段,示例:
[my_cdr]
connection=asteriskcdrdb
table=cdr
columns=calldate,clid,src,dst,dcontext,channel,dstchannel,lastapp,lastdata,duration,billsec,disposition,amaflags,accountcode,uniqueid,userfield,call_disposition
values='${CDR(start)}','${CDR(clid)}','${CDR(src)}','${CDR(dst)}','${CDR(dcontext)}','${CDR(channel)}','${CDR(dstchannel)}','${CDR(lastapp)}','${CDR(lastdata)}','${CDR(duration)}','${CDR(billsec)}','${CDR(disposition)}','${CDR(amaflags)}','${CDR(accountcode)}','${CDR(uniqueid)}','${CDR(userfield)}','${CDR(call_disposition)}'
  1. 更新数据库表结构:在你的CDR数据库(通常是MySQL的asteriskcdrdb库)里,给cdr表新增call_disposition字段:
ALTER TABLE cdr ADD COLUMN call_disposition VARCHAR(20) DEFAULT NULL AFTER userfield;

3. 排查之前DIALSTATUS效果不佳的原因

你之前尝试导入DIALSTATUS失败,可能是以下原因:

  • 时机错误:在Dial动作执行前就设置了CDR变量,此时DIALSTATUS还未生成有效值
  • 字段未映射:CDR配置文件里没有把DIALSTATUS对应的字段加入到数据库写入列表
  • 变量作用域问题:确保在Dial动作所在的上下文里正确捕获变量,避免跨上下文丢失

备选方案:利用HANGUPCAUSE变量补充判断

如果需要更底层的呼叫原因判断,可以结合HANGUPCAUSE变量(对应SIP协议的原因码):

  • 主叫主动取消对应的HANGUPCAUSE通常是487(Request Terminated,更准确)
  • 被叫未接听对应的HANGUPCAUSE通常是19(No Answer)

你可以在Hangup前添加判断:

exten => _X.,n,Set(CDR(hangup_cause)=${HANGUPCAUSE})

内容的提问来源于stack exchange,提问作者T.Sh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 09:25:19