package midware.service.init; import com.alibaba.fastjson2.JSON; import lombok.extern.slf4j.Slf4j; import midware.service.eslclient.entity.Agent; import midware.service.eslclient.entity.Channel; import midware.service.eslclient.EslCommon; import midware.service.eslclient.EslEventListener; import midware.service.eslclient.entity.Session; import midware.util.config.EslClientConfig; import midware.util.enums.EslAgentEnum; import midware.util.enums.EslCommandEnum; import midware.util.enums.EslEventEnum; import midware.util.helper.StringHelper; import midware.util.helper.TtsHelper; import org.freeswitch.esl.client.inbound.Client; import org.freeswitch.esl.client.transport.SendMsg; import org.freeswitch.esl.client.transport.message.EslMessage; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Service; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; import java.io.File; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; import java.util.stream.Stream; @Slf4j @Service @Order(1) public class EslClientService { @Autowired private Client client; @Autowired private EslClientConfig config; @PostConstruct public void init() { client.addEventListener(new EslEventListener()); //单独起1个线程,定时检测连接状态 new ScheduledThreadPoolExecutor(1).scheduleAtFixedRate(() -> { if (!client.canSend()) { try { if (EslCommon.agents.size() > 0) { for (Agent a : EslCommon.agents) { logout(a.getAgent(), a.getGroup(),""); a.setAgentState(EslAgentEnum.logout.ordinal()); } EslCommon.agents=new ArrayList<>(); } client.connect(config.getHost(), config.getPort(), config.getPassword(), config.getTimeout()); //移除事件 client.cancelEventSubscriptions(); Thread.sleep(500); //移除事件 client.cancelEventSubscriptions(); //设置监听事件 client.setEventSubscriptions("plain", "all"); Stream.of(EslEventEnum.values()).filter(s -> StringHelper.isEmpty(s.getSubclass())) .map(Enum::name).forEach(s -> client.addEventFilter("Event-Name", s)); Stream.of(EslEventEnum.values()).filter(s -> StringHelper.isNotEmpty(s.getSubclass())) .map(EslEventEnum::getSubclass).forEach(s -> client.addEventFilter("Event-Subclass", s)); //扫描已注册的分机 scanExten(); } catch (Exception e) { log.error("fs reConnect Exception", e); try { client.close(); } catch (Exception e1) { } } } }, 1, 5000, TimeUnit.MILLISECONDS); if (client.canSend()) { //删除所有坐席 delAgentAll(); //扫描已注册的分机 scanExten(); //设置中间件根目录 String path=new File("").getAbsolutePath(); client.sendAsyncApiCommand(EslCommandEnum.global_setvar.name(), "md_base_dir=" +path ); } EslCommon.checkAuth(); } @PreDestroy public void destroy() { if (EslCommon.agents.size() > 0) { for (Agent a : EslCommon.agents) { logout(a.getAgent(), a.getGroup(),""); a.setAgentState(EslAgentEnum.logout.ordinal()); } EslCommon.agents=new ArrayList<>(); } } //删除所有坐席 public void delAgentAll() { try { String command = EslCommandEnum.callcenter_config.name(); //获取坐席组中所有坐席 EslMessage message = client.sendSyncApiCommand(command, "tier list"); if (message != null && message.getBodyLines().size() > 0) { for (String line : message.getBodyLines()) { if (!line.startsWith("queue") && !line.startsWith("+OK")) { String[] lines = line.split("\\|"); client.sendAsyncApiCommand(command, "agent del " + lines[1]); client.sendAsyncApiCommand(command, "tier del " + lines[0] + " " + lines[1]); } } } //获取所有坐席 EslMessage message1 = client.sendSyncApiCommand(command, "agent list"); if (message1 != null && message1.getBodyLines().size() > 0) { for (String line : message1.getBodyLines()) { if (!line.startsWith("name") && !line.startsWith("+OK")) { String[] lines = line.split("\\|"); client.sendAsyncApiCommand(command, "agent del " + lines[0]); } } } } catch (Exception e) { log.error("删除所有坐席失败", e); } } //扫描已注册的分机 public void scanExten() { try { //挂断所有 client.sendSyncApiCommand("hupall", ""); //获取已注册的分机 EslMessage message = client.sendSyncApiCommand("sofia status profile internal reg", ""); if (message != null && message.getBodyLines().size() > 0) { String ip = ""; for (String line : message.getBodyLines()) { if (line.startsWith("Auth-User:")) { String exten = line.substring(10).trim(); Channel chan = EslCommon.getChanByExten(exten); if (chan == null) { chan = new Channel(); chan.setType(1); chan.setNumber(exten); EslCommon.channels.add(chan); } chan.setAnswer(false); chan.setChanId(""); chan.setRecordPath(""); chan.setCallType(0); chan.setSessionId(""); chan.setRecordId(0); chan.setRingTime(null); chan.setSessionSort(0); chan.setIp(ip); } if (line.startsWith("IP:")) { ip = line.substring(3).trim(); } } } } catch (Exception e) { log.error("扫描已注册的分机失败", e); } } //坐席签入 public boolean login(String agent, String ext, String group,String action) { String result = ""; try { String command = EslCommandEnum.callcenter_config.name(); // 添加座席 String arg = " agent add " + agent + " Callback"; result = client.sendAsyncApiCommand(command, arg); // 设置呼叫字符串 arg = " agent set contact " + agent + " [call_timeout=30]user/" + ext; client.sendAsyncApiCommand(command, arg); // 座席登录后默认空闲 arg = " agent set status " + agent + " Available"; client.sendAsyncApiCommand(command, arg); // 座席登录后默认空闲 arg = " agent set state " + agent + " Waiting"; client.sendAsyncApiCommand(command, arg); // 最大未接次数,到达次数后不再转接,0禁用 arg = " agent set max_no_answer " + agent + " 0"; client.sendAsyncApiCommand(command, arg); // 话后处理时间(s) //成功处理一个通话后,多久才会有电话进入的等待时长 arg = " agent set wrap_up_time " + agent + " 20"; client.sendAsyncApiCommand(command, arg); // 挂机间隔时间(s) //来电拒接后多久才会有电话进入的等待时长,0禁用 arg = " agent set reject_delay_time " + agent + " 0"; client.sendAsyncApiCommand(command, arg); // 忙重试间隔时间(s) //来电遇忙后多久才会有电话进入的等待时长 arg = " agent set busy_delay_time " + agent + " 0"; client.sendAsyncApiCommand(command, arg); // 添加梯队到队列等价于坐席组 group = StringHelper.isEmpty(group) ? "ZXZ" : group; arg = " tier add " + group + " " + agent + " 1 1" +"\r\nJob-UUID:" + action + "|"+ System.currentTimeMillis(); client.sendAsyncApiCommand(command, arg); } catch (Exception e) { log.error(agent + "|" + ext + "|" + group + " 签入失败", e); } return !result.equals(""); } //坐席签出 public boolean logout(String agent, String group,String action) { String result = ""; try { String command = EslCommandEnum.callcenter_config.name(); // 删除座席 String arg = " agent del " + agent; result = client.sendAsyncApiCommand(command, arg); // 删除梯队 group = StringHelper.isEmpty(group) ? "ZXZ" : group; arg = " tier del " + group + " " + agent +"\r\nJob-UUID:" + action + "|"+ System.currentTimeMillis(); client.sendAsyncApiCommand(command, arg); } catch (Exception e) { log.error(agent + "|" + group + " 签出失败", e); } return !result.equals(""); } //坐席置忙/置闲 public boolean setWork(String agent, boolean isWork,String action) { String result = ""; try { String command = EslCommandEnum.callcenter_config.name(); String state = isWork ? "'Available'" : "'On Break'"; String arg = " agent set status " + agent + " " + state +"\r\nJob-UUID:" + action + "|"+ System.currentTimeMillis(); result = client.sendAsyncApiCommand(command, arg); } catch (Exception e) { String state = isWork ? "置闲" : "置忙"; log.error(agent + "|" + isWork + " " + state + "失败", e); } return !result.equals(""); } //删除 public boolean kill(String chanId,String action) { String result = ""; try { result = client.sendAsyncApiCommand(EslCommandEnum.uuid_kill.name(), chanId + "\r\nJob-UUID: " + action + "|" + System.currentTimeMillis()); } catch (Exception e) { log.error(chanId + " 删除失败", e); } return !result.equals(""); } //app挂断 public boolean killApp(String chanId) { String result = ""; try { String command = EslCommandEnum.uuid_broadcast.name(); String arg = chanId + " hangup::NORMAL_CLEARING" ; result = client.sendAsyncApiCommand(command, arg); } catch (Exception e) { log.error( chanId + " app挂断失败", e); } return !result.equals(""); } //分机呼叫 public boolean extenCall(String callerNum, String calleeNum,String action) { String result = ""; try { String fix = action.substring(action.lastIndexOf("|") + 1); String command = EslCommandEnum.originate.name(); // String arg = " {instant_ringback=true,origination_caller_id_number=" + callerNum // + ",call_called=" + calleeNum.substring(fix.length()) + ",record_concat_video=true" // + ",transfer_ringback=local_stream://moh,ignore_early_media=true" // + "}user/" + callerNum + " &bridge(" + getCallString(calleeNum) + ")" // + "\r\nJob-UUID: " + action + "|" + System.currentTimeMillis(); String arg = " {origination_caller_id_number=" + callerNum + ",call_called=" + calleeNum.substring(fix.length()) + ",record_concat_video=true,transfer_ringback=local_stream://moh,ringback=${us-ring}" + "}user/" + callerNum + " &bridge(" + getCallString(calleeNum) + ")" + "\r\nJob-UUID: " + action + "|" + System.currentTimeMillis(); result = client.sendAsyncApiCommand(command, arg); } catch (Exception e) { log.error(callerNum + "|" + calleeNum + " 分机呼叫失败", e); } return !result.equals(""); } //呼叫2个号码并桥接 public boolean bridgeNum(String callerNum, String calleeNum,String action) { String result = ""; try { String command = EslCommandEnum.originate.name(); String arg = " {origination_caller_id_number=" + callerNum + ",call_called=" + calleeNum + ",call_type=2}" + getCallString(callerNum) + " &bridge(" + getCallString(calleeNum) + ")" + "\r\nJob-UUID: " + action + "|" + System.currentTimeMillis(); result = client.sendAsyncApiCommand(command, arg); } catch (Exception e) { log.error(callerNum + "|" + calleeNum + " 呼叫号码并桥接失败", e); } return !result.equals(""); } //协商呼叫 public boolean consult(String chanId, String callerNum,String calleeNum,String action) { String result = ""; try { String fix = action.substring(action.lastIndexOf("|")+1); String command = EslCommandEnum.uuid_broadcast.name(); String arg = chanId + " att_xfer::{origination_caller_id_number=" + callerNum+",record_concat_video=true" + ",call_called=" + calleeNum.substring(fix.length()) + "}" + getCallString(calleeNum) + "\r\nJob-UUID: " + action + "|" + System.currentTimeMillis(); result = client.sendAsyncApiCommand(command, arg); } catch (Exception e) { log.error(chanId + "|" + calleeNum + " 协商呼叫失败", e); } return !result.equals(""); } //强插 public boolean insert(String callerNum,String calleeNum, String sessionId,String action) { String result = ""; try { String command = EslCommandEnum.originate.name(); String arg = " {origination_caller_id_number=" + callerNum + ",cc_member_session_uuid=" + sessionId + ",call_called=" + calleeNum + "}user/" + callerNum + " &three_way(" + sessionId + ")" + "\r\nJob-UUID: " + action + "|" + System.currentTimeMillis(); result = client.sendAsyncApiCommand(command, arg); } catch (Exception e) { log.error(callerNum + "|" + calleeNum + "|" + sessionId + " 强插失败", e); } return !result.equals(""); } //强截 public boolean intercept(String callerNum,String calleeNum, String chanId,String sessionId,String action) { String result = ""; try { Session session = EslCommon.getSessionById(sessionId); String command = EslCommandEnum.originate.name(); String arg = " {origination_caller_id_number=" + callerNum + ",cc_member_session_uuid=" + sessionId + ",call_called=" + calleeNum + "}user/" + callerNum + " &intercept(" + chanId + ")" + "\r\nJob-UUID: " + action + "|" + System.currentTimeMillis(); result = client.sendAsyncApiCommand(command, arg); } catch (Exception e) { log.error(callerNum + "|" + calleeNum + "|" + chanId + "|" + sessionId + " 强截失败", e); } return !result.equals(""); } //监听 public boolean listen(String callerNum,String calleeNum, String sessionId,String action) { String result = ""; try { String command = EslCommandEnum.originate.name(); String arg = " {origination_caller_id_number=" + callerNum+ ",cc_member_session_uuid=" + sessionId + ",call_called=" + calleeNum+ "}user/" + callerNum + " &eavesdrop(" + sessionId + ")" + "\r\nJob-UUID: " + action + "|" + System.currentTimeMillis(); result = client.sendAsyncApiCommand(command, arg); } catch (Exception e) { log.error(callerNum + "|" + sessionId + " 监听失败", e); } return !result.equals(""); } //播放排队位置 public boolean playPosition(int num, String chanId) { String result = ""; try { String command = EslCommandEnum.uuid_broadcast.name(); //String path = "/home/wav/" + num + ".mp3"; String path = TtsHelper.TextToSpeechPosition("你当前的位置为" + num, num + ""); String arg = chanId + " playback::" + path; result = client.sendAsyncApiCommand(command, arg); } catch (Exception e) { log.error(num + "|" + chanId + " 播放排队位置失败", e); } return !result.equals(""); } //播放坐席工号 public boolean playAgent(String agent, String chanId) { String result = ""; try { // String command = EslCommandEnum.sched_broadcast.name(); // String path = "/home/wav/8001.wav"; // //1秒后播放坐席工号 // String arg = " +1 " + chanId + " playback::" + path + " both"; String command = EslCommandEnum.uuid_broadcast.name(); //String path = "/home/wav/8001.wav"; String at = agent; try { Integer.parseInt(agent); at = agent.replaceAll("(.)", " $1").substring(1); } catch (Exception ex) { } String path = TtsHelper.TextToSpeechAgent("你好," + at + "号话务员为您服务", agent); String arg = chanId + " playback::" + path + " both"; result = client.sendAsyncApiCommand(command, arg); } catch (Exception e) { log.error(chanId + " 播放坐席工号失败", e); } return !result.equals(""); } //播放语音 public boolean playBack(String path, String chanId) { String result = ""; try { String command = EslCommandEnum.uuid_broadcast.name(); //path = "/home/wav/8001.wav"; String arg = chanId + " playback::" + path; result = client.sendAsyncApiCommand(command, arg); } catch (Exception e) { log.error(path + "|" + chanId + " 播放语音失败", e); } return !result.equals(""); } //播放语音并挂断 public boolean playHangup(String path, String chanId) { String result = ""; try { String command = EslCommandEnum.uuid_broadcast.name(); //path = "/home/wav/8001.wav"; String arg = chanId + " playback!::" + path; result = client.sendAsyncApiCommand(command, arg); } catch (Exception e) { log.error(path + "|" + chanId + " 播放语音并挂断失败", e); } return !result.equals(""); } //放音收号 public boolean playAndGetDigits(String path,String var, String chanId) { String result = ""; try { String command = EslCommandEnum.uuid_broadcast.name(); //path = "/home/wav/8001.wav"; String arg = chanId + " 'play_and_get_digits::1 1 2 2000 # " + path + " silence_stream://250 " + var + " \\d+'"; result = client.sendAsyncApiCommand(command, arg); } catch (Exception e) { log.error(path + "|" + var + "|" + chanId + " 放音收号失败", e); } return !result.equals(""); } //放音识别 public boolean playAndDetectSpeech(String path,String var, String chanId) { String result = ""; try { String command = EslCommandEnum.uuid_broadcast.name(); //path = "/home/wav/8001.wav"; String arg = chanId + " 'play_and_detect_speech::" + path + " detect:unimrcp:mrcpv2 " + "{start-input-timers=false,no-input-timeout=5000,define-grammar=false," + var + "=0}hello'"; result = client.sendAsyncApiCommand(command, arg); } catch (Exception e) { log.error(path + "|" + var + "|" + chanId + " 放音识别失败", e); } return !result.equals(""); } //会话加入会议 public boolean talkJoinMeeting(String sessionId) { String result = ""; try { String command = EslCommandEnum.uuid_transfer.name(); //String arg = sessionId + " -both " + sessionId + " xml ExtenMeeting"; String at = "threeway"; Session session = EslCommon.getSessionById(sessionId); if (session != null && session.isVideo()) at = "video-mcu-stereo"; String arg = sessionId + " -both 'set:hangup_after_bridge=false,set:record_concat_video=true," + "conference:" + sessionId + "@" + at + "' inline"; result = client.sendAsyncApiCommand(command, arg); if (!result.equals("") && session != null) session.setMeeting(true); } catch (Exception e) { log.error(sessionId + " 会话加入会议失败", e); } return !result.equals(""); } //呼叫号码加入会议 public boolean callJoinMeeting(String callerNum, String calleeNum, String meetingId,String action) { String result = ""; try { String fix = action.substring(action.lastIndexOf("|") + 1); String command = EslCommandEnum.originate.name(); String at = "threeway", argstr = ""; Session session = EslCommon.getSessionById(meetingId); if (session != null && session.isVideo()) { at = "video-mcu-stereo"; String parentPath = "files/video/meeting/" + new SimpleDateFormat("yyyyMMdd").format(new Date()); String path = new File(parentPath).getAbsolutePath() + "/" + meetingId + ".mp4"; session.setVideoPath(parentPath + "/" + meetingId + ".mp4"); argstr = ",record_concat_video=true,conference_auto_record=" + path; } String arg = " {origination_caller_id_number=" + callerNum + ",cc_member_session_uuid=" + meetingId + ",call_called=" + calleeNum.substring(fix.length()) + ",transfer_ringback=local_stream://moh,ringback=${us-ring}" + argstr + "}" + getCallString(calleeNum) // + " " + meetingId + " xml ExtenMeeting"; + " &conference(" + meetingId + "@" + at + ")" + "\r\nJob-UUID: " + action + "|" + System.currentTimeMillis(); result = client.sendAsyncApiCommand(command, arg); } catch (Exception e) { log.error(callerNum + "|" + calleeNum + "|" + meetingId + " 呼叫加入会议失败", e); } return !result.equals(""); } //开启/关闭静音 public boolean setMute(String chanId, boolean isMute,String action) { String result = ""; try { String command = EslCommandEnum.uuid_audio.name(); String arg = chanId + (isMute ? " start" : " stop") + " write mute -4" +"\r\nJob-UUID: " + action + "|" + System.currentTimeMillis(); result = client.sendAsyncApiCommand(command, arg); } catch (Exception e) { String state = isMute ? "开启" : "关闭"; log.error(chanId + " " + state + "静音失败", e); } return !result.equals(""); } //开启/关闭保持 public boolean setHold(String chanId, boolean isHold,String action) { String result = ""; try { String command = EslCommandEnum.uuid_hold.name(); String arg = (isHold ? " " : " off") + " " + chanId + "\r\nJob-UUID: " + action + "|" + System.currentTimeMillis(); result = client.sendAsyncApiCommand(command, arg); } catch (Exception e) { String state = isHold ? "开启" : "关闭"; log.error(chanId + " " + state + "保持失败", e); } return !result.equals(""); } //录音 public boolean record(String chanId, String filePath) { String result = ""; try { String command = EslCommandEnum.uuid_record.name(); String arg = chanId + " start " + filePath; result = client.sendAsyncApiCommand(command, arg); } catch (Exception e) { log.error(chanId + "|" + filePath + " 录音失败", e); } return !result.equals(""); } //录音停止 public boolean recordStop(String chanId, String filePath) { String result = ""; try { String command = EslCommandEnum.uuid_record.name(); String arg = chanId + " stop " + filePath; result = client.sendAsyncApiCommand(command, arg); } catch (Exception e) { log.error(chanId + "|" + filePath + " 录音停止失败", e); } return !result.equals(""); } //转满意度 public boolean turnMyd(String chanId,String action) { String result = ""; try { String command = EslCommandEnum.uuid_transfer.name(); //String arg = chanId + " turnmyd xml ForExten"; String arg = chanId + " 'set:hangup_after_bridge=false,ivr:myd' inline" +"\r\nJob-UUID: " + action + "|" + System.currentTimeMillis(); result = client.sendAsyncApiCommand(command, arg); } catch (Exception e) { log.error(chanId + " 转满意度失败", e); } return !result.equals(""); } //转移号码 public boolean transfer(String chanId,String callerNum, String calleeNum,String action) { String result = ""; try { String fix = action.substring(action.lastIndexOf("|") + 1); String command = EslCommandEnum.uuid_transfer.name(); //String arg = chanId + " " + calleeNum + " xml ForExten"; // String arg = chanId + " 'm:^:set:hangup_after_bridge=false^set:record_concat_video=true^" // + "set:instant_ringback=true^set:transfer_ringback=local_stream://moh^" // + "bridge:{ignore_early_media=true,origination_caller_id_number=" + callerNum + ",call_called=" // + calleeNum.substring(fix.length()) + "}" + getCallString(calleeNum) + "' inline" // + "\r\nJob-UUID: " + action + "|" + System.currentTimeMillis(); String arg = chanId + " 'm:^:set:hangup_after_bridge=false^set:record_concat_video=true^" + "set:transfer_ringback=local_stream://moh^set:ringback=${us-ring}^" + "bridge:{origination_caller_id_number=" + callerNum + ",call_called=" + calleeNum.substring(fix.length()) + "}" + getCallString(calleeNum) + "' inline" + "\r\nJob-UUID: " + action + "|" + System.currentTimeMillis(); result = client.sendAsyncApiCommand(command, arg); } catch (Exception e) { log.error(chanId + "|" + calleeNum + " 转移失败", e); } return !result.equals(""); } //发送按键 public boolean sendDtmf(String chanId, String dtmf,String action) { String result = ""; try { String command = EslCommandEnum.uuid_send_dtmf.name(); String arg = chanId + " " + dtmf +"\r\nJob-UUID: " + action + "|" + System.currentTimeMillis(); result = client.sendAsyncApiCommand(command, arg); } catch (Exception e) { log.error(chanId + "|" + dtmf + " 发送按键失败", e); } return !result.equals(""); } //设置会议人员离开是否播放声音 public boolean setConferenceExitSound(String meetingId, boolean isplay) { String result = ""; try { String command = EslCommandEnum.conference.name(); String arg = meetingId + " exit_sound " + (isplay ? "on" : "off"); result = client.sendAsyncApiCommand(command, arg); } catch (Exception e) { log.error(meetingId + "|" + isplay + " 设置会议离开失败", e); } return !result.equals(""); } //设置会议人员是否静音 public boolean setConferenceIsMute(String meetingId, String memberId, boolean isMute,String action) { String result = ""; try { String command = EslCommandEnum.conference.name(); if (isMute) { String arg = meetingId + " deaf " + memberId; client.sendAsyncApiCommand(command, arg); arg = meetingId + " mute " + memberId +"\r\nJob-UUID: " + action + "|" + System.currentTimeMillis(); result = client.sendAsyncApiCommand(command, arg); } else { String arg = meetingId + " undeaf " + memberId; client.sendAsyncApiCommand(command, arg); arg = meetingId + " stop all " + memberId; client.sendAsyncApiCommand(command, arg); arg = meetingId + " unmute " + memberId +"\r\nJob-UUID: " + action + "|" + System.currentTimeMillis(); result = client.sendAsyncApiCommand(command, arg); } } catch (Exception e) { log.error(meetingId + "|" + memberId + "|" + isMute + " 设置会议静音失败", e); } return !result.equals(""); } //自动外呼 public boolean autoCall(String callerNum, String calleeNum,String taskId,String phoneId) { String result = ""; try { String command = EslCommandEnum.originate.name(); String arg = " {origination_caller_id_number=" + callerNum + ",task_id=" + taskId + ",phone_id=" + phoneId + ",call_type=3}" + getCallString(calleeNum) + " &park()"; result = client.sendAsyncApiCommand(command, arg); } catch (Exception e) { log.error(callerNum + "|" + calleeNum + " 自动外呼失败", e); } return !result.equals(""); } //api命令 public boolean apiCommand(String command, String arg) { String result = ""; try { result = client.sendAsyncApiCommand(command, arg); } catch (Exception e) { log.error(command + "|" + arg + " api命令失败", e); } return !result.equals(""); } public boolean appCommand(String chanId,String command, String arg) { try { SendMsg sm=new SendMsg(chanId); sm.addCallCommand("execute"); sm.addExecuteAppName(command); sm.addExecuteAppArg(arg); return client.sendMessage(sm).isOk(); } catch (Exception e) { log.error(command + "|" + arg + " app命令失败", e); } return false; } //呼叫字符串 private String getCallString(String calleeNum){ //呼叫内线分机号码 String callStr = "user/" + calleeNum; //呼叫外线号码 if (!EslCommon.existExten(calleeNum)) { callStr = "sofia/gateway/hykj/" + calleeNum; } return callStr; } }