关于Asterisk Dial函数多分机呼叫后无法识别接听分机的咨询
刚好我之前处理过类似的多分机呼叫追踪场景,给你几个实用的方案来确定到底是哪个分机接起了呼叫:
方法1:利用Asterisk内置变量直接记录接听分机
Asterisk在执行Dial函数后,会自动设置几个关键变量,其中**ANSWEREDPEER**就是实际接听呼叫的分机标识。你可以把这个变量直接写入CDR记录,后续从MySQL表中就能直接读取。
配置步骤:
- 首先在你的拨号上下文里添加变量写入逻辑,示例代码如下:
exten => _X.,1,NoOp(发起多分机并行呼叫) same => n,Dial(SIP/1001&SIP/1002&SIP/1003,30,tTr) ; 呼叫结束后,将接听分机写入自定义CDR字段 same => n,Set(CDR(answered_ext)=${ANSWEREDPEER}) same => n,Hangup()
- 然后在你的MySQL CDR表中添加一个对应字段,比如:
ALTER TABLE cdr ADD COLUMN answered_ext VARCHAR(50) DEFAULT NULL COMMENT '接听分机号码';
- 最后在Asterisk的
cdr_mysql.conf配置文件中,确保columns配置包含这个新字段,比如:
columns => callerid,src,dst,dcontext,channel,dstchannel,lastapp,lastdata,duration,billsec,disposition,amaflags,accountcode,uniqueid,linkedid,answered_ext
这样每次呼叫结束后,answered_ext字段就会清晰记录下接听的分机号码。
方法2:从现有CDR记录反向推导接听分机
如果你不想修改现有配置,也可以通过现有CDR表的字段反向查询。多分机并行呼叫的所有分支都会共享同一个**linkedid**(整个呼叫链的唯一标识),而只有接听的那条记录的disposition字段会标记为ANSWERED。
你可以用这条SQL查询来找到接听分机:
SELECT dst, channel FROM cdr WHERE linkedid = '目标呼叫的linkedid' AND disposition = 'ANSWERED';
这里的dst字段就是接听的分机号码,channel字段会显示完整的通道信息(比如SIP/1002-000000a1),也能从中提取分机号。
方法3:通过AMI实时监听接听事件
如果需要实时获取接听信息(不需要等CDR写入),可以用Asterisk Manager Interface(AMI)来监听Answer事件。当某个分机接听时,AMI会触发Answer事件,其中的Channel字段包含了接听分机的通道信息。
比如用Python脚本监听的示例(需要pyst库):
from asterisk.ami import AMIClient, SimpleAction # 连接到本地Asterisk AMI client = AMIClient(address='127.0.0.1', port=5038) client.login(username='ami_user', secret='ami_password') # 监听Answer事件 def handle_answer(event, **kwargs): channel = event.get('Channel') if channel and channel.startswith('SIP/'): # 从通道字符串中提取分机号 answered_ext = channel.split('/')[1].split('-')[0] print(f"实时检测到分机 {answered_ext} 接听了呼叫") client.add_event_listener(handle_answer, event='Answer') # 保持监听 client.run_forever()
注意事项:
- 如果呼叫超时无人接听或者被全部拒绝,
ANSWEREDPEER变量会为空,查询时需要做判断; - 确保Asterisk的CDR模块已经正确启用并配置了MySQL连接;
- AMI需要在
manager.conf中配置有权限的用户,才能正常连接监听。
内容的提问来源于stack exchange,提问作者Oğuzhan Çetin
相关产品推荐
相关产品推荐

