Freeswitch修炼宝典(二)-----freeswitch的ESL开发

本文介绍了Freeswitch的ESL(Event Socket Library)开发,包括内联(Inbound)和外联(Outbond)连接方式。内联是客户端主动连接Freeswitch,而外联则是Freeswitch主动发起连接。文中详细讲解了API的使用,特别是api和bgapi的区别,并通过一个语音通知命令实例解析了如何发起呼叫、设置参数以及执行应用程序。

 一般来说,其他客户端都是通过ESL与fs进行连接的,如: Java是通过JAVA-ESL-CLIENT  朝FS进行连接的,连接方式分为内联:inbond 以及外联outbond 2种方式。

Inbound内联:简单说就是客户端主动通过socket的连接方式向FS进行连接,开启了一个“通道”,通过这个通道客户端不仅可以订阅监听一些时间,也可以通过这个通道进行命令的发送。fs_cli 其实就是一个fs的客户端。

 

Outbond外联:外联是FS主动朝外发送连接请求,每一个通话进入在拨号计划设置后都可以进行外联,这个外连接的存活周期就是这通通话的session存活周期,当然有时候FS状态推送慢,session挂断了,外联通道还没监听到这个事件,但是fs中有预留一个api进行这个的控制:linger,linger可以告诉freeswitch当一个通道挂机时不要关闭socket连接,直到收取相关通道的最后一个事件。这样就可以让我们去处理很多依赖状态的事件,比如状态推送,如果我们不是特别需要的话,就可以不增加这个参数。

 

在外部开发中,如JAVA 使用内联连接上后,都是运用的都是API进行开发,在API开发中,有2种命令发送方式朝FS发送命令。一种是api,一种是bgapi,两种api的区别就是一个是同步发送命令,一个是异步发送命令。使用api发送命令,是一个阻塞的状态,无论在fs_cli 还是在 其他工程中,使用这个命令进行发送,在执行成功前都收不到任何消息,多条命令也会被阻塞(阻塞模式),只会按顺序执行,所以我们再开发以及使用中都使用bgapi。当执行bgapi的时候,后台会产生一个Job-UUID,我们也可以通过订阅BACKGROUND_JOB来获取回调结果。

 

其他语言都是通过这些呼叫命令,来完成对fs中会话的控制以及呼叫的发起,我们这里来一个比较简单的语音通知的命令进行拆分解析一下:

bgapi  originate {origination_caller_id_number=123456,hangup_after_bridge=true,ignore_early_media=true}sofia/gateway/test/1565555555  &playback(cyddsb.wav)

 

这个命令是指定主叫号码123456  通过网关gateway 呼叫手机号:1565555555  ,接通成功后播放cyddsb.wav这个音,然后挂断。

 

拆分解析:

bgapi:这是一个异步命令

originate:表示创建一个session发起一通呼叫

{}:这里这个通话的session选项,几乎这通通话所有的参数都是在这里面完成设置的

origination_caller_id_number:设置通话的主叫号码

hangup_after_bridge:bridge成功后是否挂断不执行后续的拨号计划

ignore_early_media:是否忽略早起媒体。

并且我们可以通过这里直接设置很多的透明参数,比如我想为这通通话加上一个vccid,可以直接在{}里增加{vccid=1007},或者我还想增加一个servicekey,我也可以直接在{}增加{vccid=1007,.servicekey=900002},这样增加透明参数后,我们可以把这些事件以为通道变量的形式去取出,在事件中这些自定义参数,会被加上variable_  的头,即我们取出需要去 variable_vccid  variable_servicekey 这样既可取出对应的1007  900002 这些参数。

sofia/gateway/test/1565555555 :这1传就是使用 test网关去拨打1565555555 这个号码了,但是首先你需要自己配置好这个test的网关,具体的网关如何配置在后面也会详细说明。简单的外呼主要有2种方式。一种是通过配置好的网关进行呼叫,还有一种是可以直接通过prpfile和ip进行呼叫。这里使用的就是第一种方式,还有一种方式可以直接执行:sofia/external/1565555555 @172.16.xx.xx:5060进行呼叫,这里是选定的profile = external,这样就会根据external.xml的profile配置去完成呼叫。

&playback(cyddsb.wav) 这里&表示执行一个app,playback是放音,也可以执行bridge,conference等等 app命令。()里表示执行的data,也就是执行的参数,这里表示播放cyddsb.wav 这个录音,由于我这里将这个音放在了默认路径下,这里也可以填写录音的绝对路径,如:/usr/cyddsb.wav 也可以填写 httpd映射的远程录音服务器,比如 http://media:9999/cyddsb.wav ,这样都是可以的。

<think> 我们正在讨论FreeSWITCH中的Channel-Call-UUID。根据之前的对话历史和提供的引用,我将整理相关信息。 首先,在FreeSWITCH中,每个呼叫都会有一个唯一的Call-UUID(也称为Unique-ID),用于标识整个呼叫。同时,每个通道(Channel)也会有自己的UUID(通常称为Channel-UUID)。但需要注意的是,有时人们也会提到Channel-Call-UUID,实际上它应该是指与通道关联的Call-UUID。 关键点: 1. 每个呼叫(Call)有一个唯一的Call-UUID,该呼叫可能包含多个通道(例如主叫通道和被叫通道)。 2. 在桥接(bridge)操作中,两个通道(坐席和用户)会被关联到同一个Call-UUID下。 根据引用[1]中的内容: - 在外呼场景中,坐席拨打用户时,通过`uuid_bridge`命令将坐席通道和用户通道桥接起来。 - 执行`uuid_bridge`的时机很重要:如果坐席不需要听用户的早媒体(early media),则在收到被叫通道的`CHANNEL_ANSWER`事件时执行;如果需要听早媒体,则在更早的事件(如`CHANNEL_PROGRESS_MEDIA`)时执行。 引用[2]提供了网关状态事件的例子,其中包含了多个UUID字段(如Core-UUID),但这里并没有直接涉及Channel-Call-UUID。 引用[3]提到通过UUID定位session并发送event,说明UUID是定位通道的关键标识。 引用[4]中展示了一些通道变量,其中虽然没有直接出现Channel-Call-UUID,但我们可以推断,在通道变量中,通常使用`uuid`来指代当前通道的UUID,而整个呼叫的标识则可能使用`call_uuid`。 因此,关于Channel-Call-UUID,我们可以理解为: 在FreeSWITCH中: - `Unique-ID`(即通道的UUID)是分配给每个单独通道的唯一标识符。 - 而`Call-UUID`则是指整个呼叫的唯一标识符。在一个呼叫中,可能包含多个通道(例如主叫通道、被叫通道),这些通道的`Call-UUID`是相同的,因为属于同一个呼叫。 但是,在FreeSWITCH的变量中,我们通常可以看到: - `uuid`:当前通道的Unique-ID(即通道UUID) - `call_uuid`:这个变量实际上并不存在。通常,整个呼叫的标识是通过通道的`uuid`来关联的,因为FreeSWITCH中一个呼叫可能由多个通道桥接而成,每个通道都有自己的`uuid`,而桥接后的两个通道会通过同一个呼叫(Call)关联起来,但FreeSWITCH并没有一个名为`call_uuid`的变量。 实际上,FreeSWITCH中有一个核心概念:一个呼叫(Call)由一个或多个通道(Channel)组成。当两个通道桥接在一起时,它们属于同一个呼叫。在事件中,我们可以通过`Core-UUID`(FreeSWITCH实例的唯一标识)和通道的`Unique-ID`来追踪。 那么,Channel-Call-UUID指的是什么呢? - 可能是指通道所属的呼叫的UUID。但是,在FreeSWITCH内部,并没有一个单独的变量来存储这个呼叫级别的UUID。通常,我们通过桥接操作将两个通道关联,这时这两个通道会共享同一个呼叫标识,但实际上,每个通道仍然保留自己的UUID。 然而,在FreeSWITCH的事件中,我们可以通过事件头中的`Caller-Unique-ID`和`Unique-ID`来关联通道。例如,当两个通道桥接时,会生成一个`CHANNEL_BRIDGE`事件,该事件包含两个通道的UUID。 另外,在呼叫建立过程中,主叫通道(A-leg)的UUID会在整个呼叫过程中保持不变,而被叫通道(B-leg)也有自己的UUID。当桥接后,这两个通道属于同一个呼叫,但FreeSWITCH并没有提供一个全局的呼叫UUID。不过,在一些场景下,我们可以将主叫通道的UUID视为整个呼叫的标识(Call-ID),因为它是呼叫的发起方。 总结: 1. **Channel UUID**:每个通道的唯一标识,在通道创建时分配,在通道的整个生命周期中保持不变。可以通过通道变量`uuid`获取。 2. **Call-UUID的概念**:FreeSWITCH并没有一个名为`Call-UUID`的全局变量。通常,在桥接呼叫中,我们使用主叫通道的UUID(即A-leg UUID)来代表整个呼叫,因为它是呼叫的起点。 使用场景: - 通过UUID可以定位到一个通道(session),然后我们可以对这个通道执行操作(如播放声音、挂断等)。 - 在事件监听中,我们可以根据通道UUID来追踪事件(如`CHANNEL_ANSWER`、`CHANNEL_BRIDGE`等)。 例如,根据引用[3]中的配置,我们可以通过Event Socket监听事件,事件中会包含通道的UUID。我们可以使用以下命令通过UUID发送指令: ``` uuid_bridge <uuid1> <uuid2> ``` 这个命令将两个通道桥接在一起(坐席和用户)。 关于Channel-Call-UUID,如果是在事件中,我们可以查看事件的头域: - `Unique-ID`:当前通道的UUID(即通道UUID)。 - 另外,在桥接事件中,会有两个UUID:`Other-Leg-Unique-ID`(另一条腿的UUID)和`Unique-ID`(当前通道的UUID)。 因此,如果我们看到事件中有`Channel-Call-UUID`这个字段,那么它很可能是自定义的,并不是FreeSWITCH标准事件的一部分。在标准事件中,我们使用`Unique-ID`来标识通道,而整个呼叫的关联则通过桥接事件中的两个UUID来体现。 如果在文档或某处看到“Channel-Call-UUID”,需要具体上下文。但在FreeSWITCH核心中,通常只使用`uuid`(通道UUID)和`Core-UUID`(FreeSWITCH实例的UUID)。 最后,关于如何获取和操作: - 在拨号方案中,可以通过`${uuid}`获取当前通道的UUID。 - 在事件监听中,事件头中的`Unique-ID`就是通道UUID。 - 通过ESL(Event Socket Library)可以使用`uuid_xxx`系列API命令操作指定UUID的通道。 例如: - `uuid_bridge <uuid1> <uuid2>`:桥接两个通道。 - `uuid_answer <uuid>`:应答指定通道。 注意:在桥接命令中,执行时机很重要(如引用[1]所述),否则可能会影响媒体交互。 相关问题: 1. 如何通过Channel-Call-UUID(即通道UUID)获取当前通道的状态? 2. 在FreeSWITCH中如何桥接两个不同的通道? 3. 如何监听特定通道的事件? 4. 通道变量中的`uuid`和`call_uuid`是否存在?有什么区别? 我将按照以上思路组织回答。 </think> ### FreeSWITCH Channel-Call-UUID 详解 在 FreeSWITCH 中,**Channel-Call-UUID** 是核心会话标识符,用于精确追踪和管理呼叫生命周期。以下是关键信息: --- #### 一、Channel-Call-UUID 本质 1. **唯一会话标识** - 每个呼叫通道(Channel)创建时自动生成全局唯一 UUID - 格式示例:`971f0c15-1d9b-4dae-8f8c-af39b9a8b1f0` - 作用:在分布式系统中精准定位会话,避免冲突[^3] 2. **与核心组件关系** ```mermaid graph TB A[呼叫请求] --> B{FreeSWITCH核心} B --> C[生成Channel-Call-UUID] C --> D[绑定到SIP事务] C --> E[绑定到媒体流] ``` --- #### 、关键应用场景 1. **会话追踪与调试** - 通过 UUID 过滤日志: ```bash fs_cli -x "/log 6" | grep 971f0c15-1d9b-4dae-8f8c-af39b9a8b1f0 ``` - 查看完整会话轨迹: ```bash uuid_debug_a 971f0c15-1d9b-4dae-8f8c-af39b9a8b1f0 ``` 2. **跨模块操作** - **桥接控制**:精准执行 `uuid_bridge` ```xml <action application="set" data="bridge_target=${uuid_bridge(${uuid}, target_uuid)}"/> ``` 需在 `CHANNEL_ANSWER` 或 `CHANNEL_PROGRESS_MEDIA` 事件触发(早媒体场景)[^1] - **强制挂断**: ```bash uuid_kill 971f0c15-1d9b-4dae-8f8c-af39b9a8b1f0 ``` 3. **事件订阅** 在 `event_socket.conf` 配置监听: ```xml <param name="listen-ip" value="0.0.0.0"/> <param name="listen-port" value="8021"/> ``` 通过 ESL 订阅指定 UUID 事件: ```python socket.send("event json CHANNEL_ANSWER CHANNEL_HANGUP_COMPLETE") ``` --- #### 三、技术特性 1. **生命周期管理** | 阶段 | 事件 | UUID 状态 | |---------------------|-----------------------|-------------------| | 呼叫发起 | CHANNEL_CREATE | 生成 | | 媒体交互中 | CHANNEL_PROGRESS_MEDIA| 活跃[^1] | | 呼叫结束 | CHANNEL_HANGUP_COMPLETE| 保留 300 秒[^4] | 2. **关联变量** - `variable_uuid`:当前通道 UUID - `variable_other_uuid`:桥接对端 UUID - `variable_endpoint_disposition`:呼叫结果(如 `ANSWER`/`CANCEL`)[^4] --- #### 四、调试技巧 1. **定位会话** ```bash uuid_getvar 971f0c15-1d9b-4dae-8f8c-af39b9a8b1f0 sip_call_id ``` 2. **诊断媒体问题** ```bash uuid_audio 971f0c15-1d9b-4dae-8f8c-af39b9a8b1f0 ``` --- ### 总结 - **核心价值**:全局唯一标识符,实现精准会话管理 - **关键操作**:需依托事件机制(如 `CHANNEL_PROGRESS_MEDIA`)执行桥接[^1] - **最佳实践**:通过 ESL 订阅事件 + UUID 过滤实现全链路监控[^3]
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值