FreeSWITCH CDR MySQL
Сохранение CDR в mysql и просмотр данных о звонках FreeSWITCH при помощи веб интерфейса - CDR-Viewer.
Подготовим FreeSWITCH для работы с MySQL через ODBC
Предполагается, что сервер mysql (mariadb) установлен.
yum install -y mysql-connector-odbc unixODBC unixODBC-devel
Проверим odbcinst.ini
# Driver from the mysql-connector-odbc package # Setup from the unixODBC package [MySQL] Description = ODBC for MySQL Driver = /usr/lib/libmyodbc5.so Setup = /usr/lib/libodbcmyS.so Driver64 = /usr/lib64/libmyodbc5.so Setup64 = /usr/lib64/libodbcmyS.so FileUsage = 1
Заполним odbc.ini
[freeswitch] Driver=MySQL SERVER=localhost PORT=3306 DATABASE=freeswitchcdr USER=DB_USER PASSWORD=DB_PASSWORD
Проверим подключение к MySQL
echo "select 1" | isql -v freeswitch
+---------------------------------------+ | Connected! | | | | sql-statement | | help [tablename] | | quit | | | +---------------------------------------+ SQL> select 1 +---------------------+ | 1 | +---------------------+ | 1 | +---------------------+ SQLRowCount returns 1 1 rows fetched
Создадим БД MySQL в формате asteriskcdrdb
Создайте файл, например:
touch freeswitchcdr.sql
И скопируйте в него структуру таблицы БД:
CREATE TABLE cdr ( calldate datetime NOT NULL default '0000-00-00 00:00:00', clid varchar(80) NOT NULL default '', src varchar(80) NOT NULL default '', dst varchar(80) NOT NULL default '', dcontext varchar(80) NOT NULL default '', channel varchar(80) NOT NULL default '', dstchannel varchar(80) NOT NULL default '', lastapp varchar(80) NOT NULL default '', lastdata varchar(80) NOT NULL default '', duration int(11) NOT NULL default '0', billsec int(11) NOT NULL default '0', disposition varchar(45) NOT NULL default '', amaflags int(11) NOT NULL default '0', accountcode varchar(20) NOT NULL default '', uniqueid varchar(32) NOT NULL default '', userfield varchar(255) NOT NULL default '', did varchar(50) NOT NULL default '', recordingfile varchar(255) NOT NULL default '', KEY `calldate` (`calldate`), KEY `dst` (`dst`), KEY `accountcode` (`accountcode`), KEY `uniqueid` (`uniqueid`) );
Создаем БД: freeswitchcdr
mysqladmin create freeswitchcdr
Создаем таблицу:cdr
mysql asteriskcdrdb < freeswitchcdr.sql
Задаем права на БД с параметрами определенными в odbc.ini
mysql> GRANT ALL PRIVILEGES ON freeswitchcdr.* TO DB_USER@localhost IDENTIFIED BY 'DB_PASSWORD'; flush privileges; \q
Подготовим FreeSWITCH
Расскомментируйте строку event_handlers/mod_odbc_cdrв файле исходников FS ../freeswitch/modules.conf
и выполните make && make install.
По окончании компиляции скопируйте файл odbc_cdr.conf.xml из исходников в директорию, где установлен FS.
В моем примере это /usr/local/src/freeswitchи /usr/local/freeswitchсоответственно
cp /usr/local/src/freeswitch/src/mod/event_handlers/mod_odbc_cdr/conf/autoload_configs/odbc_cdr.conf.xml /usr/local/freeswitch/conf/autoload_configs/odbc_cdr.conf.xml
И заполните файл следующим содержанием, где параметры БД (odbc-dsn), данные определенные нами в odbc.ini:
<configuration name="odbc_cdr.conf" description="ODBC CDR Configuration"><settings><!-- <param name="odbc-dsn" value="freeswitchcdr:DB_USER:DB_PASSWORD"/> --><param name="odbc-dsn" value="odbc://freeswitch"/><!-- global value can be "a-leg", "b-leg", "both" (default is "both") --><param name="log-leg" value="both"/><!-- value can be "always", "never", "on-db-fail" --><param name="write-csv" value="on-db-fail"/><!-- location to store csv copy of CDR --><param name="csv-path" value="/usr/local/freeswitch/log/odbc_cdr"/><!-- if "csv-path-on-fail" is set, failed INSERTs will be placed here as CSV files otherwise they will be placed in "csv-path" --><param name="csv-path-on-fail" value="/usr/local/freeswitch/log/odbc_cdr/failed"/><!-- dump SQL statement after leg ends --><param name="debug-sql" value="true"/></settings><tables><!-- only a-legs will be inserted into this table --><table name="cdr" log-leg="a-leg"><field name="calldate" chan-var-name="start_stamp"/><field name="clid" chan-var-name="caller_id_name"/><field name="src" chan-var-name="caller_id_number"/><field name="dst" chan-var-name="destination_number"/><field name="dcontext" chan-var-name=""/><field name="channel" chan-var-name="channel_name"/><field name="dstchannel" chan-var-name="bridge_channel"/><field name="lastapp" chan-var-name="hangup_cause"/><field name="lastdata" chan-var-name="sip_hangup_disposition"/><field name="duration" chan-var-name="duration"/><field name="billsec" chan-var-name="billsec"/><field name="disposition" chan-var-name="hangup_cause"/><field name="lastapp" chan-var-name="current_application"/><field name="amaflags" chan-var-name="amaflags"/><field name="uniqueid" chan-var-name="uuid"/><field name="recordingfile" chan-var-name="recordingfile"/><field name="userfield" chan-var-name=""/></table></tables></configuration>
Загрузим модуль mod_odbc_cdr
fs_cli
load mod_odbc_cdr
Если в дальнейшем вы будете вносить изменения в файл odbc_cdr.conf.xmlих можно применить командой:
reload mod_odbc_cdr
Подготовим Asterisk CDR Viewer
cd /var/www/html
git clone https://github.com/g613/asterisk-cdr-viewer.git cd asterisk-cdr-viewer/include
Отредактируем файл config.inc.php
$db_type = 'mysql'; $db_host = 'localhost'; $db_port = '3306'; $db_user = 'DB_USER'; $db_pass = 'DB_PASSWORD'; $db_name = 'freeswitchcdrdb'; $db_table_name = 'cdr'; $db_options = array();
Если все сделано правильно в Asterisk-CDR-Viewer будут отображаться свежие данные о вызовах:
Для того, чтобы работала сортировка по статусу вызова надо отредактировать файл ../asterisk-cdr-viewer/templates/form.tpl.phpзаменив секцию:
<td nowrap=""nowrap><input <?php if ( isset($_REQUEST['disposition_neg'] ) && $_REQUEST['disposition_neg'] == 'true' ) { echo 'checked="checked"'; } ?> type="checkbox" name="disposition_neg" value="true" /> not<select name="disposition" id="disposition"><option <?php if (empty($_REQUEST['disposition']) || $_REQUEST['disposition'] == 'all') { echo 'selected="selected"'; } ?> value="all">All Dispositions</option><option <?php if (isset($_REQUEST['disposition']) && $_REQUEST['disposition'] == 'ANSWERED') { echo 'selected="selected"'; } ?> value="ANSWERED">Answered</option><option <?php if (isset($_REQUEST['disposition']) && $_REQUEST['disposition'] == 'BUSY') { echo 'selected="selected"'; } ?> value="BUSY">Busy</option><option <?php if (isset($_REQUEST['disposition']) && $_REQUEST['disposition'] == 'FAILED') { echo 'selected="selected"'; } ?> value="FAILED">Failed</option><option <?php if (isset($_REQUEST['disposition']) && $_REQUEST['disposition'] == 'NO ANSWER') { echo 'selected="selected"'; } ?> value="NO ANSWER">No Answer</option></select></td>
на следующий код:
<td nowrap=""nowrap><input <?php if ( isset($_REQUEST['disposition_neg'] ) && $_REQUEST['disposition_neg'] == 'true' ) { echo 'checked="checked"'; } ?> type="checkbox" name="disposition_neg" value="true" /> not<select name="disposition" id="disposition"><option <?php if (empty($_REQUEST['disposition']) || $_REQUEST['disposition'] == 'all') { echo 'selected="selected"'; } ?> value="all">All Dispositions</option><option <?php if (isset($_REQUEST['disposition']) && $_REQUEST['disposition'] == 'NORMAL_CLEARING') { echo 'selected="selected"'; } ?> value="NORMAL_CLEARING">Answer</option><option <?php if (isset($_REQUEST['disposition']) && $_REQUEST['disposition'] == 'USER_BUSY') { echo 'selected="selected"'; } ?> value="USER_BUSY">Busy</option><option <?php if (isset($_REQUEST['disposition']) && $_REQUEST['disposition'] == 'UNALLOCATED_NUMBER') { echo 'selected="selected"'; } ?> value="UNALLOCATED_NUMBER">No Number</option><option <?php if (isset($_REQUEST['disposition']) && $_REQUEST['disposition'] == 'NO_ROUTE_DESTINATION') { echo 'selected="selected"'; } ?> value="NO_ROUTE_DESTINATION">No Route</option><option <?php if (isset($_REQUEST['disposition']) && $_REQUEST['disposition'] == 'ORIGINATOR_CANCEL') { echo 'selected="selected"'; } ?> value="ORIGINATOR_CANCEL">No Answer</option></select></td>