星号:如果对端不可访问则转发

星号:如果对端不可访问则转发

我想通过检查特定对等点是否可联系来响应来电,并相应地拨打适当的号码。

目前我这样做了:

exten => 1200,1,Answer()
same => n,Set(reachable=${SHELL(asterisk -rx "sip show peers" | grep ^cedrich-phone.*OK)})
same => n,GotoIf($["${LEN(${reachable})}" = "0"]?extoffline)
same => n,Dial(SIP/cedrich-phone,20)
same => n(extoffline),Dial(SIP/another-phone,20,tr)
same => n,Hangup()

您能告诉我这是否可以接受以及是否可以通过使用最佳实践来改进吗?

答案1

我觉得在来电时执行 asterisk 的 shell 不太对劲。它可能工作正常,但 asterisk 难道不应该已经知道对等方的状态吗?

我使用函数SIPPEER()您可以使用它来请求对等方的状态。如果 的前 3 个字符(OK (44 ms))是,OK那么您可以呼叫对等方。所有其他情况,您都可以转发给另一个对等方。

我做了这样的事情:

exten => _202,1,Log(NOTICE,Dial Status of ${EXTEN}: ${SIPPEER(${EXTEN},status)})
exten => _202,n,GotoIf($["${SIPPEER(${EXTEN},status):0:3}"="OK "]?ok1:forward)
exten => _202,n(ok1),Log(NOTICE,Calling number is available)
exten => _202,n,Dial(SIP/${EXTEN},50,wW)
exten => _202,n,Hangup()
exten => _202,n(forward),Log(NOTICE,Calling forward number)
exten => _202,n,Dial(SIP/201,50,wW)
exten => _202,n,Hangup()

这将在我们前往之前检查状态,如果对方不可用、忙碌或其他情况不正常,则Dial()前往。n(forward)

但是,这样做有一个小问题。当对方拒绝呼叫(或由于其他原因不可用,例如,在我们下次在线检查之前他已上线)时,呼叫将无法接通。

有一个函数DIALSTATUS我们可以在之后使用Dial()它来检查呼叫是否已成功应答。因此,在之后使用它,Dial()如果未应答,也执行转发。(它在我进行的测试中有效。拒绝呼叫会BUSY记录日志并转到下一个对等点)

你会得到类似这样的结果:

exten => _202,1,Log(NOTICE,Dial Status of ${EXTEN}: ${SIPPEER(${EXTEN},status)})
exten => _202,n,GotoIf($["${SIPPEER(${EXTEN},status):0:3}"="OK "]?ok1:forward)
exten => _202,n(ok1),Log(NOTICE,Calling number is available)
exten => _202,n,Dial(SIP/${EXTEN},50,wW)
exten => _202,n,Log(NOTICE,Dial status: ${DIALSTATUS})
exten => _202,n,GotoIf($["${DIALSTATUS)}"="ANSWER"]?ok2:forward)
exten => _202,n(ok2),Log(NOTICE,Successfull call)
exten => _202,n,Hangup()
exten => _202,n(forward),Log(NOTICE,Calling forward number)
exten => _202,n,Dial(SIP/201,50,wW)
exten => _202,n,Hangup()

我没有对最后一点进行DIALSTATUS广泛的测试,所以你应该做一些测试,但在这里它似乎有效。

答案2

正如 @arheops 提到的,如果是 1:1 映射(1 个设备上有 1 个帐户),则可以使用 DEVICE_STATE() 获取特定设备的状态。您可以使用以下内容:

${DEVICE_STATE(${CHANNEL(channeltype)}/${CHANNEL(peername)})}

另一种可能性是,如果您有 1:多映射(一个扩展具有多个设备),则可以使用 EXTENSION_STATE() 函数。

两者都可以有如下提示这里如果您需要让一个用户使用多台设备。这里您可以看到如何进行动态提示

答案3

在拨号计划中使用系统将打开 shell 并为每个呼叫生成 2 个进程。

当然,Asterisk 可以完成你的任务。所有书籍中都有描述。

-= Info about function 'DEVICE_STATE' =- 

[Synopsis]
Get or Set a device state. 

[Description]
The DEVICE_STATE function can be used to retrieve the device state from any
device state provider. For example:
NoOp(SIP/mypeer has state ${DEVICE_STATE(SIP/mypeer)})
NoOp(Conference number 1234 has state ${DEVICE_STATE(MeetMe:1234)})
The DEVICE_STATE function can also be used to set custom device state from
the dialplan.  The 'Custom:' prefix must be used. For example:
Set(DEVICE_STATE(Custom:lamp1)=BUSY)
Set(DEVICE_STATE(Custom:lamp2)=NOT_INUSE)
You can subscribe to the status of a custom device state using a hint in
the dialplan:
exten => 1234,hint,Custom:lamp1
The possible values for both uses of this function are:
UNKNOWN | NOT_INUSE | INUSE | BUSY | INVALID | UNAVAILABLE | RINGING |
RINGINUSE | ONHOLD

相关内容