Маршрутизация на основе времени и CallerID

Мы уже научились создавать интерактивные голосовые меню и управлять очередями вызовов. Это база. Но в реальной работе статичного распределения мало. Бизнесу нужна гибкость: ночной режим, приоритет для VIP-клиентов и защита от спама.

Чтобы реализовать такую логику, мы выйдем за рамки кнопок FreePBX и заглянем «под капот» — в диалплан Asterisk.

Как Asterisk видит время

Для принятия решений (например, отправить звонок на автоответчик после 18:00) сервер должен знать текущее время и уметь его форматировать. За это отвечает функция STRFTIME.

Внутри Asterisk время хранится в переменной ${EPOCH} — это количество секунд с 1 января 1970 года. Читать его в таком виде невозможно, поэтому мы переводим его в понятный формат.

; Получаем часы и минуты (например, 15:30)
Set(CURRENT_TIME=${STRFTIME(${EPOCH},,%H:%M)})
; Получаем день недели (1 — понедельник, 7 — воскресенье)
Set(CURRENT_DAY=${STRFTIME(${EPOCH},,%u)})

Использование Time в условиях делает сценарии динамичными. Как показано на Схеме 1, процесс всегда идет по цепочке: запрос системных данных → форматирование → сравнение с графиком.

Работа с данными абонента

Второй инструмент умной маршрутизации — обработка по CallerID. В Asterisk за это отвечает функция CALLERID(). У неё есть два ключевых параметра:

  1. CALLERID(num) — номер телефона (например, 79991234567).
  2. CALLERID(name) — имя абонента.

Важно: Всегда берите переменные в кавычки в условиях GotoIf. Если CallerID придет пустым (скрытый номер), Asterisk без кавычек выдаст ошибку и оборвет звонок. Правильно: "$[${CALLERID(num)}" = "79001112233"]".

Практика: Маршрутизация по времени

Настроим «Рабочее время» вручную в файле extensions_custom.conf. Используем оператор ветвления GotoIf.

[office-schedule-custom]
exten => s,1,NoOp(Проверка времени вызова)
; Условие: Пн-Пт (1-5) И время с 09:00 до 17:59
same => n,Set(WorkTime=$[${STRFTIME(,,%u)} < 6 & ${STRFTIME(,,%H%M)} >= 0900 & ${STRFTIME(,,%H%M)} < 1800])
same => n,GotoIf($["${WorkTime}" = "1"]?open:closed)

same => n(open),Log(NOTICE, Офис открыт)
same => n,Dial(PJSIP/100,20)
same => n,Hangup()

same => n(closed),Log(NOTICE, Офис закрыт)
same => n,Playback(vm-goodbye)
same => n,Hangup()

Если условие истинно (равно 1), вызов уходит на метку open, иначе — на closed.

VIP-клиенты и фильтрация

Маршрутизация по времени и номеру позволяет приоритизировать звонки. Можно создать «белый список», чтобы важные клиенты попадали сразу к менеджеру, минуя IVR.

МетодОписаниеПример
Точное совпадениеСравнение номера целикомПрямой перевод для директора 🎩
Проверка по маскеИспользование шаблоновЗвонки из СПб (_7812X.) — в питерский филиал
Проверка на пустотуНаличие номераБлокировка анонимов 🕵️

Пример VIP-фильтра:

[incoming-filter-custom]
exten => s,1,NoOp(Проверка VIP для ${CALLERID(num)})
; Если номер совпадает с VIP, идем на метку vip-line
same => n,GotoIf($["${CALLERID(num)}" = "79001112233"]?vip-line)
; Если номер начинается на 8800, сбрасываем (спам)
same => n,GotoIf($["${CALLERID(num):0:4}" = "8800"]?block)
same => n,Goto(from-internal,s,1)

same => n(vip-line),Dial(PJSIP/200,30)
same => n,Hangup()

same => n(block),Answer()
same => n,Wait(1)
same => n,Playback(ss-noservice)
same => n,Hangup()

Как не «сломать» диалплан

При ручной правке конфигов легко ошибиться там, где GUI подстраховал бы вас.

  • Забудьте про Macro. В современных версиях Asterisk макросы устарели. Используйте GoSub — это надежнее и современнее.
  • Кавычки — это закон. Всегда пишите "$[${VAR} = ...]". Это страховка от пустых значений.
  • Логируйте действия. Используйте NoOp или Log, чтобы в консоли было видно, по какой ветке пошел звонок.

Мы научились строить логику, которая делает АТС «умной». Но что делать, если вызов пошел не по плану? Чтобы не гадать, почему VIP-клиент слышит «гудбай», нужно научиться заглядывать в «мысли» системы.

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

Понравился урок?

Сохраните прогресс и получите персональный курс по любой теме — без форм и паролей

Продолжить в Telegram