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存储方式)能把这个自定义字段写入数据库:
- 修改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)}'
- 更新数据库表结构:在你的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
相关产品推荐
相关产品推荐

