Asterisk callback — обратные звонки

Звонить из роуминга дорого, поэтому мы заставим Астериск инициировать вызов на наш мобильный (вместе с которым мы греем ноги на пляже) и дать нам возможность позвонить «как будто мы дома». Хорошо, если наш тарифный план в роуминге дает возможность принимать входящие бесплатно, но сейчас речь не об этом.

Вводные данные: номер мобильного — 89007654321, номер Астериска — 84951230001, название провайдерского транка, с которого будет осуществлен обратный звонок — mytrunk1, название контекста, в котором находятся внутренние телефоны — localphones, название контекста, обрабатывающего входящие вызовы — default.

Для реализации используем проверку по условию GotoIf(), call-файлы и функцию DISA(). Call-файлы помещаются в /var/spool/asterisk/outgoing, но Астериск постоянно мониторит эту директорию и как только видит в ней файл с расширением .call — бросается его выполнять, поэтому создадим мы его в любой другой директории (в этом примере — в /var/spool/asterisk/). PS (у пользователя, от имени которого работает asterisk должны быть полные права на .call файл).

 
~$ cd /var/spool/asterisk
/var/spool/asterisk$ touch 89007654321.call
/var/spool/asterisk$ nano 89007654321.call

Наполняем файл 89007654321.call:

 
Channel: SIP/mytrunk1/89007654321
MaxRetries: 1
RetryTime: 30
WaitTime: 30
Context: callback-dialer
Extension: s
Callerid: autodialer
Account: autodialer
Priority: 1

Разберем значения основных опций:

    • Channel: : Канал, который будет использоваться при наборе.
    • MaxRetries: Количество повторных попыток набора. В нашем случае — если первая попытка окажется неудачной, Астериск повторит попытку ещё 1 раз.
    • RetryTime: Количество секунд между попытками вызова.
    • WaitTime: Количество секунд, которое Астериск ждёт ответа на вызов.
    • Account: Поле account code в CDR.
    • Context: Имя контекста, который обрабатывает вызов (в extensions.conf).
    • Extension: Название экстеншена в указанном контексте.
    • Priority: Номер операции экстеншена, с которого начинается обработка вызова после соединения.

Теперь идём в extensions.conf и добавляем контекст callback-dialer.

 
[callback-dialer]
exten => s,1,Answer()
exten => s,n,Wait(1)
exten => s,n,DISA(no-password,localphones)
exten => s,n,Hangup

Перечитываем диалплан (dialplan reload). На этом этапе Астериск ещё не умеет сам инициировать вызов, но уже можно проверить, что он дозванивается на мобильный и даёт возможность набрать номер также, как это делают внутренние абоненты. Для этого скопируем .call-файл в папку outgoing/

/var/spool/asterisk$ cp 89007654321.call outgoing/89007654321.call

Астериск обнаружит call-файл, найдёт в диалплане нужный контекст и совершит вызов. После поднятия трубки выполнится команда Answer(), затем Астериск подождет одну секунду, а следом включит функцию DISA(), т.е. в трубке появится гудок. В данном примере  DISA не будет запрашивать пароль, а вызванный абонент окажется в том же контексте, что и внутренние телефоны и сможет осуществить набор по тем же правилам, что и все остальные абоненты. После завершения вызова Астериск удалит call-файл из папки outgoing/ (именно поэтому мы использовали cp, а не mv).

Теперь нам предстоит научить диалплан распознавать номер, на который нужно совершать обратный вызов. Эту функцию можно повесить на внутренний добавочный, но мы ведь не хотим платить даже за минуту в роуминге — поэтому в начало контекста, обрабатывающий входящие вызовы, вставим проверку А-номера. Если А-номер совпадает с заданным — функция GotoIf() перебросит вызов на экстеншен callback с номером операции 1, в котором Астериск через функцию System() выполнит копирование созданного заранее call-файла и завершит входящий вызов, параллельно начиная исходящий.

 
[default]
...
exten => 84951230001,1,GotoIf($[${CALLERID(num)}=89007654321]?callback,1)
... 
exten => callback,1,System(cp /var/spool/asterisk/${CALLERID(num)}.call /var/spool/asterisk/outgoing/${CALLERID(num)}.call)
exten => callback,n,Hangup

Если же номер не совпал — продолжится его обычная обработка. А если для callback используется отдельный номер и нам не нужна дальнейшая обработка — можно вставить вторую метку и завершить звонок.

 [default]
...
exten => 84951230001,1,GotoIf($[${CALLERID(num)}=89007654321]?callback,1:reject)
exten => 84951230001,n(reject),Hangup
... 
exten => callback,1,System(cp /var/spool/asterisk/${CALLERID(num)}.call /var/spool/asterisk/outgoing/${CALLERID(num)}.call)
exten => callback,n,Hangup

В целом схема не сложна в реализации, если мобильных номеров много — можно прикрутить использование базы данных или чтение А-номеров из файла, а копирование созданных заранее call-файлов заменить на их автоматическую генерацию.

Leave a Reply

Ваш e-mail не будет опубликован. Обязательные поля помечены *