Использование макросов и подпрограмм для модульности
Мы уже умеем создавать базовые маршруты и настраивать PJSIP-транки. Но по мере роста АТС файл конфигурации превращается в «простыню» из повторяющегося кода. Если вам нужно добавить запись разговора или проверку черного списка для ста входящих номеров, копирование строк — это прямой путь к ошибкам.
Чтобы этого избежать, используйте принцип модульности диалплана. Мы выносим общую логику в отдельный блок и вызываем его из любого места системы.
Прощаемся с макросами
В старых версиях Asterisk для этого использовали приложение Macro(). В современном Asterisk (актуальном в 2026 году) макросы удалены из ядра. Им на смену пришла более мощная концепция — подпрограмма.
Подпрограмма — это именованный фрагмент кода, который выполняет задачу и возвращает управление в точку вызова. Главный инструмент здесь — приложение GoSub.
Анатомия GoSub
Приложение GoSub работает по принципу стека: Asterisk запоминает текущую позицию, «прыгает» в подпрограмму, выполняет её и возвращается точно к следующему шагу основного сценария.
Синтаксис:
GoSub(контекст,экстеншен,приоритет(аргумент1,аргумент2,...))
Сравним подходы на примере: перед соединением нужно проиграть приветствие и включить запись.
Плохо: избыточный код
[from-internal]
exten => 101,1,Playback(welcome)
exten => 101,n,MixMonitor(${UNIQUEID}.wav)
exten => 101,n,Dial(PJSIP/101)
exten => 102,1,Playback(welcome)
exten => 102,n,MixMonitor(${UNIQUEID}.wav)
exten => 102,n,Dial(PJSIP/102)
Хорошо: модульный подход
[from-internal]
exten => 101,1,GoSub(sub-pre-call,s,1(welcome))
exten => 101,n,Dial(PJSIP/101)
exten => 102,1,GoSub(sub-pre-call,s,1(hello))
exten => 102,n,Dial(PJSIP/102)
[sub-pre-call]
exten => s,1,Playback(${ARG1})
exten => s,n,MixMonitor(${UNIQUEID}.wav)
exten => s,n,Return()
Как показано на Схеме 1, вызов GoSub создает временное ответвление логики, которое всегда завершается возвратом в основную ветку.
Аргументы и возврат управления
Внутри подпрограммы данные принимаются через переменные ARG1, ARG2 и так далее. Это делает код универсальным.
Ключевой элемент — приложение Return. Без него Asterisk не поймет, что нужно вернуться назад, и либо продолжит выполнять код по порядку, либо оборвет вызов 🧱
Для пользователей FreePBX: размещайте свои подпрограммы только в файле
extensions_custom.conf. Иначе графический интерфейс сотрет их при первом же нажатии «Apply Config».
Практический кейс: Универсальный фильтр
Создадим подпрограмму для проверки «черного списка». Вместо того чтобы прописывать условия для каждого транка, используем один блок:
[sub-check-blacklist]
exten => s,1,NoOp(Проверка номера ${CALLERID(num)})
exten => s,n,GotoIf($["${CALLERID(num)}" = "12345"]?reject:allow)
exten => s,n(reject),Hangup()
exten => s,n(allow),Return()
Теперь достаточно вызвать GoSub(sub-check-blacklist,s,1) в начале любого маршрута. Если номер в списке — вызов завершится. Если нет — подпрограмма вернет управление, и Asterisk пойдет дальше.
Подпрограммы — фундамент гибкой АТС. Чтобы сделать их еще мощнее, нужно научиться передавать данные между разными частями системы. В следующей теме мы разберем работу переменных и научимся управлять логикой на основе данных вызова.
Понравился урок?
Сохраните прогресс и получите персональный курс по любой теме — без форм и паролей
Продолжить в Telegram