Отправка уведомлений о пропущенных звонках из Asterisk

Что имеем: Входящая многоканальная линия с номером +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 выглядит следующим образом:

/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)
otpravka_otcheta_o_propuschennom_zvonke_na_email.txt · Последние изменения: 2013/11/18 16:43 (внешнее изменение)
GNU Free Documentation License 1.3
Driven by DokuWiki Recent changes RSS feed Valid CSS Valid XHTML 1.0 Яндекс.Метрика