XCC API

XCC事件说明

事件订阅可以直接使用 NATS 提供的 subscribe 功能实现,可以订阅 FreeSWITCH 中原生的事件,如,订阅所有原生事件:cn.xswitch.ctrl.event.>。事件的 Subject 以及所需的事件类型可以在系统的 xcc 配置界面上指定。原生事件以 JSON-RPC 格式发出,可以在各种语言中很简单的解析其中的内容。

原始事件订阅说明

分机注册事件

  • cn.xswitch.ctrl.event.custom.sofia::register 分机注册信息
  • cn.xswitch.ctrl.event.custom.sofia::unregister 分机注销信息

通话事件

系统有来话或去话时,将生成一个新的 Channel,并产生 channel_create 事件,该事件包含 Channel 的 UUID,主叫号码、被叫号码、Channel 的创建时间等信息。

如果通话正常进行,则会产生 channel_progress 事件(如,收到对方的 100 或 180 消息),如果应答前收到 183 消息,则产生 channel_progress_media 事件。

如果通话被应答,则产生 channel_answer 事件。

如果一个 channel 与另一个 channel bridge 成功则产生 channel_bridge 事件。

如果通话结束挂机,则产生 channel_hangup 和 channel_hangup_complete 事件。其中 channel_hangup_complete 事件内容更丰富,带有 variable_duration(通话时长)以及 variable_billsec(计费时长)等信息。

  • cn.xswitch.ctrl.event.channel_create 通话开始事件
  • cn.xswitch.ctrl.event.channel_state 通话状态事件,其中 Answer-State 表示呼叫状态,如 ringing、answered 等
  • cn.xswitch.ctrl.event.channel_answer 通话应答事件
  • cn.xswitch.ctrl.event.channel_bridge 通话桥接事件
  • cn.xswitch.ctrl.event.channel_hangup_complete 通话结束事件
  • cn.xswitch.ctrl.event.record_start 通话录音开始事件
  • cn.xswitch.ctrl.event.record_stop 通话录音结束事件

会议事件

  • cn.xswitch.ctrl.event.custom.conference::maintenance 会议所有事件

事件参数说明

会议事件中 Action 为事件动作名,其中主要事件名解释如下:

  • conference-create 会议开始
  • add-member 成员加入
  • del-member 成员离开
  • mute-member 成员静音
  • unmute-member 成员解除静音
  • deaf-member 成员禁听
  • undeaf-member 成员解除禁听
  • conference-destroy 会议结束
  • start-recording 开始会议录制
  • stop-recording 结束会议录制
  • conference-destroy 会议结束

事件中部分重要参数说明:

  • "Conference-Name": "710894413-gaofei.cn" 会议名(号码)会议的唯一标识
  • "Conference-Size": "1" 会议总人数
  • "Unique-ID": "ee16e182-b298-48f7-8f3e-11c6638c4411" 本次通话 UUID,会话唯一标志
  • "Caller-Direction": "inbound" 呼叫方向,inbound 表示呼入,outbound 呼出
  • "Caller-Caller-ID-Name": "819" 主叫名称
  • "Caller-Caller-ID-Number": "819" 主叫号码
  • "Video": "false", 是否开启视频
  • "Hear": "true", 是否可听状态
  • "See": "true", 是否可看状态
  • "Member-ID": "22", 加入会议后的 ID,成员唯一标识
  • "Action": "add-member" 事件名

成员加入完整事件如下:

{
  "jsonrpc": "2.0",
  "method": "Event.NativeEvent",
  "params": {
    "node_uuid": "6b7532d6-9d2a-4cfe-bf3c-87a353256de0",
    "event": {
      "Event-Name": "CUSTOM",
      "Core-UUID": "6b7532d6-9d2a-4cfe-bf3c-87a353256de0",
      "FreeSWITCH-Hostname": "gao",
      "FreeSWITCH-Switchname": "gao",
      "FreeSWITCH-IPv4": "172.19.0.3",
      "FreeSWITCH-IPv6": "::1",
      "Event-Date-Local": "2022-07-08 09:34:07",
      "Event-Date-GMT": "Fri, 08 Jul 2022 01:34:07 GMT",
      "Event-Date-Timestamp": "1657244047352956",
      "Event-Calling-File": "conference_member.c",
      "Event-Calling-Function": "conference_member_add",
      "Event-Calling-Line-Number": "965",
      "Event-Sequence": "126921",
      "Event-Subclass": "conference::maintenance",
      "Conference-Name": "710894413-gaofei.cn", //会议名(号码)会议的唯一标识
      "Conference-Domain": "gaofei.cn",
      "Conference-Size": "1", //会议总人数
      "Conference-Ghosts": "0",
      "Conference-Profile-Name": "default",
      "Conference-Unique-ID": "3b937b30-2d76-44dc-acf7-61d652eb3a5f",
      "Conference-Rate": "8000",
      "Conference-Interval": "20",
      "Floor": "false",
      "Channel-State": "CS_EXECUTE",
      "Channel-Call-State": "ACTIVE",
      "Channel-State-Number": "4",
      "Channel-Name": "sofia/default/819@gaofei.cn",
      "Unique-ID": "ee16e182-b298-48f7-8f3e-11c6638c4411", // 本次通话 UUID,会话唯一标志
      "Call-Direction": "inbound",
      "Presence-Call-Direction": "inbound",
      "Channel-HIT-Dialplan": "true",
      "Channel-Presence-ID": "819@gaofei.cn",
      "Channel-Call-UUID": "ee16e182-b298-48f7-8f3e-11c6638c4411",
      "Answer-State": "answered",
      "Channel-Read-Codec-Name": "L16",
      "Channel-Read-Codec-Rate": "48000",
      "Channel-Read-Codec-Bit-Rate": "768000",
      "Channel-Write-Codec-Name": "opus",
      "Channel-Write-Codec-Rate": "48000",
      "Channel-Write-Codec-Bit-Rate": "0",
      "Caller-Direction": "inbound", //呼叫方向,inbound 表示呼入,outbound 呼出
      "Caller-Logical-Direction": "inbound",
      "Caller-Username": "819",
      "Caller-Dialplan": "XML",
      "Caller-Caller-ID-Name": "819", //主叫名称
      "Caller-Caller-ID-Number": "819", //主叫号码
      "Caller-Orig-Caller-ID-Name": "819", //原始主叫名称
      "Caller-Orig-Caller-ID-Number": "819", //原始主叫号码
      "Caller-Network-Addr": "112.237.150.183",
      "Caller-ANI": "819",
      "Caller-Destination-Number": "710894413",
      "Caller-Unique-ID": "ee16e182-b298-48f7-8f3e-11c6638c4411",
      "Caller-Source": "mod_sofia",
      "Caller-Context": "context-22",
      "Caller-Channel-Name": "sofia/default/819@gaofei.cn",
      "Caller-Profile-Index": "1",
      "device_id": "819",
      "Caller-Profile-Created-Time": "1657244047307959",
      "Caller-Channel-Created-Time": "1657244047307959",
      "Caller-Channel-Answered-Time": "1657244047345952",
      "Caller-Channel-Progress-Time": "0",
      "Caller-Channel-Progress-Media-Time": "1657244047330954",
      "Caller-Channel-Hangup-Time": "0",
      "Caller-Channel-Transfer-Time": "0",
      "Caller-Channel-Resurrect-Time": "0",
      "Caller-Channel-Bridged-Time": "0",
      "Caller-Channel-Last-Hold": "0",
      "Caller-Channel-Hold-Accum": "0",
      "Caller-Screen-Bit": "true",
      "Caller-Privacy-Hide-Name": "false",
      "Caller-Privacy-Hide-Number": "false",
      "Video": "false", //是否开启视频
      "Hear": "true", // 是否可听状态
      "See": "true", // 是否可看状态
      "Speak": "true",
      "Talking": "false",
      "Mute-Detect": "false",
      "Hold": "false",
      "Member-ID": "22", // 加入会议后的 ID,成员唯一标识
      "Member-Type": "moderator",
      "Member-Ghost": "false",
      "Energy-Level": "0",
      "Current-Energy": "0",
      "Action": "add-member" // 事件名
    }
  }
}

呼叫中心

  • cn.xswitch.ctrl.event.custom.callcenter::info mod_callcenter 队列模块事件

事件参数说明

事件中 CC-Action 表明事件所属的动作,部分说明如下:

  • agent-add:坐席加入队列
  • agent-del:坐席签出队列
  • agent-contact-change:坐席呼叫字符串发生改变
  • agent-status-change:当坐席的逻辑状态 status 改变时候对应的事件
  • agent-state-change:当坐席的电话呼叫有关状态 state 改变的时候对应的事件
  • agent-offering:将坐席分配给队里中的某个来电成员,坐席还没接听时候的事件
  • bridge-agent-start:来电成员连接坐席成功
  • bridge-agent-end:来电成员和坐席连接断开
  • bridge-agent-fail:呼叫坐席失败时产生的事件
  • members-count:有通话(主叫来电者)进入或者离开队列时产生的事件,即:排队数。
  • member-queue-start:有通话(主叫来电者)呼入加入队列事件
  • member-queue-end:有通话(主叫来电者)离开队列事件

坐席状态

一个座席有两个状态标志,分别是 Status 和 States,如下所示:

Status 是一个座席逻辑上的状态,它有以下几种取值:

  • Logged Out:退出服务状态;
  • Available:可用状态,可以接电话;
  • Available (On Demand):一种特殊的可用状态;
  • On Break:座席已登录,但不可以接电话。

States 是跟电话呼叫有关的状态,它有以下几种取值:

  • Idle:空闲;
  • Waiting:等待接受呼叫;
  • Receiving:正在接受呼叫,响铃;
  • In a queue call:当前正在一个队列呼叫中。
  • Reserved:被分配

js 代码示例

const NATS = require('nats')
let nats_url = "nats://xcc-nats:4222"; //这个从系统 xcc 界面里查看 nats-url 的值
console.log("Connecting to " + nats_url)
const nc = NATS.connect(nats_url);
console.log("Event started, waiting ...")

// controller handler

const events_subject = "cn.xswitch.ctrl.event.custom.conference::maintenance"; //订阅的事件
nc.subscribe(events_subject, function (msg, reply, subject, sid) {
    console.log('Received a message: ' + subject)
    console.log(msg)
})

function wait() {
    // console.log('tick ... ');
    setTimeout(wait, 3000);
}

wait();

其他事件

  • cn.xswitch.ctrl.event.dtmf 系统收到按键信息
  • cn.xswitch.ctrl.event.detected_speech 语音识别结果事件

话单事件

  • cn.xswitch.cdr XCC 话单事件

Event.CDR 事件为 XCC 特别处理后的事件,该话单仅包含话单主要字段,如需更多字段可通过 xcc 配置页面修改。

在通话完毕后发出。每一个 Channel 都会有一个 CDR 事件,如果参与通话的是两条腿(alegbleg),则会有两个 CDR 事件,并分别有 leg 标志。CDR 事件一般会在 Event.Destroy 之前发出。

CDR 事件默认会送到与 Event.Channel 相同的 Subject 上,但也可以通过全局配置参数 cdr-subject 配置单独的 Subject。

比如开启了 cdr-subject,则订阅 cn.xswitch.cdr 即可收到话单事件。

{
  "jsonrpc": "2.0",
  "method": "Event.CDR",
  "params": {
    "node_uuid": "6b7532d6-9d2a-4cfe-bf3c-87a353256de0",
    "node_ip": "172.19.0.3",
    "cdr": {
      "sip_hangup_disposition": "recv_bye",
      "direction": "inbound",
      "answer_stamp": "2022-07-07 10:19:52",
      "start_stamp": "2022-07-07 10:19:52",
      "uuid": "9c780905-b058-4e64-a183-11d535bbfeb6",
      "abs_path": "/usr/local/freeswitch/storage/recordings/auto-record-20220708-9c780905-b058-4e64-a183-11d535bbfeb6.wav",
      "billsec": "3",
      "caller_id_name": "819",
      "caller_id_number": "819",
      "destination_number": "710894413",
      "hangup_cause": "NORMAL_CLEARING",
      "account_code": "819",
      "context": "context-1",
      "duration": "3",
      "end_stamp": "2022-07-07 10:19:55",
      "leg": "a",
      "logical_direction": "inbound"
    },
    "uuid": "9c780905-b058-4e64-a183-11d535bbfeb6"
  }
}

默认 XCC-CDR 字段说明

话单字段中文说明
caller_id_name主叫名称
start_stamp开始时间
billsec计费时长
account_code计费号码
network_addr网络地址
abs_path录音文件绝对路径
answer_stamp应答时间
sip_hangup_dispositionSIP 相关
context呼叫源
duration总时长
end_stamp结束时间
uuid通话 UUID
bleg_uuidB 腿 UUID
direction方向,inbound 为向内,outbound 向外
destination_number被叫号码
network_port网络端口
realm
caller_id_number主叫号码
hangup_cause挂机原因

常用挂机原因说明

: 挂机原因表

挂机原因中文说明
ORIGINATOR_CANCEL主叫挂机
NORMAL_CLEARING正常释放
NORMAL_TEMPORARY_FAILURE临时故障
WRONG_CALL_STATE呼叫状态异常
USER_BUSY用户忙
LOSE_RACE别处应答
MEDIA_TIMEOUT媒体超时
CALL_REJECTED拒绝呼叫
UNALLOCATED_NUMBER空号
NO_ROUTE_DESTINATION无法路由
NO_USER_RESPONSE久叫不应
NO_ANSWER无应答
NORMAL_UNSPECIFIED未定义
NETWORK_OUT_OF_ORDER网络异常
RECOVERY_ON_TIMER_EXPIRE呼叫超时
USER_NOT_REGISTERED用户未注册
SUBSCRIBER_ABSENT用户缺席
GATEWAY_DOWN网关故障
MANDATORY_IE_MISSINGSIP 消息不全
SYSTEM_SHUTDOWN系统关机
INCOMPATIBLE_DESTINATION目的地不兼容
EXCHANGE_ROUTING_ERROR交换路由错误
MANAGER_REQUEST强制挂机
DESTINATION_OUT_OF_ORDER目的地异常
SERVICE_NOT_IMPLEMENTED服务未实现
微信小程序