Меню переадресации для Asterisk
Администратор, 24.11.2015Asterisk - IP-АТС с крайне широкими возможностями. Однако, это скорее "двигатель для постройки любого автомобиля", нежели мощнейший суперкар, в смысле того, что все функции, которые в нее заложены, администратор вынужден настраивать с нуля на каждой новой инсталяции, то есть мы не имеем никакого pre-defined кода, как это сделано, скажем, во FreePBX.
С одной стороны - это крайне удобно, потому что вы не завязаны на использование диалплана, который придуман разработчиками и имеете полнейшую свободу выбора в настройке, тем самым пользуетесь всеми преимуществами настоящего open source решения. Однако с другой стороны, процесс первичного развертывания АТС затягивается из-за того, что вы вынуждены писать диалплан с нуля в каждой новой системе.
Что же делать? Наиболее верным решением является использование некоторых функциональных блоков, которые перетекают у вас от инсталляции к инсталляции. Одной из такой фич несомненно является опция установки переадресации абонентом, ведь не принципиально, какие внешние условия наложены на вашу систему (DAHDI, SIP и тд), этот функционал будет использоваться везде.
Нами были сделаны два варианта реализации:
Вариант 1. Реализация установки переадресации с помощью интерактивного голосового меню и взаимодействия с пользователем:
extensions.conf
exten => 4567,1,Answer() ;абонент набирает номер 4567
same => n,Playback(/var/lib/asterisk/sounds/redir/4) ; приветствие системы
same => n,Set(ACTNUM=${DB(tempred/${CALLERID(num)})}) ; кладем в переменную ACTNUM номер, введенный пользователем при условии его существования
same => n,NoOp(${ACTNUM})
same => n,GotoIf(${DB_EXISTS(tempred/${CALLERID(num)})}?yes:no) ;если есть уже номер для переадресации - идем к метке (yes), нет - (no)
same => n(no),Playback(/var/lib/asterisk/sounds/redir/5) ; просим пользователя ввести номер
same => n,Read(TMPNUM) ; читаем этот номер
same => n,Set(DB(tempred/${CALLERID(num)})=${TMPNUM}) ; кладем в базу
same => n,Set(ACTNUM=${DB(tempred/${CALLERID(num)})}) ; кладет в переменную ACTNUM номер, введенный пользователем
same => n,Playback(/var/lib/asterisk/sounds/redir/6) ; говорим, что номер установлен
same => n,SayDigits(${ACTNUM}) ;проговариваем номер
same => n,Wait(1)
same => n,Playback(vm-goodbye) ; прощаемся с абонентом
same => n,Hangup()
same => n(yes),GoTo(redir-yes,s,1) ; идем в другой контекст
exten => _4567XXX,1,Answer() ; проверка статуса перадресация для внутренних абонентов, в моем случае используются трехзначные номера ХХХ
same => n,Set(ACTNUM=${DB(tempred/${CALLERID(num)})}) ;см выше
same => n,Set(EXIST=${ISNULL(${ACTNUM})}) ;Проверяем существование номера
same => n,GotoIf($["${EXIST}"="1"]?null:notnull) ;условный переход по существованию номера для переадресации
same => n(null),Playback(/var/lib/asterisk/sounds/redir/7);;Переадресация не установлена
same => n,Hangup()
same => n(notnull),Playback(/var/lib/asterisk/sounds/redir/8);Установлена переадресация на номер
same => n,SayDigits(${ACTNUM}) ; проговариваем номер, на который установлена переадресация
same => n,Hangup()
[redir-yes]
exten => s,1,Answer()
same => n,Playback(/var/lib/asterisk/sounds/redir/1);;У вас установлена переадресация на номер
same => n,SayDigits(${ACTNUM}) ; проговариваем номер
same => n,Background(/var/lib/asterisk/sounds/redir/2);; Для удаления переадресации нажмите один
same => n,WaitExten(5) ;ждем пока абонент введет цифру один
same => n,Hangup()
exten => 1,1,Playback(/var/lib/asterisk/sounds/redir/3) ;;переадресация удалена. до свидания
same => n,NoOp(${DB_DELETE(tempred/${CALLERID(num)})}) ;удаляем номер из базы
same => n,Hangup()
И непосредственно диалплан для вызова внутреннего номера:
exten => _XXX,1,NoOp(Call from ${CALLERID(num)} to ${EXTEN})
same => n,Set(ACTNUM=${DB(tempred/${EXTEN:-3})})
same => n,Set(EXIST=${ISNULL(${ACTNUM})})
same => n,GotoIf($["${EXIST}"="1"]?null:notnull)
same => n(null),Dial(SIP/${EXTEN},40,Tt)
same => n,Hangup()
same => n(notnull),Set(length=${LEN(${ACTNUM})})
same => n,NoOp(${length})
same => n,GotoIf($["${length}" = "3"]?local:long)
same => n(local),Dial(SIP/${ACTNUM},60,Tt)
same => n,Hangup()
same => n(long),GoTo(from-internal-out,${ACTNUM},1)
same => n,Hangup()
Вариант 2. Установка переадресации через кодовые команды (наподобие USSD-запросов мобильных телефонов)
exten =>_*1*1*X.,1,NoOp(CCF activated) ;установка условной переадресации
same => n,Set(cond=${EXTEN:3:1}) ;кладем переменную условия, 1 - условная, 0 - безусловная
same => n,Set(tmpnum=${EXTEN:5}) ; номер для переадресации
same => n,NoOp(${cond})
same => n,NoOp(${tmpnum})
same => n,Set(DB(condi/${CALLERID(num)})=${cond}) ; кладем в базу условие
same => n,Set(DB(tempred/${CALLERID(num)})=${tmpnum}) ; кладем в базу номер
same => n,Set(ACTNUM=${DB(tempred/${CALLERID(num)})}) ; делаем переменную, в которую кладем номер переадресации
same => n,Playback(/var/lib/asterisk/sounds/redir/ccf_activated) ; проговариваем, что установлена переадресация
same => n,SayDigits(${tmpnum}) ; говорим номер переадресации
same => n,Hangup()
;аналогичная логика для написанного выше
exten =>_*1*0*X.,1,NoOp(UCF activated)
same => n,Set(cond=${EXTEN:3:1})
same => n,Set(tmpnum=${EXTEN:5})
same => n,NoOp(${cond})
same => n,NoOp(${tmpnum})
same => n,Set(DB(condi/${CALLERID(num)})=${cond})
same => n,Set(DB(tempred/${CALLERID(num)})=${tmpnum})
same => n,Set(ACTNUM=${DB(tempred/${CALLERID(num)})})
same => n,Playback(/var/lib/asterisk/sounds/redir/ucf_activated)
same => n,SayDigits(${tmpnum})
same => n,Hangup()
;убираем переадресацию
exten =>_*0!,1,NoOp(any CF deactivated)
same => n,NoOp(${DB_DELETE(tempred/${CALLERID(num)})})
same => n,NoOp(${DB_DELETE(condi/${CALLERID(num)})})
same => n,Playback(/var/lib/asterisk/sounds/redir/cf_off)
same => n,Hangup()
;;cf checking
;проверка статуса переадресации
exten => _*2XXX,1,NoOp(CF Checking)
same => n,Answer()
same => n,Set(tellnum=${DB(tempred/${EXTEN:2})})
same => n,Set(EXIST=${ISNULL(${tellnum})})
same => n,GotoIf($["${EXIST}"="1"]?null)
same => n,Playback(/var/lib/asterisk/sounds/redir/cf_activated)
same => n,SayDigits(${tellnum})
same => n,Hangup()
same => n(null),Playback(/var/lib/asterisk/sounds/redir/cf_off)
same => n,Hangup()
И непосредственно диалплан для вызова внутреннего номера:
exten => _XXX,1,NoOp(Call from ${CALLERID(num)} to ${EXTEN})
same => n,Set(actcon=${DB(condi/${EXTEN})})
same => n,NoOp(ACTUAL CONDITION = ${actcon})
same => n,Set(actnum=${DB(tempred/${EXTEN})})
same => n,NoOp(ACTUAL NUMBER = ${actnum})
same => n,GotoIf($["${actcon}"="1"]?ccf)
same => n,GotoIf($["${actcon}"="0"]?ucf)
same => n,Dial(SIP/${EXTEN},40,Tt)
same => n,Hangup()
same => n(ccf),Dial(SIP/${EXTEN},10,Tt)
same => n,Dial(SIP/${EXTEN}&SIP/provider/${actnum},60,Tt)
same => n,Hangup()
same => n(ucf),GoTo(from-internal-out,${actnum},1)
same => n,Hangup()