extensions.conf

Начинал писать еще 25 числа, накануне корпоратифффа, и в день рожденья одного человека. Вышло достаточно символично:)
Не судите строго последние пару месяцев совсем не пишется, нет вдохновения:(
Попытаюсь изложить основы «сердца нашей атс», а именно диалплана. По сути это логика работы нашей АТС, без нее какие бы устройства мы не подключали, толку будет мало. Кому интересно почитать о маршрутизации звонков, вилкамен дальше.

В самом начале файла мы можем подключить другой файл, к extensions.conf, делается это с помощью

 #INCLUDE <filename> 
Например:
#INCLUDE company1.conf

Диалплан состоит из четырех основных элементов: контекстов, добавочных номеров, приоритетов и приложений.
1.
Специальные контексты:
[general] содержит список общих настроек диалплана (о которых, вероятно, вам никогда не придется беспокоиться).
[globals] — работа с глобальными переменными

Контексты – это именованные группы добавочных номеров, которые выполняют несколько функций.
Контексты изолируют разные части диалплана, предотвращая возможность их взаимодействия. Добавочный номер, определенный в одном контексте, полностью изолирован от добавочных номеров другого контекста, если только взаимодействие не разрешено специально с помощью include=>.
Контексты различаются по именам. Имена контекстов заключаются в квадратные скобки ([ ]). Допустимыми символами для образования имени являются буквы от A до Z (верхнего и нижнего регистра), цифры от 0 до 9, дефис и символ подчеркивания(никогда не используйте пробелы!!!). Например, контекст для входящих вызовов выглядит так:
[incoming]
2.
Добавочные номера
В астериске это больше чем просто номер телефона привязанного к определенному телефону. Добавочный номер это набор действий которые выполнит наша атс, если вы его наберете.
Синтаксис
exten => имя,приоритет,приложение()
Пример
exten => 123,1,Answer()
Особые добавочные номера:
s(start) сюда попадают все входящие вызовы.
t(timeout) при построении IVR, если человек не выбрал ни один из пунктов меню он попадает сюда
i(invalid) при построении IVR, если человек выбрал несуществующий пункт меню он попадает сюда

3.
Приоритеты
Если наш номер состоит из более чем одного действия, то удобно использовать следующую конструкцию

exten => имя,приоритет,приложение()
same => n,приложение()

Можно использовать номера приоритетов, но я бы советовал использовать именно конструкцию приведенную выше. первая строка с приоритетом 1, а все последующие с приоритетом n(next).
Это значительно улучшит читабельность кода и его правку.
Также приоритетам можно задавать метку, для удобства понимания, и удобству перехода по диалплану
exten => 123,n(метка),приложение()
например
exten => 123,n(start),Answer()
4.
Приложения
Я думаю обьяснять, что это, зачем это, неуместно 🙂
Добавлю, что приложения бывают с параметрами(задаем в скобочках) и без параметров(пустые скобочки)
Вкратце остановимся на основных приложениях
Answer(к-во миллисекунд) приложение которое отвечает на поступивший вызов.
Progress() пытается предоставить информацию о состоянии вызова в исходный канал, иногда помогает решить проблему со странным поведением сигнализации(телефонной) НЕ ОХРАННОЙ!!!
Playback(имяфайла) играет существующий звуковой файл в канал, не слушая вводимые данные пользователем.
Hangup() кладем трубку:)
Background(имяфайла) воспроизводит записанный звуковой файл, но если пользователь нажимает кнопку (или последовательность кнопок) на клавиатуре телефона, оно прерывает воспроизведение и переходит к добавочному номеру соответственно нажатым цифрам.
WaitExten(секунд) ожидала ввода абонента, обычно используется с background()
Echo() будет возвращать все, что вы скажете.
SayDigits(число) говорит цифры из которых состоит число
Congestion() (перегрузка), воспроизводит «короткие гудки» (тональный сигнал перегрузки линии), сообщая абоненту, что дозвониться не удалось.
Goto(контекст,добавочный номер,приоритет) переход к определенной части диалплана
Можно указывать не все параметры. Если передается только один аргумент, Asterisk предположит, что это основной приоритет текущего добавочного номера. Если передано два аргумента, Asterisk будет трактовать их как добавочный номер и приоритет, к которым надо перейти в текущем контексте.

same => n,Goto(incoming,123,1)

Dial() набор определенного номера принимает четыре аргумента.
Первый – получатель вызова. (технологи/клиент)

Dial(DAHDI/[gGrR]канал_или_группа[/удаленный_добавочный_номер])
exten => 123,1,Dial(DAHDI/4) повзонит на аналоговый телефон подкл к 4му порту

Также можно звонить по нескольким каналам одновременно, объединяя получателей вызова с помощью символа амперсанда (&):

exten => 123,1,Dial(DAHDI/1&DAHDI/2&SIP/Jane) кто первый снял тому и дозвонились

также можно дозвонится абоненту который не был описан
Dial(технология/пользователь[:пароль]@удаленный_хост[:порт][/удаленный_добавочный_номер])

exten => 500,1,Dial(IAX2/[email protected]/s)

Второй аргумент – время ожидания, задаваемое в секундах. Если время ожидания задано, Dial() будет пытаться дозвониться по заданным номерам в течение этого количества секунд, а потом перейдет к следующему приоритету добавочного номера. Если не задано будет звонить вечно или пока не повесят трубку.
Третий аргумент — строка опций
m — играет музыка во время ожидания.
t — Разрешает ответившему пользователю перевести звонок.
T — Разрешает звонящему пользователю перевести звонок.
r — Генерировать сигналы вызова вызывающему абоненту, не передавая никаких аудиосигналов пока не получен ответ на звонок.

Четвертый аргумент — передается URL, сообщение которое будет выведено на экран телефона, если он поддерживает такую возможность.

Если не хотите задавать определенный аргумент просто поставьте пробел
Переменные возвращаемые приложением Dial():

• ${DIALEDTIME} -> время звонка, втч сигналов вызова
• ${ANSWEREDTIME} -> время реального звонка

• ${DIALSTATUS} Статус звонка может быть:
• CHANUNAVAIL
• CONGESTION
• NOANSWER
• BUSY
• ANSWER
• CANCEL
• DONTCALL
• TORTURE

• ${CAUSECODE} -> Сообщение о ошибке вызова

Более подробно о опциях и дргуих прелестях Dial():
http://www.asterisk.org/docs/asterisk/trunk/applications/dial

Read(variable[,filename[&filename2…]][,maxdigits][,option][,attempts][,timeout])
Объединяет в себе и background и waitexten
Считывает в указанную переменную, вводимую пользователем, DTMF последовательность, завершенную символом ‘#’, заданное число раз.

Параметры команды:

variable: имя переменной, в которой будет сохранена введенная пользователем последовательность.
filename: имя звукового файла (или файлов, начиная с версии 1.6) или тона, если используется опция ‘i’, проигрываемых пользователю до считывания последовательности.
maxdigits: максимально возможное число считываемых цифр. Считывание прекращается если введено максимальное количество цифр (в этом случае от пользователя не требуется нажатия кнопки ‘#’). Значение по умолчанию: 0 — нет лимита — команда ждет, пока пользователь не нажмет кнопку ‘#’. Любое значение меньше нуля приводят к такому же результату. Максимальное значение для этого параметра — 255.
option: дополнительные параметры, допустимые значения ‘s’, ‘i’, ‘n’:
‘s’ — указывает немедленно закончить выполнение команды, если линия связи не в соединенном состоянии.
‘i’ — вместо имени файла/файлов указаны «indication tone», из файла indications.conf.
‘n’ — для чтения цифр, даже если линия не в соединенном состоянии.
attempts: если больше 1, то указывается число попыток чтения последовательности, в том случае, если пользователь ничего не набрал.
timeout: Количество секунд ожидания ввода пользователя. Если значение больше нуля, то это значение будет использоваться вместо значения таймаута по умолчанию. (Начиная с версии 1.6, могут использоваться не целые значения).

Начиная с версии 1.6, данное приложение по завершении устанавливает значение переменной канала READSTATUS в соответствии с результатом своей работы, в одно из значений:
OK | ERROR | HANGUP | INTERRUPTED | SKIPPED | TIMEOUT

CURL(url[|post-data])
Позволяет получить контент по заданному URL.
url — URL, с которого получаем контент.
post-data — Необязательные данные, при использовании метода POST (GET — метод по умолчанию).
Возвращает полученную в результате работы строку/страницу.
Например:

exten => s,1,Set(foo=${CURL(http://somewhere.com/somepage.html?x=5&y=4)})

5.
Переменные
Установка значения переменной из диалплана осуществляется с помощью Set():

exten => 301,1,Set(VARRR=SIP/0000FFFF0001) 

Чтение значения переменной, обязательно используется конструкция типа ${}

same => n,Dial(${VARRR})

Имена переменных чувствительны к регистру, но хорошим тоном является указание названия переменной в верхнем регистре(КАПСОМ), учтите что некоторые имена такие как CHANNEL EXTEN зарезервированы системой!
Существует 3 типа переменных: Глобальные, переменные канала, системные
Глобальные переменные
Глобальные действуют по всему диалплану, задаются в контексте [globals]
[globals]
USER_A=DAHDI/4
Второй способ задания прямо во время выполнения
[employees]
exten => 124,1,Set(GLOBAL(GEORGE)=SIP/George)
Переменная канала
Переменная канала, действует только для текущего вызова, и доступны для каналов участвующих в нем.
Если команде Set присоединить спереди к имени переменной одиночный символ _ , то в этом случае эта переменная будет унаследована каналом, который будет создан основным каналом, например, при использовании команды Dial(Local/…); . Однажды будучи наследована, эта переменная не будет далее унаследована. В случае, если мы присоединим спереди к имени переменной два символа _, переменная будет наследоваться неограниченное число раз.
Устанавливается с помощью Set():

exten => 202,1,Set(MagicNumber=42)

Популярные переменные:
${EXTEN} выдать набранный номер
Часто переменную ${EXTEN} удобно использовать для удаления определенного количества цифр в начале добавочного номера. Это осуществляется с помощью синтаксиса Полный синтаксис переменной ${EXTEN} – ${EXTEN:x:y}, где x – начальное положение, а y – количество цифр, которое должно быть возвращено.
94169671111
• ${EXTEN:4:7} – будет возвращена строка 9671111.
• ${EXTEN:1} – отбросить первую цифру.
• ${EXTEN:-4:4} отрицательное значение говорит что считать нужно с конца, вернет 1111
• ${EXTEN:2:-4} начнет со второй цифры и отбросит последние 4 вернет 16967
• ${EXTEN:-6:-4} начнет с 6й цифры с конца и отбросит последние 4 цифры вернет 67

${CONTEXT} текущий контекст
${CALLERID(name)} CID имя
${CALLERID(num)} CID номер
${CALLERID(all)} имя и номер CID
${PRIORITY} Текущий приоритет
Список зарезервированных переменных канала:
https://wiki.asterisk.org/wiki/display/AST/Asterisk+Standard+Channel+Variables
Переменные среды
Переменные среды – это средство организации доступа к переменным среды UNIX из Asterisk. Для их использования служит функция диалплана ${ENV(var)},где var – переменная среды UNIX, на которую выполняется ссылка.

${ENV(LANG)} 
Set(ENV(LANG))=ru_RU

6.
ШАБЛОНЫ
НЕ ЗАБЫВАЙТЕ СТАВИТЬ _
Шаблоны диалплана всегда начинаются с _
X любое число от 0 до 9
Z число от 1 до 9
N число от 2 до 9
[15-7] Соответствует любому однозначному числу из заданного диапазона.В данном случае шаблон соответствует одиночной цифре 1, 5, 6 или 7.
. (точка) Универсальное соответствие; соответствует одному или более символам, любым.
! (восклицательный знак) Универсальное соответствие; соответствует нулю или более символам, любым.
НЕ УВЛЕКАЙТЕСЬ ! и . для Вашей же безопасности четко задавайте к-во символов в номере

7.
Перезагрузка диалплана

CLI> dialplan reload

ADD1. Небольшое дополнение с удобной записью приглашений(менюхи)

[prompts]
exten => s,1,Answer
exten => s,n,Set(step1count=0) ; Initialize counters

; If we get no response after 3 times, we stop asking
   same => n(beginning),GotoIf($[${step1count} > 2]?end)
   same => n,Read(which,prompt-instructions,3)
   same => n,Set(step1count=$[${step1count} + 1])

; All prompts must be 3 digits in length
   same => n,GotoIf($[${LEN(${which})} < 3]?beginning) 
   same => n,Set(step1count=0) ; We have a successful response, so reset our counters
   same => n,Set(step2count=0)

   same => n(step2),Set(step2count=$[${step2count} + 1])
   same => n,GotoIf($[${step2count} > 2]?beginning) ; No response after 3 tries

; If the file doesn't exist, then don't ask whether to play it
   same => n,GotoIf($[${STAT(f,${which}.wav)} = 0]?recordonly) 
   same => n,Background(prompt-tolisten)

   same => n(recordonly),Background(prompt-torecord)
   same => n,WaitExten(10) ; Wait 10 seconds for a response
   same => n,Goto(step2)

exten => 1,1,Set(step2count=0)
   same => n,Background(${which})
   same => n,Goto(s,step2)

exten => 2,1,Set(step2count=0)
   same => n,Playback(prompt-waitforbeep)
   same => n,Record(${CHANNEL(uniqueid)}.wav)

   same => n(listen),Playback(${CHANNEL(uniqueid)})
   same => n,Set(step3count=0)
   same => n,Read(saveornot,prompt-1tolisten-2tosave-3todiscard,1)
   same => n,GotoIf($["${saveornot}" = "1"]?listen)
   same => n,GotoIf($["${saveornot}" = "2"]?saveit)
   same => n,System(rm -f /var/lib/asterisk/sounds/${CHANNEL(uniqueid)}.wav)
   same => n,Goto(s,beginning)

   same => n(saveit),System(mv -f ${CHANNEL(uniqueid)}.wav ${which}.wav)
   same => n,Playback(prompt-saved)
   same => n,Goto(s,beginning)

Комментарии: