Новый web-интерфейс статистики и прослушивания вызовов для IP АТС Asterisk

Идея написания web-интерфейса статистики и прослушивания вызовов для IP АТС Asterisk не покидала меня вот уже несколько лет. Решения, найденные в Интернет, не устраивали по тем или иным критериям — где-то не хватало функционала, какие-то из них совсем не радовали глаз.

И вот, вооружившись стеком технологий и оседлав боевого коня, предоставленного компанией ServerClub, я отправился в путь.

Результатом моего путешествия стал новый интерфейс, с диаграммами, графиками и возможностью скачивать и прослушивать вызовы.
Не стану далее утомлять вас словесами, вот пара скриншотов:
657eeeb7238345b5b45cc2e835e153b8.png
cd8b87f0faf14dc79768ae7ffd402440.png

А под катом вас ждет видео-гайд по интерфейсу, необходимые настройки и подробное описание всего доступного функционала.

Интерфейс.


Дабы пост не выглядел как простыня из скриншотов, я сделал небольшое слайдшоу, где вы можете ознакомиться с интерфейсом.

Описание. Что уже готово, планы.


На текущий момент реализован следующий функционал:

Входящие вызовы:

  • Отчет — Количество звонков в очереди за период (всего/непринятые/отвеченные/не дождались ответа)
  • Диаграмма — Принятые/Непринятые
  • Диаграмма — Принятые, распределение по операторам
  • Диаграмма — Неотвеченные, распределение по операторам
  • Отчет — Статистика по операторам. Кто и сколько принял/не принял вызовов
  • Отчет — Причина разъединения (оператор/клиент)
  • Отчет — Вызовы. Сколько на дату Поступило/Отвеченных/Неотвеченных
  • Поиск записей в БД. Прослушивание и скачивание записей разговров

Исходящие вызовы:
  • Отчет — Всего звонков, неотвеченные/отвеченные/занято (ошибка вызова), общая продолжительность и распределение вызовов по длительности (см. след. пункт).
  • Диаграмма — Распределения вызовов по длительности: до 30с, от 30с до 90с, от 90с
  • Диаграмма — Количество звонков, распределение по менеджерам
  • Отчет — распределение звонков по длительности между менеджерами/операторами
  • Отчет — Вызовы. Сколько было совершено вызовов на дату (считаем только отвеченные*)
  • Поиск записей в БД. Прослушивание и скачивание записей разговров

*отчеты по исходящим строятся только по звонкам во мир, т.е. внутренние звонки между сотрудниками не учитываются

Так же доступны несколько настроек, где указывается использует ли Asterisk очереди* и путь к файлам записей разговоров на сервере.
*реализовано в настройках, но пока нет в интерфейсе

В ближайших планах добавить:

  • возможность группировать менеджеров/операторов и строить отчеты по группам
  • возможность создавать пользователей и разграничивать их права в просмотре отчетов по группам
  • построение отчетов, если на Asterisk не используются очереди
  • поиск, прослушивание и скачивание записей во всей БД, без фильтров «Входящие/Исходящие» (чтобы видеть и внутренние звонки)

Asterisk. Настройки


Для работы с описываемым интерфейсом потребуется Asterisk версии 1.8 и выше.
На АТС должно быть настроено ведение записей CDR и queue_log в БД MySQL. Если вы это еще не сделали, то я расскажу как.
Так же я приведу пример настройки диалплана Asterisk, для организации сохранения записей разговоров.
Настраиваем Asterisk для работы с MySQL
1. Устанавливаем необходимые пакеты (для примера в Debian/Ubuntu)
aptitude install unixodbc-dev libmyodbc

2. Asterisk должен быть собран со следующими опциями
9d37fd2a5c08439f8a69fe81a398891c.png
34d0b50241d3443d827afa222aede0f4.png
3. Далее редактируем несколько конфиг-файлов
небольшой хинт, если odbc-коннектор не цепляется
Поймал на одной из систем баг, при котором коннектор почему-то перестал цепляться и астер сваливался в корку:

Core was generated by `asterisk -cvvvvvvvgd'.

Program terminated with signal 8, Arithmetic exception.

#0 0×00007ff4cc77a61b in sqlchar_as_sqlwchar () from /usr/lib/x86_64-linux-gnu/odbc/libmyodbc.so

решил тем, что скачал последнюю версию с сайта MySQL — dev.mysql.com/downloads/file/? id=461779

распаковал либы в /usr/lib/x86_64-linux-gnu/odbc/

и чуть подправил конфиг

/etc/odbcinst.ini

[MySQL] Descripti driver
Driver = /usr/lib/x86_64-linux-gnu/odbc/libmyodbc5w.so
Setup = /usr/lib/x86_64-linux-gnu/odbc/libodbcmy5S.so 
CPTimeout =
CPReuse =


/etc/asterisk/res_odbc.conf

[asterisk]
enabled => yes
dsn => MySQL-asterisk
username => asterisk_user
password => 232d2edxse3e

cdr_adaptive_odbc.conf

[cdr_adaptive_connection]
connection=asterisk
table=cdr
alias start => calldate
# раскоментируй, если хочешь видеть реальный номер, накоторый пришел вызов, а не номер оператора очереди
#alias dst => does_not_exist
#alias realdst => dst

/etc/odbc.ini

[MySQL-asterisk]
Description = MySQL Asterisk database
;Trace = Off
;TraceFile = stderr
Driver = MySQL
Server = localhost
User = asterisk_user
Password = 232d2edxse3e
;Port = 3306
Socket = /var/run/mysqld/mysqld.sock
Database = asterisk
Charset = utf8

/etc/odbcinst.ini

[MySQL]
Description = MySQL driver
Driver = /usr/lib/odbc/libmyodbc.so
Setup = /usr/lib/odbc/libodbcmyS.so
CPTimeout =
CPReuse =

*для x64
[MySQL]
Description = MySQL driver
Driver = /usr/lib/x86_64-linux-gnu/odbc/libmyodbc.so
Setup = /usr/lib/x86_64-linux-gnu/odbc/libodbcmyS.so
CPTimeout =
CPReuse =

4. Создадим БД и таблицу cdr в MYSQL
mysql> create database asterisk;
mysql> use asterisk;
mysql> CREATE TABLE `cdr` ( `id` int(9) unsigned NOT NULL AUTO_INCREMENT,
                    `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 '',
                    `filename` varchar(255) NOT NULL DEFAULT '',
                    PRIMARY KEY (`id`),
                    KEY `calldate` (`calldate`),
                    KEY `accountcode` (`accountcode`),
                    KEY `uniqueid` (`uniqueid`),
                    KEY `dst` (`dst`),
                    KEY `src` (`src`) ) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8;
mysql> grant all on asterisk.* to 'asterisk_user'@'localhost' identified by '232d2edxse3e';


5. Теперь создадим табличку queue_log
mysql> CREATE TABLE IF NOT EXISTS `queue_log` (
`time` varchar(32) DEFAULT NULL,
`callid` char(64) DEFAULT NULL,
`queuename` char(64) DEFAULT NULL,
`agent` char(64) DEFAULT NULL,
`event` char(32) DEFAULT NULL,
`data` char(64) DEFAULT NULL,
`data1` char(64) DEFAULT NULL,
`data2` char(64) DEFAULT NULL,
`data3` char(64) DEFAULT NULL,
`data4` char(64) DEFAULT NULL,
`data5` char(64) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
mysql> \q
Bye

6. Внесем в /etc/asterisk/extconfig.conf

строку
queue_log => odbc,asterisk

7. Перезагружаем Asterisk и проверяем подключение
*CLI> odbc show asterisk 
ODBC DSN Settings
-----------------
  Name:   asterisk
  DSN:    MySQL-asterisk
    Last connection attempt: 1970-01-01 07:00:00
  Pooled: No
  Connected: Yes

8. Так же стоит позвонить и проверить попадают ли данные в БД

Диалплан Asterisk — выдержка из /etc/asterisk/extensions.ael
globals {
    WAV=/var/calls; //Временный каталог с WAV
    MP3=/var/calls; //Куда выгружать mp3 файлы
    RECORDING=1; // Запись, 1 - включена.
};

macro recording (calling,called) {
        if ("${RECORDING}" = "1"){
              Set(fname=${UNIQUEID}-${STRFTIME(${EPOCH},,%Y-%m-%d-%H_%M)}-${calling}-${called});
	      Set(datedir=${STRFTIME(${EPOCH},,%Y/%m/%d)});
	      System(mkdir -p ${MP3}/${datedir});
	      System(mkdir -p ${WAV}/${datedir});
              Set(monopt=nice -n 19 /usr/bin/lame -b 32  --silent "${WAV}/${datedir}/${fname}.wav"  "${MP3}/${datedir}/${fname}.mp3" && rm -f "${WAV}/${fname}.wav" && chmod o+r "${MP3}/${datedir}/${fname}.mp3");
              Set(CDR(filename)=${fname}.mp3);
	      Set(CDR(recordingfile)=${fname}.wav);
              Set(CDR(realdst)=${called});
              MixMonitor(${WAV}/${datedir}/${fname}.wav,b,${monopt});

       };
};

_XXXXXX => {
&recording(${CALLERID(number)},${EXTEN});
Dial(SIP/83843${EXTEN}@multifon,180,tT);
HangUP();
} // end of _XXXXXX

Файлы записей разговоров попадают прямиков в 
/var/calls

где имеют следующую иерархию

ls /var/calls/2016/ -l
total 24
drwxr-xr-x 19 asterisk asterisk 4096 May 31 10:10 05
drwxr-xr-x 30 asterisk asterisk 4096 Jun 30 10:02 06
drwxr-xr-x 31 asterisk asterisk 4096 Jul 31 10:18 07
drwxr-xr-x 31 asterisk asterisk 4096 Aug 31 09:00 08
drwxr-xr-x 26 asterisk asterisk 4096 Sep 26 09:51 09

Asterisk. Подключение к интерфейсу статистики


Настало время развеять некоторые сомнения, или же подтвердить некоторые догадки.
Да — на текущий момент сервис предоставляется по модели SAAS, т.е. на вашу АТС устанавливается клиент для синхронизации БД и записей звонков.

После регистрации (не думаю, что стоит на ней подробно останавливаться — там все как обычно), нужно зайти в личный кабинет по адресу stat.vistep.ru, перейти в настройки, указать путь к файлам записей и нажать «Сохранить».
После чего будет доступна ссылка на скачивание скрипта-клиента.

Для установки скрипта нужно выполнить следующие шаги:
1. Установить на сервер nodejs и менеджер пакетов npm, если они еще не установлены (с помощью yum или apt/aptitude/apt-get)
2. Установить pm2

npm install -g pm2

3. Создать и перейти в папку /opt/stat.vistep.ru
mkdir /opt/stat.vistep.ru
cd /opt/stat.vistep.ru

4. Поместить архив со скриптом в папку, созданную шагом ранее, и распаковать его
unzip skript_name.zip

5. Отредактировать скрипт, внеся изменения в строки 393 — 397 (и 398 — опционально, если вам знакомы regexp), а именно
"dbhost":"localhost",
"dbuser":"asterisk_user",
"dbpassword":"232w2edxse3e",
"db":"asterisk", 
"timezone":"Asia/Novokuznetsk", // <--- часовой пояс
"fileMask":  /\.*/  // 

6. Запустить скрипт на выполнение:
pm2 start stat.vistep.ru.js --name "ViStep.RU stat"

7. Настроить автозапуск/останов скрипта синхронизации вместе с ОС:
pm2 startup
pm2 save

С настройками на этом все.
Осталось дождаться загрузки данных на сервер статистики и начать пользоваться!

Заключение


Вот и завершился мой сказ о путешествии и его результатах. Но только сказ, не само путешествие — оно еще только начинается. Верю, что ждут меня еще многие свершения, увлекательные пути-дороги и интересные квесты.

За помощью в настройке Asterisk милости прошу писать нам на support@vistep.ru
Ежели вопрос по сотрудничеству, условиям предоставления сервиса или еще какая оказия, то жду писем на sales@vistep.ru

Так же все мои контакты есть в профиле и, конечно, я с удовольствием отвечу на ваши вопросы в комментариях.

За сим позвольте закончить.
Благодарю за внимание!

Комментарии (2)

  • 27 сентября 2016 в 09:23

    +1

    Вы бы предоставили демо доступ к ссылочке, что есть в статье — большинство заинтересованных сказало бы Вам огромное спасибо!
    • 27 сентября 2016 в 09:35

      0

      Упустил из виду этот момент.
      Подготовлю в течение пары часов демо-доступ и обновлю статью.

© Habrahabr.ru