Macro()

Вызывает заранее определённый макрос диалплана.

Macro(имя_макроса,arg1[,arg2...])
V
${MACRO_CONTEXT}
${MACRO_PRIORITY}
${MACRO_EXTEN}
V
[macro-имя_макроса]

Выполняет макрос, определённый в контексте macro-имя_макроса, переходя в добавочный номер s этого контекста и выполняя каждый шаг. Возвращается после того, как все шаги были выполнены.

Вызывающий добавочный номер, контекст и приоритет хранятся в переменных ${MACRO_EXTEN}, ${MACRO_CONTEXT} и ${MACRO_PRIORITY} соответственно. Аргументы arg1, arg2 и т.д. становятся в контексте макроса переменными ${ARG1}, ${ARG2} и т.д.

Макрос - очень полезная структура, разработанная во избежание повторов в диалплане. Также они облегчают задачу по внесению изменений в диалплан. Чтобы проиллюстрировать это, снова вернёмся к нашему примеру диалплана. Если вы помните, при внесении изменений для голосовой почты мы остановились на следующем варианте добавочного номера для Джона:

exten => 101, 1, Dial(${JOHN},10) exten => 101, n, GotoIf($["${DIALSTATUS}" = "BUSY"]?busy:unavail) exten => 101, n(unavail), VoiceMail(101@default) exten => 101, n, Hangup() exten => 101, n(busy), VoiceMail(101@default) exten => 101, n, Hangup()

Допустим, системой Asterisk пользуюся 100 абонентов. Для задания добавочных номеров пришлось бы многократно копирвать и вставлять фрагменты кода. Теперь предположим, что возникла необходимость немного скорректировать работу добавочных номеров. для этого пришлось бы вносить массу изменений, и почти наверняка при этом будут допущены ошибки.

Вместо этого можно определить макрос, содержащий список необходимых шагов, и затем сделать так, чтобы все добавочные номера использовали его. В этом случае корректировать придётся только макрос, и это обеспечит изменение всех элементов диалплана, ссылающихся на него.

Описание макроса

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

Описание макроса очень похоже на контексты. По сути, можно даже утверждать, что это действительно небольшие контексты с ограниченной функциональностью. Для описания макроса используется служебное слово "macro-", за которым следует имя макроса, и вся эта конструкция заключается в квадратные скобки:

[macro-voicemail]

Имена макросов должны начинаться со служебного слова "macro-". Это отличает их от обычных контекстов. Команды внутри макроса формируются практически аналогично всем остальным элементам диалплана; единственное ограничение - макросы используют только добавочный номер "s". Введём логику голосовой почты в макрос, заменяя по ходу добавочные номера на "s":

[macro-voicemail] exten => s, 1, Dial(${JOHN},10) exten => s, n, GotoIf($["${DIALSTATUS}" = "BUSY"]?busy:unavail) exten => s, n(unavail), VoiceMail(101@default) exten => s, n, Hangup() exten => s, n(busy), VoiceMail(101@default) exten => s, n, Hangup()

Для начала хорошо, но не идеально, потому что данный макрос предназначен только для Джона и номера его почтового ящика. Чтобы сделать его универсальным и подходящим не только для Джона, но и для всех его сослуживцев, воспользуемся другой возможностью макроса - его аргументами. Но прежде рассмотрим, как осуществлять вызов макроса в диалплане.

Вызов макроса из диалплана

Использовать макрос в диалплане нам поможет приложение Macro(). Оно вызывает заданный макрос и передаёт в него необходимые аргументы. Например, чтобы вызвать наш макрос голосовой почты из диалплана, можно сделать следующее:

exten => 101, 1, Macro(voicemail)
Приложение Macro() определяет также несколько специальных переменных. К
ним относятся:

${MACRO_CONTEXT}
	исходный контекст, в котором был вызван макрос.

${MACRO_EXTEN}
	исходный добавочный номер, в котором был вызван макрос.

${MACRO_PRIORITY}
	исходный приоритет, в котором был вызван макрос.

${ARGn}
	n-ный аргумент, передаваемый в макрос. Например, первым быь бы
	аргумент ${ARG1}, вторым - ${ARG2} и т.д.

Как говорилось ранее, описанный выше макрос был жёстко определён для Джона, тогда как должен быть универсальным. Давайте изменим его и вместо номера почтового ящика 101 будем использовать переменную ${MACRO_EXTEN}. Таким образом, при вызове макроса из добавочного номера 101 сообщения голосовой почты будут приходить в почтовый ящик 101; если макрос будет вызван из добавочного номера 102, сообщения пойдут в почтовый ящик 102 и т.д.:

[macro-voicemail] exten => s, 1, Dial(${JOHN},10) exten => s, n, GotoIf($["${DIALSTATUS}" = "BUSY"]?busy:unavail) exten => s, n(unavail), VoiceMail(${MACRO_EXTEN}@default) exten => s, n, Hangup() exten => s, n(busy), VoiceMail(${MACRO_EXTEN}@default) exten => s, n, Hangup()

Использование аргументов в макросе

Итак, мы уже близки к получению того макроса, какой нам нужен, осталось внести последнее изменение. Необходимо передать в макрос канал, по которому будут выполняться вызовы, потому что до сих пор в нём был жёстко прописан канал ${JOHN} (помните, мы определяли переменную JOHN как канал для звонков Джону?). Передадим канал как аргумент - и наш первый макрос будет готов:

[macro-voicemail] exten => s, 1, Dial(${ARG1},10) exten => s, n, GotoIf($["${DIALSTATUS}" = "BUSY"]?busy:unavail) exten => s, n(unavail), VoiceMail(101@default) exten => s, n, Hangup() exten => s, n(busy), VoiceMail(101@default) exten => s, n, Hangup()

Теперь, когда макрос готов, его можно использовать в диалплане. Вот как вызывается макрос для обеспечения функции голосовой почты для Джона, Джейн и Джека:

exten => 101, 1, Macro(voicemail,${JOHN}) exten => 102, 1, Macro(voicemail,${JANE}) exten => 102, 1, Macro(voicemail,${JACK})

И для 50 или более пользователей этот диалплан сохранит свою чёткость и организованность; для каждого пользователя просто будет создана строка со ссылкой на макрос, который может быть настолько сложным, насколько это необходимо. Может существовать даже несколько разных макросов для различных типов пользователей, таких как executives (руководство), courtesy_phones (телефоны справочной службы), call_center_agents (агенты центра обработки вызовов), analog_sets (аналоговые телефоны), sales_department (отдел продаж) и т.д.

Более сложная версия макроса может выглядеть примерно так:

[macro-voicemail] exten => s, 1, Dial(${ARG1},20) exten => s, n, Goto(s-${DIALSTATUS},1) exten => s-NOANSWER, 1, VoiceMail(${MACRO_EXTEN},u) exten => s-NOANSWER, n, Goto(incoming,s,1) exten => s-BUSY, 1, VoiceMail(${MACRO_EXTEN},u) exten => s-BUSY, n, Goto(incoming,s,1) exten => _s-., 1, Goto(s-NOANSWER,1)

Этот макрос использует замечательный побочный эффект приложения Dial(): Dial() задаёт переменную ${DIALSTATUS} как индикатор успешности или неуспешности вызова. В данном случае обрабатываются варианты NOANSWER (не отвечает) и BUSY (занято), а все остальные результаты трактуются как NOANSWER.

Поддержите проект, если он помог вам

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