Задача
Имеется небольшой call-центр. Все входящие звонки с разных линий и номеров сначала поступают на сервер Asterisk (FreeBSD+Asterisk 11.14.1), а он в свою очередь распределяет эти звонки между всеми операторами по определенному сценарию (queues).
При звонке, клиент сначала прослушивает голосовое приветствие, потом его сервер соединяет со свободным оператором, и начинается общение. Но часто бывает, что при плохой связи – звонок обрывает. Клиенту приходится заново перезванивать, слушать опять голосовое приветствие (которое порой может длиться до полуминуты), и попадает на оператора… на другого оператора. Приходится заново рассказывать о своей проблеме другому оператору и решать все по новой. Порой “качество” связи (мобильной) может упасть на столько, что приходится перезванивать по 5-10 раз !!!
Поэтому было решено сделать так, что бы при обрыве, при повторном звонке, от одного и того же клиента – звонок шел без очереди на того же оператора, без голосовых приветсвий и т.д.
Решение
Решение оказалось довольно простым.
Будем использовать существующую базу Asterisk’а – CDR. В этой базе хранятся все записи и входящих и исходящих звонках нашего телефонного сервера.
Открываем файл /etc/asterisk/extensions.conf и правим нужный нам входящий канал. Добавляем такой блок:
exten => 100,1,MYSQL(Connect connid IP_MYSQL ЛОГИН_MYSQL ПАРОЛЬ_MYSQL БАЗА_MYSQL) exten => 100,n,MYSQL(Query resultid ${connid} select dstchannel from cdr where clid like '%${CDR(src)}' and calldate like '${STRF TIME(${EPOCH},,%Y-%m-%d %H)}%') exten => 100,n,MYSQL(Fetch fetchid ${resultid} operator) exten => 100,n,GotoIf($["${operator}" = ""]?8:5) exten => 100,n,MYSQL(Clear ${resultid}) exten => 100,n,MYSQL(Disconnect ${connid}) exten => 100,n,Dial(SIP/${operator:-12:3},20,tT) exten => 100,n,Background(hello) exten => 100,n,Queue(support)
Что мы делаем
При входящем звонке, соединяемся с базой, делаем запрос, на поиск в таблице cdr в поле clid по номеру водящего звонка (переменная %${CDR(src)} ) и время укажем последний текущий час (переменная ${STRF TIME(${EPOCH},,%Y-%m-%d %H)}%) в поле calldate. Если звонок “новый” и еще не звонил в течении часа, то запрос вернет пустое значение в переменную operator, и звонок перекинется на проигрывание приветствия, и звонок поступит в очередь операторов, где на него ответит свободный оператор.
Пример cmd asterisk:
-- Executing [100@local-phones:1] MYSQL("SIP/INPUT_MTS-0000006c", "Connect connid localhost aster password asterisk") in new stack -- Executing [100@local-phones:2] MYSQL("SIP/INPUT_MTS-0000006c", "Query resultid 3 select dstchannel from cdr where clid like '%099xxxxxxx' and calldate like '2017-09-06 09%'") in new stack -- Executing [100@local-phones:3] MYSQL("SIP/INPUT_MTS-0000006c", "Fetch fetchid 4 operator") in new stack -- Executing [100@local-phones:4] GotoIf("SIP/INPUT_MTS-0000006c", "1?8:5") in new stack -- Goto (local-phones,100,8) -- Executing [100@local-phones:8] BackGround("SIP/INPUT_MTS-0000006c", "hello") in new stack -- <INPUT_MTS-0000006c> Playing 'hello.slin' (language 'ru') -- Executing [100@local-phones:9] Queue("SIP/INPUT_MTS-0000006c", "support") in new stack -- Started music on hold, class 'default', on SIP/INPUT_MTS-0000006c == Using SIP RTP CoS mark 5 -- SIP/971-0000006d is ringing -- SIP/971-0000006d answered SIP/INPUT_MTS-0000006c -- Stopped music on hold on SIP/INPUT_MTS-0000006c
Если же, клиент уже звонил и в базе cdr уже существует запись о том, что он звонил. Тогда в переменную operator вернется значение – SIP- номер оператора, с кем он разговаривал, и звонок уже вне очереди поступит напрямую к тому же оператору.
-- Executing [100@local-phones:1] MYSQL("SIP/INPUT_MTS-0000006a", "Connect connid localhost aster password asterisk") in new stack -- Executing [100@local-phones:2] MYSQL("SIP/INPUT_MTS-0000006a", "Query resultid 1 select dstchannel from cdr where clid like '%099xxxxxxx' and calldate like '2017-09-06 09%'") in new stack -- Executing [100@local-phones:3] MYSQL("SIP/INPUT_MTS-0000006a", "Fetch fetchid 2 operator") in new stack -- Executing [100@local-phones:4] GotoIf("SIP/INPUT_MTS-0000006a", "0?8:5") in new stack -- Goto (local-phones,100,5) -- Executing [100@local-phones:5] MYSQL("SIP/INPUT_MTS-0000006a", "Clear 2") in new stack -- Executing [100@local-phones:6] MYSQL("SIP/INPUT_MTS-0000006a", "Disconnect 1") in new stack -- Executing [100@local-phones:7] Dial("SIP/INPUT_MTS-0000006a", "SIP/971,20,tT") in new stack