Различия

Здесь показаны различия между двумя версиями данной страницы.

Ссылка на это сравнение

Предыдущая версия справа и слева Предыдущая версия
Следующая версия
Предыдущая версия
otpravka_otcheta_o_propuschennom_zvonke_na_email [2013/11/18 16:42]
ansealk
otpravka_otcheta_o_propuschennom_zvonke_na_email [2013/11/18 16:43] (текущий)
Строка 1: Строка 1:
 +====== Отправка уведомлений о пропущенных звонках из Asterisk ======
 +**Что имеем:​** Входящая многоканальная линия с номером +7 (495) 1234567, IVR, 4 оператора в очереди вызова.
 +**Задачи:​**
 +  - Отправлять отчет о пропущенном звонке,​ с указанием номера звонящего,​ времени поступления звонка и времени ожидания на линии. ​
 +  - Если абонент ждал на линии более 10 секунд и по какой-либо причине положил трубку,​ не дождавшись ответа оператора — отправляем отчет о пропущенном звонке.
 +  - Заносить в БД (в текущем примере MySQL) данные о том, какой оператор в очереди ответил звонок и фиксируем время в которое разговор был завершен.
  
 +В качестве решения приведу пример конфигурации (один из возможных вариантов решения),​ с комментариями на самых интересных по-моему мнению моментах.
 +Вот так выглядит конфигурация IVR рабочего времени + очереди вызова:​
 +<file lua>
 +[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()
 +</​file>​
 +
 +Обратите внимание,​ что если работает IVR и требуется узнать точное время ожидания абонента на линии (в обратном случае,​ у вас посчитается и время, которое абонет слушал голосовое меню), то нужно после Answer() добавить ResetCDR(w). Еще один интересный момент — запись в БД нам нужно заносить как только оператор в очереди ответит на звонок — тут нам поможет макрос startflag1, который будет выполнен,​ как только любой оператор в очереди ответит на звонок.
 +
 +Тут все довольно просто,​ если на вызов не ответили,​ переходим в контекст noanswer, который выглядит следующим образом:​
 +<file lua>
 +[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()
 +</​file>​
 +
 +  * ${STRFTIME(${EPOCH},,​%H:​%M)} — время поступления звонка.
 +  * ${CALLERID(NUM)} — номер звонящего.
 +  * ${COUNT} — по большей части пример работы с ASTBD, значение переменной добавляется в конец создаваемого файла, чтобы сделать его уникальным,​ на случай если с одного и того же номера,​ в одно и то же время поступит звонок.
 +Теперь о добавлении записей в таблицу MySQL.
 +  * ${SQLHOST/​SQLUSER/​SQLPASS/​SQLD} — данные переменные я определил в секции globals.
 +  * ${QID} — переменная которую мы передаем в макрос,​ предварительно определив ее при входящем звонке '​Set(__QID=${CDR(uniqueid)})'​. Обратите внимание на два ведущих символа подчеркивания,​ позволяющих унаследовать переменную в макрос macro-startflag1.
 +<file lua>
 +[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()
 +</​file>​
 +
 +**Рассмотрим еще одну задачу:​** требуется формировать XML файл при пропущенных звонках.
 +Формат файла должен быть следующего вида:
 +<file 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>​
 +</​file>​
 +В решении задачи я воспользуюсь командой System() и perl- скриптом.
 +
 +Установим XML::Writer
 +<code bash>
 +yum install perl-XML-Writer
 +</​code>​
 +
 +Скрипт /​etc/​asterisk/​scripts/​genxml.pl выглядит следующим образом:​
 +<file perl /​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();​
 +</​file>​
 +
 +Запуск скрипта производится следующим образом:​
 +<code lua>
 +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)
 +</​code>​
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 Яндекс.Метрика