虽然freeswitch已经内置了一些标识的事件,比如:CHANNEL_CREATE(发起呼叫时触发),CHANNEL_HANGUP_COMPLETE(电话挂断时触发)...,但是有时候我们想根据业务需求,新增一些自定义的事件,比如:客人进线后,如果分配到了一个空闲的客服,希望触发一个特定的事件。
可参考以下代码(注:以下所有代码依赖的esl-client,来自于github上的最新代码)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
@Override
public void onConnect(Context context, EslEvent eslEvent) {
try {
Execute exe = new Execute(context, null );
StringBuilder sbEvent = new StringBuilder();
sbEvent.append( "Event-Name=" ).append( "CUSTOM" ).append( "," );
sbEvent.append( "Event-Subclass=" ).append( "callcenter::info" ).append( "," );
//自定义事件中的变量(根据业务需求,可自行添加,注:系统变量并不能覆盖,比如下面的Caller-ANI)
sbEvent.append( "Caller-ANI=" ).append( "999999" ).append( "," );
//只有业务新增的变量,赋值才有意义
sbEvent.append( "MY-VAR-1=" ).append( "abcdefg" ).append( "," );
//触发自定义事件
exe.event(sbEvent.toString());
//其它处理(这里只是示例调用了echo)
exe.echo();
} catch (ExecuteException e) {
e.printStackTrace();
} finally {
context.closeChannel();
}
}
|
ESL outbound外联模式下,onConnect方法中的上述代码,相当于每次进线,都触发一个自定义事件,然后调用echo,让主叫方听到自己的声音。
测试一下,可以在inbound中监控该事件,主要代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
//inbound test
final Client inboundClient = new Client();
inboundClient.connect( new InetSocketAddress( "localhost" , 8021 ), "ClueCon" , 10 );
inboundClient.setEventSubscriptions(IModEslApi.EventFormat.PLAIN, "ALL" );
inboundClient.addEventListener((ctx, event) ->
{
String eventName = event.getEventName();
if (eventName.equalsIgnoreCase( "CUSTOM" ) || eventName.contains( "HANGUP_COMPLETE" )) {
String ani = event.getEventHeaders().get( "Caller-ANI" );
String myvar = event.getEventHeaders().get( "MY-VAR-1" );
System.out.println( "INBOUND=> eventName: " + event.getEventName() + ", ani = " + ani + ", myvar = " + myvar);
}
}
|
执行结果 :
这里有几个要注意的地方:
1. 系统自带的默认通道变量,比如Caller-ANI,在自定义事件中并不能通过赋值的方式篡改。比如上面的示例中,我们把Caller-ANI想改成999999,但是没未生效。
2. 每一次自定义事件的触发,设置的业务变量(比如:上面的MY-VAR-1),只在本次事件中有效,并不象freeswitch自带的变量,可以一直传递到后面的事件中。
3. 如果需要添加自定义变量,且一直能向下传递到所有事件中,可以用export导出变量
1 |
exe.export( "MY-VAR-2" , "something" , true );
|
而且用export导出的变量,在取值时,要加上variable_前缀,即:
1 |
event.getEventHeaders().get( "variable_MY-VAR-2" );
|
另外还有一个大坑,可能是esl-client代码的问题,在inbound订阅事件时,可以指定订阅指定事件,上面的示例中,我们用的是ALL,即订阅所有事件。
inboundClient.setEventSubscriptions(IModEslApi.EventFormat.PLAIN, "ALL" );
|
根据setEventSubscriptions源码的注释说明,可以用类似 “A B C”的方式,指定订阅事件A, B ,C
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
/**
* Set the current event subscription for this connection to the server. Examples of the events
* argument are:
* <pre>
* ALL
* CHANNEL_CREATE CHANNEL_DESTROY HEARTBEAT
* CUSTOM conference::maintenance
* CHANNEL_CREATE CHANNEL_DESTROY CUSTOM conference::maintenance sofia::register sofia::expire
* </pre>
* Subsequent calls to this method replaces any previous subscriptions that were set.
* </p>
* Note: current implementation can only process 'plain' events.
*
* @param format can be { plain | xml }
* @param events { all | space separated list of events }
* @return a {@link CommandResponse} with the server's response.
*/
@Override
public CommandResponse setEventSubscriptions(EventFormat format, String events) {
checkConnected();
return clientContext.get().setEventSubscriptions(format, events);
}
|
但现实是残酷的,当我们换成后
1 2 |
inboundClient.setEventSubscriptions(IModEslApi.EventFormat.PLAIN, "CHANNEL_CREATE CHANNEL_HANGUP CHANNEL_HANGUP_COMPLETE CHANNEL_DESTROY CUSTOM" );
|
居然发现inbound模式下的CUSTOM事件无法订阅成功(注:解决方法,见评价区1楼ctgu_czy的回复,感谢ctgu_czy)
标签:自定义,CUSTOM,CHANNEL,ESL,event,append,事件 From: https://www.cnblogs.com/kn-zheng/p/17099395.html