FreeSWITCH Java ESL Client Demo
1简介
在开启Java ESL Client编程之前,请先阅读《FreeSWITCH权威指南》学习什么是FreeSWITCH Event Socket。
Java连接FreeSWITCH的ESL可以采用两种模式:inbound和outbound。
-
Inbound模式:Java应用作为客户端主动连接到FreeSWITCH的内置TCP服务器上,默认监听8021端口。连接成功后,Java应用可以订阅FreeSWITCH的各种事件通知,并对特定事件进行处理,也可以向FreeSWITCH发送命令。例如,通过Java应用可以获取来电事件,并且可以控制呼叫流程,如发送异步API命令发起呼叫 。
-
Outbound模式:Java应用作为服务器端,FreeSWITCH作为客户端连接到Java应用。这种模式下,需要在FreeSWITCH配置中指定Java应用的IP和端口。当有来电时,FreeSWITCH会连接到Java应用,Java应用可以根据业务需求对通话进行处理,如播放音乐或转接呼叫 。
选择哪种模式取决于具体的业务需求。如果需要监控所有来电情况或实现自助语音服务,inbound模式可能更合适。而如果需要对来电进行人工客服分配,outbound模式可能更简单 。另外,Java ESL客户端库支持这两种模式,并且提供了丰富的API来处理ESL连接和事件 。
在实际开发中,开发者可以根据需要选择适合的连接模式,并利用Java ESL客户端提供的接口来实现与FreeSWITCH的交互。
Java ESL客户端通过与FreeSWITCH的Event Socket Library(ESL)交互,能够实现以下操作:
-
连接管理:建立与FreeSWITCH的连接,并处理连接的生命周期,包括断开和重连。
-
事件订阅:订阅FreeSWITCH产生的各种事件,如呼叫开始、结束、通道变更等。
-
事件处理:接收并处理来自FreeSWITCH的事件通知,允许应用根据事件执行业务逻辑。
-
发送API命令:向FreeSWITCH发送同步或异步API命令来控制呼叫流程,例如发起呼叫、挂断、转接等。
-
执行异步命令:发送异步命令并接收结果,如查询呼叫状态、执行数据库操作等。
-
同步命令执行:发送同步命令并等待其执行结果,适用于需要即时反馈的操作。
-
设置呼叫变量:在呼叫过程中设置或修改呼叫变量,以控制FreeSWITCH的行为。
-
用户和设备管理:通过API命令管理SIP用户、分机、IVR流程等。
-
呼叫录音:控制呼叫录音的开始和停止。
-
呼叫监听和监视:监听特定呼叫的音频流或监视呼叫状态。
-
发送DTMF:向正在通话的通道发送DTMF信号。
-
应用执行:在呼叫中执行特定的FreeSWITCH应用,如播放音乐、发送短信等。
-
错误处理:处理与FreeSWITCH连接或命令执行过程中可能出现的错误。
-
日志记录:记录与FreeSWITCH交互的日志信息,方便问题排查。
-
自定义协议支持:实现自定义的ESL协议命令,以支持FreeSWITCH的高级特性。
-
多线程和并发处理:支持多线程环境下的并发调用和事件处理。
-
资源管理:管理与FreeSWITCH的连接资源,优化连接使用效率。
Java ESL客户端作为一个强大的工具,允许开发者通过编程方式与FreeSWITCH进行交互,实现复杂的呼叫处理和通信应用(fs_cli)。
2实现
2.1maven依赖
<dependency>
<groupId>org.freeswitch.esl.client</groupId>
<artifactId>org.freeswitch.esl.client</artifactId>
<version>0.9.2</version>
</dependency>
2.2代码
package org.example;import org.freeswitch.esl.client.IEslEventListener;
import org.freeswitch.esl.client.inbound.Client;
import org.freeswitch.esl.client.transport.event.EslEvent;/*** @author yrz* @create 2024/08/20*/
public class ESLClient {private static final String HOST = "10.192.33.34";private static final int PORT = 8021;private static final String PASSWORD = "ClueCon";private static String job_UUID = null;public static void main(String[] args) {InBound();}private static void InBound() {final Client client = new Client();try {client.connect(HOST, PORT, PASSWORD, 20);System.out.println("连接成功");} catch (Exception e) {System.out.println("连接失败");}client.addEventListener(new IEslEventListener() {@Overridepublic void eventReceived(EslEvent event) {if (event.getEventName().equals("CHANNEL_ANSWER")) {System.out.println("通道应答");} else if (event.getEventName().equals("HEARTBEAT")) {System.out.println("收到心跳 --> " + event.getEventBodyLines());job_UUID = client.sendAsyncApiCommand("status", null);System.out.println("Job_UUID --> " + job_UUID);} else if (event.getEventName().equals("CHANNEL_DESTROY")) {System.out.println("通道销毁");} else if (event.getEventName().equals("CHANNEL_HANGUP_COMPLETE")) {//挂断System.out.println("通道挂断完成");} else if (event.getEventName().equals("CHANNEL_CREATE")) {System.out.println("通道创建");}}@Overridepublic void backgroundJobResultReceived(EslEvent event) {String uuid = event.getEventHeaders().get("Job-UUID");if (job_UUID.equals(uuid)) {for (String s : event.getEventBodyLines()) {System.out.println(s);}}}});client.setEventSubscriptions("plain", "all");}
}
/*
播打电话
String originate = client.sendAsyncApiCommand("originate", CallEnum.CALL_BRIDGE);
类型
//相当于1001给1002打电话 {origination_caller_id_number=1001}可以设置1001方显示名字(默认是0000000)
public static final String CALL_BRIDGE = "{origination_caller_id_number=1002}user/1001 &bridge(user/1002)";
// 给1001打电话,channel启动echo app(类似汤姆猫) 并修改名字和号码
public static final String CALL_CHANNEL_CHANGE_NAME = "{origination_caller_id_name='Zhang San',origination_caller_id_number=1234}user/1001 &echo";
//等价于 user/1001 &echo
public static final String CALL_DIALPLAN_XML = "user/1001 echo inline";
// 给1001通话,channel启动playback app(播放录音)
public static final String CALL_PLAYBACK = "{origination_caller_id_name='Zhang San',origination_caller_id_number=1234}user/1001 &playback(/播放文件路径)";
// 顺振 第一个呼叫失败,呼叫第二个,以此类推
public static final String CALL_PARAMAGNETIC_RESONANCE = "user/1001|user/1002 &echo";
// 同振 同时呼叫 谁先接听谁通话,另一个挂断
public static final String CALL_WITH_VIBRATION = "user/1001,user/1002 &echo";
// 服务器先给1001打,1001接听后进入dialplan,找到1002这个exten,最后执行&echo
public static final String CALL_EXTEN = "user/1001 1002";
// 在1001接听后进入public dialplan查找路由
public static final String CALL_DIALPLAN_CONTEXT = "user/1001 1002 XML public";
// 在呼叫时,在SDP里面向对方提供G729 PCMU编码,但在执行是会缺少PCMU编码 需要转义字符\或者^^: {absolute_codec_string=G729\,PCMU}user/1001 &echo 或者下面的
public static final String CALL_ESCAPE_CODEC = "{absolute_codec_string=G729^^:PCMU}user/1001 &echo";
*/
3问题处理
3.1mod_event_socket.c:2674 IP ::ffff Rejected by acl “loopback.auto”
event socket默认监听地址为127.0.0.1。
在event_socket.conf.xml配置文件中,取消该行注释:
<param name="apply-inbound-acl" value="loopback.auto"/>
在acl.conf.xml中增加:
<list name="loopback.auto" default="allow"> <node type="allow" cidr="0.0.0.0"/>
</list>
/***********************************************/
<list name="loopback.auto" default="allow"> <node type="allow" cidr="0.0.0.0/0"/>
</list>
reloadxml
reloadacl
4参考文档
https://developer.signalwire.com/freeswitch/FreeSWITCH-Explained/Client-and-Developer-Interfaces/Java-ESL/Java-ESL-Client_7144076/
https://github.com/esl-client/esl-client
https://sunxiaodou.com/2017/08/02/java-esl-freeswitch/
https://blog.csdn.net/qq_40170041/article/details/127015890
相关文章:
FreeSWITCH Java ESL Client Demo
1简介 在开启Java ESL Client编程之前,请先阅读《FreeSWITCH权威指南》学习什么是FreeSWITCH Event Socket。 Java连接FreeSWITCH的ESL可以采用两种模式:inbound和outbound。 Inbound模式:Java应用作为客户端主动连接到FreeSWITCH的内置TCP…...
手摸手系列之Linux下根据自己的jdk包构建docker镜像
项目在本地导出PDF文件正常,部署到Linux服务器docker容器中导出就报错,百撕不得姐,经查,docker依赖的openjdk版本是8u112版本,而我本地是8u421版本,那就升级jdk的小版本试试。 在docker的中央仓库[点我直达…...
tomcat相关
一、部署安装tomcat 在10和20上安装tomcat [root10 ~]# dnf install java-1.8.0-openjdk.x86_64 -y #安装java环境 [root10 ~]# tar zxf apache-tomcat-9.0.93.tar.gz -C /usr/local/ #安装并启动tomcat [root10 ~]# ln -s /usr/local/apache-tomcat-9.0.93/ /usr/local/tomcat…...
20240821给飞凌OK3588-C的核心板刷Rockchip原厂的Buildroot并启动
20240821给飞凌OK3588-C的核心板刷Rockchip原厂的Buildroot并启动 2024/8/21 15:22 viewproviewpro-ThinkBook-16-G5-IRH:~/repo_RK3588_Buildroot20240508$ viewproviewpro-ThinkBook-16-G5-IRH:~/repo_RK3588_Buildroot20240508$ ./build.sh lunch 3. rockchip_rk3588_evb7_…...
服务优雅上下线优雅停机
一、目的 服务发生线程锁住,需要下线服务时,保证请求中的接口不受影响,执行完后,再下线服务 二、步骤 *kill -15时执行改钩子函数 优雅停机 1.当线程锁住 2.运维那边监控到,然后进行kill -15 进程ID 3.代码这边监…...
什么是生信分析?深入探讨生物信息学的技术、方法与广泛应用
介绍 生物信息学分析,简称生信分析,是一个结合了生物学、计算机科学、信息学和统计学的多学科领域,旨在处理、分析和解释海量的生物数据。随着现代生物技术的发展,尤其是高通量测序(Next-Generation Sequencing, NGS&…...
JavaScript判断数组是否包含某个值
目录: 1.for循环/while循环2.数组的some方法3.数组的filter方法4.array.indexOf5.array.findIndex6.array.includes7.array.find8.set中的has方法 1.for循环/while循环 for循环: function contains(arr, val) {for (var i 0; i < arr.length; i) {if (arr[i] …...
C# - 如何在Windows系统中通过C#添加新的PATH条目至系统和用户环境变量
编写系统环境变量-->系统变量-->path-->添加新的列 01:直接写 using Microsoft.Win32; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks;namespace updatesystempath01 {class Program{stati…...
Unity | Shader基础知识(第二十二集:两次渲染)
目录 一、前言 二、“渲染两次” 三、本次成品介绍 四、第一次渲染代码 五、第二次渲染代码 六、截止目前的所有代码 七、调整代码 八、总结 一、前言 之前一直讲的shader文件中,都只写了一次CG代码。 为了大家对这部分的整体理解,我们这次渲…...
鸿蒙Harmony实战开发:Arkts构造函数
构造函数 类声明可以包含用于初始化对象状态的构造函数。 构造函数定义如下: constructor ([parameters]) {// ... } typescript 如果未定义构造函数,则会自动创建具有空参数列表的默认构造函数,例如: class Point {x: numbe…...
@vueuse/core使用useColorMode实现主题颜色切换
useColorMode 是一个在前端开发中常用的自定义钩子(Hook),尤其在需要支持深色模式和浅色模式切换的场景下。这个钩子可以根据用户的选择或系统设置动态调整页面样式。 一、安装和引入 npm install vueuse/core # 或者 yarn add vueuse/…...
生信分析入门:从基础知识到实践操作的全方位指南
随着生物学研究的数字化转型,生物信息学(简称生信)分析已经成为现代生命科学研究中的关键工具。对于刚开始接触生信分析的初学者来说,这个领域可能看起来复杂而陌生。然而,通过系统的学习和实践,生信分析可…...
【STM32 FreeRTOS】内存管理
除了FreeRTOS提供的动态内存管理方法,标准的C库也提供了函数malloc()和函数free()来实现动态的申请和释放内存。 为啥不用标准的C库自带的内存管理算法?因为标准C库的动态管理方法有如下缺点: 占用大量的代码空间,不适合用在资源…...
vue3+vite+cesium配置参考
在vite项目中使用Cesium的配置 关键: 资源目录的复制;CESIUM_BASE_URL的正确配置 //vite.config.js // ... // 安装打包复制资源插件,手动复制不需要 // npm i vite-plugin-static-copy import { viteStaticCopy } from vite-plugin-static-c…...
WEB应用服务器TOMCAT
知识点 一 、WEB技术 1、前端三大核心技术 1.1 HTML HTML ( HyperText Markup Language )超文本标记语言,它不同于一般的编程语言。超文本 即超出纯文本的范畴,例如:描述文本颜色、大小、字体等信息,或使…...
maven打包jar后运行提示“没有主清单属性”问题的几种解决方案
常用的几种maven项目打包后,jar运行提示“没有主清单属性”问题的解决方案,大部分都是要修改pom.xml文件,同时有几种自己常用的配置文件,主要供自用,勿喷。 第一种: <build><plugins><plug…...
计算机毕业设计选题推荐-民宿可视化分析-Python爬虫-随机森林算法
✨作者主页:IT毕设梦工厂✨ 个人简介:曾从事计算机专业培训教学,擅长Java、Python、微信小程序、Golang、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。 ☑文末获取源码☑ 精彩专栏推荐⬇⬇⬇ Java项目 Py…...
WKWebView加载项目中网页的资源图片路径异常
问题原因,将含有html的文件通过如下方式引入到工程中: 这种处理方式,当应用程序变以后,引入的文件会被全部放在Resources目录下,而忽略你原本的文件路径信息。因此导致出问题。 解决方案: 采用如下方式引…...
算法全面剖析
算法 查找算法: 顺序查找: 基本思想: 顺序查找也称为线形查找,属于无序查找算法。从数据结构线形表的一端开始,顺序扫描,依次将扫描到的结点关键字与给定值k相比较,若相等则表示查找成功&am…...
tp5php7.4配置sqlserver问题汇总
先修改database.php文件 查看php版本选择sqlserver扩展 通过百度网盘分享的文件:sqlserver 链接:https://pan.baidu.com/s/1zrIV8VWQZM9miLpyH01Aww?pwdxdgx 提取码:xdgx 通过我的分享链接复制自己需要的dll到php的ext下 在php.ini里添加扩…...
深度学习在微纳光子学中的应用
深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向: 逆向设计 通过神经网络快速预测微纳结构的光学响应,替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…...
装饰模式(Decorator Pattern)重构java邮件发奖系统实战
前言 现在我们有个如下的需求,设计一个邮件发奖的小系统, 需求 1.数据验证 → 2. 敏感信息加密 → 3. 日志记录 → 4. 实际发送邮件 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其…...
页面渲染流程与性能优化
页面渲染流程与性能优化详解(完整版) 一、现代浏览器渲染流程(详细说明) 1. 构建DOM树 浏览器接收到HTML文档后,会逐步解析并构建DOM(Document Object Model)树。具体过程如下: (…...
OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别
OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别 直接训练提示词嵌入向量的核心区别 您提到的代码: prompt_embedding = initial_embedding.clone().requires_grad_(True) optimizer = torch.optim.Adam([prompt_embedding...
大学生职业发展与就业创业指导教学评价
这里是引用 作为软工2203/2204班的学生,我们非常感谢您在《大学生职业发展与就业创业指导》课程中的悉心教导。这门课程对我们即将面临实习和就业的工科学生来说至关重要,而您认真负责的教学态度,让课程的每一部分都充满了实用价值。 尤其让我…...
智能分布式爬虫的数据处理流水线优化:基于深度强化学习的数据质量控制
在数字化浪潮席卷全球的今天,数据已成为企业和研究机构的核心资产。智能分布式爬虫作为高效的数据采集工具,在大规模数据获取中发挥着关键作用。然而,传统的数据处理流水线在面对复杂多变的网络环境和海量异构数据时,常出现数据质…...
Java + Spring Boot + Mybatis 实现批量插入
在 Java 中使用 Spring Boot 和 MyBatis 实现批量插入可以通过以下步骤完成。这里提供两种常用方法:使用 MyBatis 的 <foreach> 标签和批处理模式(ExecutorType.BATCH)。 方法一:使用 XML 的 <foreach> 标签ÿ…...
iview框架主题色的应用
1.下载 less要使用3.0.0以下的版本 npm install less2.7.3 npm install less-loader4.0.52./src/config/theme.js文件 module.exports {yellow: {theme-color: #FDCE04},blue: {theme-color: #547CE7} }在sass中使用theme配置的颜色主题,无需引入,直接可…...
群晖NAS如何在虚拟机创建飞牛NAS
套件中心下载安装Virtual Machine Manager 创建虚拟机 配置虚拟机 飞牛官网下载 https://iso.liveupdate.fnnas.com/x86_64/trim/fnos-0.9.2-863.iso 群晖NAS如何在虚拟机创建飞牛NAS - 个人信息分享...
Kubernetes 网络模型深度解析:Pod IP 与 Service 的负载均衡机制,Service到底是什么?
Pod IP 的本质与特性 Pod IP 的定位 纯端点地址:Pod IP 是分配给 Pod 网络命名空间的真实 IP 地址(如 10.244.1.2)无特殊名称:在 Kubernetes 中,它通常被称为 “Pod IP” 或 “容器 IP”生命周期:与 Pod …...
