freeswitch支持电话拨入,可以接入远端IPPBX实现和现网电话的互通。

有时候我们需要统计记录所有的电话详单,并输出到指定的数据库用于数据统计。

包括呼叫方,被叫方,呼叫时间,接听时间,挂断时间,通话时长,会话等等信息。

于是,这部分可以自己写一个freeswitch插件来完成上述功能。

自己动手即可。

诀窍很简单,只要知道几个关键API即可。

首先创建一个插件。

SWITCH_MODULE_LOAD_FUNCTION(mod_cdr_mysql_load)

{

switch_status_t status = SWITCH_STATUS_SUCCESS;

load_config(pool);

if ((status = switch_dir_make_recursive(globals.log_dir, SWITCH_DEFAULT_DIR_PERMS, pool)) != SWITCH_STATUS_SUCCESS) {

switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error creating %s\n", globals.log_dir);

}

switch_core_add_state_handler(&state_handlers);

*module_interface = switch_loadable_module_create_module_interface(pool, modname);

return status;

}

SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_cdr_mysql_shutdown)

{

globals.shutdown = 1;

switch_mutex_lock(globals.db_mutex);

if(globals.db_connection) {

mysql_close(globals.db_connection);

}

switch_mutex_unlock(globals.db_mutex);

switch_mutex_destroy(globals.db_mutex);

switch_core_remove_state_handler(&state_handlers);

return SWITCH_STATUS_SUCCESS;

}

这里基本都是固定的写法。

这里有一个要注意自己实现的函数,就是load_config(pool);

在这个函数中,你可以实现对XML配置文件的读取,比如,对mysql的连接信息相关读取。

此后,实现一个函数来处理电话结束后的详单生成。

这里有一个核心函数

switch_core_add_state_handler(&state_handlers);

这里是告诉freesweitch,我要关心你的那些状态。并回调绑定对应的函数。

state_handlers包括了如下状态(各个freeswitch版本不同可能有些差异)

static switch_state_handler_table_t state_handlers = {

/*.on_init */ NULL,

/*.on_routing */ NULL,

/*.on_execute */ NULL,

/*.on_hangup */ NULL,

/*.on_exchange_media */ NULL,

/*.on_soft_execute */ NULL,

/*.on_consume_media */ NULL,

/*.on_hibernate */ NULL,

/*.on_reset */ NULL,

/*.on_park */ NULL,

/*.on_reporting */ on_reporting

};

上述代码,我只关心on_reporting 状态。

剩下的状态,请自行谷歌。

下一步,我们要绑定事件产生后的处理函数了。怎么做呢?看见上面的on_reporting没,这就是你的函数指针的名字。

于是就直接写下如下代码即可。

static switch_status_t on_reporting(switch_core_session_t *session)

{

switch_channel_t *channel = switch_core_session_get_channel(session);

switch_status_t status = SWITCH_STATUS_SUCCESS;

const char *template_str = NULL;

char *expanded_vars = NULL, *sql = NULL;

char *answer_vars = NULL;

char *user_vars = NULL;

if (globals.shutdown) {

return SWITCH_STATUS_SUCCESS;

}

{

const char * channel_name = NULL;

const char * filter = "loopback/";

if ((channel_name = switch_channel_get_variable(channel, "channel_name"))) {

if(!strncasecmp(channel_name,filter, sizeof(filter))){

return SWITCH_STATUS_SUCCESS;

}

}

}

if(check_cdr_direction(session) != SWITCH_STATUS_SUCCESS ){

if (!((globals.legs & CDR_LEG_A) && (globals.legs & CDR_LEG_B))) {

if ((globals.legs & CDR_LEG_A)) {

if (switch_channel_get_originator_caller_profile(channel)) {

return SWITCH_STATUS_SUCCESS;

}

} else {

if (switch_channel_get_originatee_caller_profile(channel)) {

return SWITCH_STATUS_SUCCESS;

}

}

}

}

if (!((globals.legs & CDR_LEG_A) && (globals.legs & CDR_LEG_B))) {

if ((globals.legs & CDR_LEG_A)) {

if (switch_channel_get_originator_caller_profile(channel)) {

return SWITCH_STATUS_SUCCESS;

}

} else {

if (switch_channel_get_originatee_caller_profile(channel)) {

return SWITCH_STATUS_SUCCESS;

}

}

}

if (globals.debug) {

switch_event_t *event;

if (switch_event_create_plain(&event, SWITCH_EVENT_CHANNEL_DATA) == SWITCH_STATUS_SUCCESS) {

char *buf;

switch_channel_event_set_data(channel, event);

switch_event_serialize(event, &buf, SWITCH_FALSE);

switch_assert(buf);

switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "CHANNEL_DATA:\n%s\n", buf);

switch_event_destroy(&event);

switch_safe_free(buf);

}

}

template_str = (const char *) switch_core_hash_find(globals.template_hash, globals.default_template);

if (!template_str) {

template_str = default_template;

}

//switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "[my_on_reporting]template_str=%s.\n", template_str);expanded_vars = switch_channel_expand_variables(channel, template_str);

}

这里的大部分代码是固定的,直接照抄就可以。

这里强调两个API是你必须要会用的。

(1) switch_core_hash_find

这个函数是,根据你的配置模板,加载指定的配置项目。

简单来说,freeswitch支持什么参数呢?

例如:

const char *default_template =

"\"${caller_id_name}\",\"${caller_id_number}\",\"${destination_number}\",\"${context}\","

"\"${start_stamp}\",\"${answer_stamp}\",\"${end_stamp}\",${duration},${billsec},"

"\"${hangup_cause}\",\"${uuid}\",\"${accountcode}\"";

这些参数名都是固定的。你可以从话单中获得这些参数的值。

你可以任意缩减或者增加这些参数名,已达到话单要求的目的。

(2)switch_channel_expand_variables

根据参数名找到对应的数值。

返回值是一个静态的const char* 这个对应你上面给出的参数名。

剩下的就是拼装sql入库的代码了,这部分,就不许赘述了。

以上,你就可以得到完整的freeswitch中的话单信息并入库。

freeswitch通话记录mysql_freeswitch电话计费详单入库方法相关推荐

  1. html5通话记录,通话记录怎么查询

    通话记录怎么查询 手机是生活中最常见的一种通讯工具,打电话也是最普遍的一种联络方式,每天都会有不同的手机号码呼出或是呼入.如果不小心删除了怎么办?不用着急,下面和大家分享一下如何查询通话记录,找回通话 ...

  2. android系统通话记录,安卓手机通话记录怎么恢复?快速恢复

    原标题:安卓手机通话记录怎么恢复?快速恢复 安卓手机通话记录怎么恢复?我们的手机上只要打过电话,一定就会有手机通话记录,那么问题就出现了,若是我们不小心将我们我们的手机通话记录给删除了,我们又比较需要 ...

  3. 通话记录有办法恢复吗?

    通话记录有办法恢复吗?平时大家都认为通话记录没什么用,这是个误区,相比通讯录.短信.社交软件的聊天记录,通话记录的存在感确实是略低一筹,但通话记录内可保存着那些你未存储的陌生手机号码.这些手机号码有用 ...

  4. 一分钟告诉你通话记录能查到多久前的!

    案例:通话记录能查到一年前的吗? [朋友们,苹果通话记录可以查询到一年前的吗?保存时间大概是多久?] 通话记录是可以查到一定时间范围内的,不同的手机系统和运营商对于通话记录的保存时间也有所不同.通话记 ...

  5. 电话计算机怎么看记录,移动怎么查通话记录详单(中国移动通话查询明细)

    移动怎么查通话记录详单(中国移动通话查询明细) 如果我们知道自己手机号的服务密码的话,是可以去营业厅查询最近6个月的通话记录的,但如果我们忘记了自己的密码该怎么办呢?是否还有办法进行查询呢?其实方法还 ...

  6. Android中联系人和通话记录详解(2)

    在文章Android中联系人和通话记录详解(1)中对通话记录进行了分析,本章将对联系人的数据库表.字段以及Insert,Query,Delelte,Update四大基本数据操作进行分析. 与联系人相关 ...

  7. Android 7.1.1 通话记录数据库详解

    在拨打或接听来电时,都会在Dialer中看到新增的通话记录,前两天遇到了个通话记录中类型显示得不对的问题,就跟踪了下Android中CallLog的相关流程,在这记录下,以后查起来方便些,顺便分享给大 ...

  8. android 通话记录分析,Android中联系人和通话记录详解(1)

    由于项目开发需要用到手机联系人和通话记录的详细信息,于是对联系人和通话记录的表及各字段以及具体实现做了详细分析. 首先,通过模拟器或者Root过的手机,在/data/data/com.android. ...

  9. 在计算机上知道手机密码,不知道密码查手机通话记录:傻瓜式教程

    不知道密码查手机通话记录:傻瓜式教程 搜狐媒体平台 05-14 09:12 大 有时我们不慎忘记了自己手机的服务密码,在这种情况下,是否还可以查询自己手机的通话记录呢?答案是可以的,今天我要介绍的方法 ...

  10. 误删通话记录?这几个方法能恢复

    有没有朋友和我一样将通话记录删了却又想找回来?我今天汇总了几个可以恢复通话记录的方法,还附带了一个恢复微信聊天记录的方法,需要的朋友就快收藏吧. 恢复通话记录的方法: 一.借助iTunes备份恢复 i ...

最新文章

  1. JavaScript 爆红后,微软为何还要开发 TypeScript?
  2. EF迁移:回滚上一次应用的迁移?
  3. linux下查找文件及内容 grep
  4. 什么?超过60%的开发者都开始从Java 8 升级到 Java 11了?
  5. 脱壳学习之加壳的概念
  6. Python3网络爬虫快速入门实战解析(一小时入门 Python 3 网络爬虫)
  7. mysql通用查询日志_MySQL通用查询日志(GeneralQueryLog)_MySQL
  8. LeetCode 1750. 删除字符串两端相同字符后的最短长度(双指针)
  9. InnoDB存储引擎详解
  10. java ajax简单实例_JAVA编写的AJAX例子,很简单,但是很容易理解详解
  11. 2017年个人工作总结
  12. 126邮箱手机登录服务器密码怎么办,魅族手机登录网易126邮箱提示账号密码或协议设置不正确解决办法...
  13. 性能测试 性能测试实战(七)Jmeter分布式性能测试 influxDB Grafana Master Salve 主从配置 高并发性能测试 环境搭建 性能数据收集 性能数据可视化平台 搭建问题分析
  14. 我的世界java版注册账号教程_我的世界java版官方购买教程
  15. P5594 【XR-4】模拟赛
  16. 攻防世界--杂项misc-János-the-Ripper--题解
  17. Document-oriented database(文档数据库)
  18. 高品质回音消除 模块 : F-23
  19. 【AntdVue】下拉选择框乱回弹问题
  20. Python自动化办公:pandas入门教程

热门文章

  1. 服务器虚拟化对硬件有要求,虚拟主机对硬件有要求吗
  2. Python爆力破解rar密码并对比多线程的效率
  3. 色相环上面的颜色和相邻颜色的关系是什么
  4. PHY之MDIO解析
  5. 用计算机求值根号12345,手算开根号
  6. 网络安全设备-认识运维安全管理与审计系统(堡垒机)
  7. 磁带库Scalar i6000界面基本操作步骤
  8. linux环境下hadoop版本的升级、更换
  9. 服务器项目管理软件,项目管理软件-Microsoft Project.pdf
  10. 挑战背后的故事 - OceanBase的6000万tpmC之路