В данном посте я расскажу вам о возможностях отправки уведомлений о пропущенных звонках с помощью Asterisk. Я постараюсь привести простые примеры конфигурации и подробнее раскрыть данную тему, далее вы можете экспериментировать по своему усмотрению или потребностям. Asterisk предлагает довольно широкие возможности для решения различных задач, поэтому одну и ту же задачу можно решать по разному, главное результат — стабильная работа ваших сервисов.
Отправка отчета о пропущенном звонке на email
Что имеем:
Входящая многоканальная линия с номером +7 (495) 1234567, IVR, 4 оператора в очереди вызова.
Задачи:
1. Отправлять отчет о пропущенном звонке, с указанием номера звонящего, времени поступления звонка и времени ожидания на линии.
2. Если абонент ждал на линии более 10 секунд и по какой-либо причине положил трубку, не дождавшись ответа оператора — отправляем отчет о пропущенном звонке.
3. Заносить в БД (в текущем примере MySQL) данные о том, какой оператор в очереди ответил звонок и фиксируем время в которое разговор был завершен.
В качестве решения приведу пример конфигурации (один из возможных вариантов решения), с комментариями на самых интересных по-моему мнению моментах.
Вот так выглядит конфигурация IVR рабочего времени + очереди вызова:
[globals]
CIDFILE=/etc/asterisk/inc-calls/call-noanswer
SQLHOST=db.domain.ru
SQLUSER=asterisksql
SQLPASS=Gt6Rju8FkS
SQLDB=asteriskdb
IVRWORK=custom/IVR_company_wav
[incoming-74951234567]
exten => h,1,Set(WAITTIME=10)
exten => h,n,Set(CTALL=$[${CDR(duration)}])
exten => h,n,Set(CTANSWER=$[${CDR(billsec)}])
exten => h,n,Set(CTDTIME=$[${CTALL}-${CTANSWER}])
exten => h,n,NoOP(${CDR(disposition)})
exten => h,n,NoOP(${CTDTIME})
exten => h,n,GotoIf($["${CDR(disposition)}" = "NO ANSWER"]?timecheck:n1)
exten => h,n(n1),GotoIf($["${CDR(disposition)}" = "BUSY"]?timecheck:n2)
exten => h,n(n2),GotoIf($["${CDR(disposition)}" = "FAILED"]?timecheck:n3)
exten => h,n(n3),GotoIf($["${CDR(disposition)}" = "ANSWERED"]?n4:misscall)
exten => h,n(n4),MYSQL(Connect connid ${SQLHOST} ${SQLUSER} ${SQLPASS} ${SQLDB})
exten => h,n,MYSQL(Query resultid ${connid} UPDATE office_calls SET active=0 WHERE asterisk_id='${QID}')
exten => h,n,MYSQL(Clear ${resultid})
exten => h,n,MYSQL(Disconnect ${connid})
exten => h,n(hang),Hangup()
exten => h,n(timecheck),GotoIf($[${CTDTIME} > ${WAITTIME}]?misscall:hang)
exten => h,n(misscall),Goto(noanswer,s,1)
exten => s,1,NoOp(${CALLERID(num)})
exten => s,n,Set(CALLID=74951234567)
exten => s,n,Set(CALLER=${CALLERID(num)})
exten => s,n,Set(__QID=${CDR(uniqueid)})
exten => s,n(begin),GotoIfTime(10:00-22:00,mon-sat,*,*?workdays:outofoffice)
exten => s,n(workdays),NoOp(Incoming CALL from ${CALLERID(num)} to ${EXTEN})
exten => s,n,Answer()
exten => s,n,ResetCDR(w)
exten => s,n,Wait(1)
exten => s,n,Background(${IVRWORK})
exten => s,n,Queue(operators,t,,,300,,startflag1)
exten => s,n,NoOp(${DIALSTATUS})
exten => s,n,Goto(noanswer,s,1)
exten => s,n,Hangup()
Обратите внимание, что если работает IVR и требуется узнать точное время ожидания абонента на линии (в обратном случае, у вас посчитается и время, которое абонет слушал голосовое меню), то нужно после Answer() добавить ResetCDR(w). Еще один интересный момент — запись в БД нам нужно заносить как только оператор в очереди ответит на звонок — тут нам поможет макрос startflag1, который будет выполнен, как только любой оператор в очереди ответит на звонок.
Тут все довольно просто, если на вызов не ответили, переходим в контекст noanswer, который выглядит следующим образом:
[noanswer]
exten => s,1,NoOp(UID CALL: ${UNIQUEID} / DATE: ${STRFTIME(${EPOCH},,%Y%m%d-%H%M%S)}))
exten => s,n,Set(RANDOM=${RAND(1000,9999)})
exten => s,n,Set(COUNT=${DB(fwcid2/count)})
exten => s,n,GotoIf($[${ISNULL(${COUNT})}]?:nextstep)
exten => s,n,Set(DB(fwcid2/count)=1)
exten => s,n,NoOp()
exten => s,n,NoOp(UNIQID = ${COUNT})
exten => s,n,Set(COUNT=$[${COUNT} + 1])
exten => s,n,Set(DB(fwcid2/count)=${COUNT})
exten => s,n,System(echo "Неотвеченный вызов с номера +7${CALLERID(NUM)} в ${STRFTIME(${EPOCH},,%H:%M)}" > ${CIDFILE}-${CALLERID(NUM)}-${COUNT})
exten => s,n,System(echo "" >> ${CIDFILE}-${CALLERID(NUM)}-${COUNT})
exten => s,n,System(echo "Время ожидания абонента на линии составило ${CTDTIME} сек" >> ${CIDFILE}-${CALLERID(NUM)}-${COUNT})
exten => s,n,System(echo "hello" | mutt -x -s "+74951234567: пропущенный звонок ${STRFTIME(${EPOCH},,%d.%m.%Y)} ${STRFTIME(${EPOCH},,%H:%M)}" -e "set from="voip@domain.ru"" -e 'set realname='Asterisk'' voip@domain.ru < ${CIDFILE}-${CALLERID(NUM)}-${COUNT})
exten => s,n,System(/bin/rm -f ${CIDFILE}-${CALLERID(NUM)}-${COUNT})
exten => s,n,Hangup()
${STRFTIME(${EPOCH},,%H:%M)} — время поступления звонка.
${CALLERID(NUM)} — номер звонящего.
${COUNT} — по большей части пример работы с ASTBD, значение переменной добавляется в конец создаваемого файла, чтобы сделать его уникальным, на случай если с одного и того же номера, в одно и то же время поступит звонок.
Теперь о добавлении записей в таблицу MySQL.
${SQLHOST/SQLUSER/SQLPASS/SQLD} — данные переменные я определил в секции globals.
${QID} — переменная которую мы передаем в макрос, предварительно определив ее при входящем звонке 'Set(__QID=${CDR(uniqueid)})'. Обратите внимание на два ведущих символа подчеркивания, позволяющих унаследовать переменную в макрос macro-startflag1.
[macro-startflag1]
exten => s,1,Set(CALLID=74951234567)
exten => s,n,MYSQL(Connect connid ${SQLHOST} ${SQLUSER} ${SQLPASS} ${SQLDB})
exten => s,n,MYSQL(Query resultid ${connid} INSERT INTO office_calls VALUES (NULL,'${STRFTIME(,GMT,%G-%m-%d %H:%M:%S)}',1,'${CALLID}','${CDR(src)}','${CDR(dstcha
nnel):0:9}','${STRFTIME(,GMT,%G-%m-%d %H:%M:%S)}','${STRFTIME(,GMT,%G-%m-%d %H:%M:%S)}','${QID}'))
exten => s,n,MYSQL(Clear ${resultid})
exten => s,n,MYSQL(Disconnect ${connid})
exten => s,n,Hangup()
Рассмотрим еще одну задачу: требуется формировать XML файл при пропущенных звонках.
Формат файла должен быть следующего вида:
<?xml version="1.0" encoding="UTF-8"?>
<callback_request>
<id>100XXXX</id> --- XXX какой-то уникальный идентификатор
<name></name> --- номер телефона, на который пришел звонок
<phone>123456</phone> --- номер телефона, с которого пришел звонок
<comment>Пропущенный звонок</comment>
<completed>false</completed>
<created_at>11.12.2012 - 17:19</created_at> --- дата звонка
<updated_at>11.12.2012 - 17:19</updated_at> --- дата звонка
<no_answer/>
</callback_request>
В решении задачи я воспользуюсь командой System() и perl- скриптом.
Установим XML::Writer
yum install perl-XML-Writer
Скрипт /etc/asterisk/scripts/genxml.pl выглядит следующим образом:
#!/usr/bin/env perl
# Create XML file
use strict;
use warnings;
use XML::Writer;
# Out to file
#open STDOUT, ">", "REQUEST.20121211171903.xml" or die "$0: open: $!";
my $doc = new XML::Writer();
# Pring attributes
$doc->xmlDecl('UTF-8');
$doc->startTag("callback_request");
$doc->dataElement( id => "$ARGV[0]");
$doc->startTag( "name");
$doc->characters( "$ARGV[1]");
$doc->endTag( "name");
$doc->dataElement( phone => "$ARGV[2]");
$doc->dataElement( comment => "Пропущенный звонок");
$doc->dataElement( completed => "false");
$doc->dataElement( created_at => "$ARGV[3]");
$doc->dataElement( updated_at => "$ARGV[3]");
$doc->emptyTag( "no_answer");
$doc->endTag();
$doc->end();
Запуск скрипта производится следующим образом:
exten => s,n,System(/usr/bin/perl /etc/asterisk/scripts/genxml.pl "100${RANDOM}" "74951234567" "${CALLERID(NUM)}" "${STRFTIME(${EPOCH},,%d.%m.%Y - %H:%M)}" > /srv/www/domain.ru/xml/REQUEST.${STRFTIME(${EPOCH},,%Y%m%d%H%M%S)}.xml)
Надеюсь данный материал будет полезен вам.
Спасибо за внимание.
Автор: sfw