关于这个功能,esl-client 上给出的源码示例极具误导性,根本跑不起来,见: https://github.com/esl-client/esl-client/blob/master/src/test/java/OutboundTest.java
正确姿势:必须在事件订阅的回调里,才能拿到用户按键值
示例代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 |
package org.freeswitch.esl.client;
import org.freeswitch.esl.client.dptools.Execute;
import org.freeswitch.esl.client.dptools.ExecuteException;
import org.freeswitch.esl.client.internal.Context;
import org.freeswitch.esl.client.outbound.IClientHandler;
import org.freeswitch.esl.client.outbound.IClientHandlerFactory;
import org.freeswitch.esl.client.outbound.SocketClient;
import org.freeswitch.esl.client.transport.event.EslEvent;
import org.freeswitch.esl.client.transport.message.EslHeaders.Name;
import org.freeswitch.esl.client.transport.message.EslMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.net.InetSocketAddress;
import java.util.regex.Pattern;
import static com.google.common.base.Throwables.throwIfUnchecked;
public class OutboundDTMFTest {
private static Logger logger = LoggerFactory.getLogger(OutboundDTMFTest. class );
private static String sb = "/usr/local/freeswitch/sounds/en/us/callie/ivr/8000/" ;
String prompt = sb + "ivr-please_enter_extension_followed_by_pound.wav" ;
String failed = sb + "ivr-that_was_an_invalid_entry.wav" ;
public static void main(String[] args) {
new OutboundDTMFTest();
}
public OutboundDTMFTest() {
try {
//outbound test
final SocketClient outboundServer = new SocketClient(
new InetSocketAddress( "localhost" , 8086 ),
new OutboundHandlerFactory());
outboundServer.startAsync();
} catch (Throwable t) {
throwIfUnchecked(t);
}
}
public class OutboundHandlerFactory implements IClientHandlerFactory {
@Override
public IClientHandler createClientHandler() {
//just for sample , recommend use singleton pattern, to avoid new too many instance
return new OutboundHandler();
}
}
public class OutboundHandler implements IClientHandler {
StringBuffer buffer = new StringBuffer( 10 );
String pattern1 = "^\\d+" ;
String pattern2 = "^\\d+#$" ;
@Override
public void onConnect(Context context, EslEvent eslEvent) {
try {
Execute exe = new Execute(context, "" );
//订阅DTMF事件
EslMessage eslMessage = context.sendCommand( "event plain DTMF" );
if (eslMessage.getHeaderValue(Name.REPLY_TEXT).startsWith( "+OK" )) {
logger.info( "subscribe event success!" );
}
exe.answer();
int timeOutSeconds = 30 ;
//放音采集
exe.playAndGetDigits( 1 ,
1 , 10 , timeOutSeconds * 1000 , "#" , prompt,
failed, pattern1, timeOutSeconds * 1000 );
//等待用户输入按键
long start = System.currentTimeMillis();
while ( true ) {
if (System.currentTimeMillis() - start > timeOutSeconds * 1000 ) {
break ;
}
if (buffer.length() > 0 && Pattern.matches(pattern2, buffer.toString())) {
break ;
}
Thread.sleep( 50 );
}
System.out.println( "you pressed:" + buffer.toString());
} catch (ExecuteException | InterruptedException e) {
logger.error( "Could not prompt for digits" , e);
} finally {
context.closeChannel();
}
}
@Override
public void onEslEvent(Context ctx, EslEvent event) {
// System.out.println(event.getEventName());
if (event.getEventName().equalsIgnoreCase( "DTMF" )) {
String key = event.getEventHeaders().get( "DTMF-Digit" );
if ( "#" .equalsIgnoreCase(key)) {
//检查是否输入正确(如果错误,请将之前输入的清空掉)
if (!Pattern.matches(pattern1, buffer.toString())) {
buffer.setLength( 0 );
return ;
}
}
buffer.append(key);
}
}
}
}
|
解释一下:
1. 首先要订阅DTMF事件,只有在事件回调里,才能拿到用户按键信息
2. playAndGetDigits 在outbound async full异步模式下,这个方法的返回值,其实没啥用,永远都是__undef__,所以要在后面循环检测结果,还要考虑用户一直不按键的情况,要有超时保底
3. 事件回调onEslEvent与用户进线onConnect是在2个不同的方法中,但是都是在同一个线程里的,所以为方便起见,用了一个线程安全的StringBuffer用来保存按键信息
4. 事件回调中,要考虑用户按错键的情况,比如提示用户按数字键,然后用户输入了字母或星号之类的,遇到这种要把之前的输入结果清掉。
标签:outbound,new,client,org,freeswitch,import,esl From: https://www.cnblogs.com/kn-zheng/p/17099407.html