Создание переадресаций по расписанию
Многие используют переадресации на мобильные или стационарные телефоны, возможно еще на автоответчик. Однако иногда требуется создать не абсолютную переадресацию, а переадресацию по времени. Например переадресация по пятницам. Для реализации используем запись расписания в базу данных, в которой будем указывать номер на котором необходимо включать переадресацию, время в которое она должна работать и номер на который […]
Многие используют переадресации на мобильные или стационарные телефоны, возможно еще на автоответчик. Однако иногда требуется создать не абсолютную переадресацию, а переадресацию по времени. Например переадресация по пятницам.
Для реализации используем запись расписания в базу данных, в которой будем указывать номер на котором необходимо включать переадресацию, время в которое она должна работать и номер на который переадресовывать вызов.
Пример заполнения даты и времени можно посмотреть в базе asterisk, таблице timegroups_details.
Соответственно необходимо создать свою таблицу с необходимыми полями:
Для создания расписания необходимо реализовать веб-интерфейс управления, для достпа к нему создадим виртуальный хост в конфигах apache.
В корне указанной директории создаем файл index.php, который будет стартовой страницей.
На странице создаем поля ввода номеров и интервала дней месяца, недели и времени, которые должны быть обязательно заполнены (required).

Реализуем обработчик нажатия (для теста можно вывести все, что отправляется через POST запрос:
Сам обработчик дополним проверкой совпадений введенных значений и пустых значений:
Как видно из базовой таблицы freepbx нам необходимо указывать дату и время в определенном формате. Выведем в необходимом виде, чтобы проверить правильность заполнения:

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

Настройка голосового меню (IVR) на Asterisk
Интерактивное голосовое меню, или голосовое дерево, IVR меню или просто, IVR используется для возможности позвонившему подключиться к конкретному сотруднику компании или соединиться с линией поддержки определенной категории. Также, с помощью IVR можно получить необходимую информацию без ответа со стороны оператора, выбрав интересующую информацию. Другими словами, это система, взаимодействующая с абонентом и реагирующая на его команды.
Принцип настройки
IVR настраивается в плане набора Aterisk (dialplan) — в конфигурационном файле extensions.conf.
Сначала мы проигрываем запись с голосовым приветствием и предложением ввести номер в тональном режиме. В том же файле мы обрабатываем вводимую информацию, перекидывая абонента на другие диалплан, очередь или конкретного сотрудника.
Базовая настройка
Открываем конфигурационный файл:
[outcaling]
.
exten => 222,1,Answer()
same => n,Background(basic-pbx-ivr-main)
exten => _XXX,1,Dial(SIP/$
* в данном примере, при звонке на номер 222 нам проигрывается голосовая запись basic-pbx-ivr-main (из каталога /var/lib/asterisk/sounds/ ). Когда мы вводим трехзначный добавочный номер, нас соединяет Asterisk с этим номером. Предполагается, что наш основной диалплан называется outcaling.
Перезапускаем настройки диалплана:
Голосовое дерево
Теперь настроим возможность выбора отдела, с которым абонент захочет соединиться.
Приводим наш диалплан к следующему виду:
exten => 333,1,Answer()
exten => 333,2,Background(basic-pbx-ivr-main)
exten => 333,3,WaitExten(5)
exten => 1,1,Goto(managers,s,1)
exten => 2,1,Goto(support,s,1)
[managers]
exten => s,1,Ringing
same => n,Wait(1)
same => n,Background(/var/lib/asterisk/sounds/wav/managers)
same => n,Waitexten(5)
exten => 1,1,Dial(SIP/201)
exten => 2,1,Dial(SIP/202)
exten => 0,1,Goto(outcaling,333,1)
[support]
exten => s,1,Ringing
same => n,Wait(1)
same => n,Background(/var/lib/asterisk/sounds/wav/support)
same => n,Waitexten(5)
exten => 1,1,Dial(SIP/101)
exten => 2,1,Dial(SIP/102)
exten => 0,1,Goto(outcaling,333,1)
Перечитываем настройки диалплана:
Таймаут по времени ожидания и неправильные действия
Добавим обработку неправильно введенной цифры и превышение времени ожидания. В вышеуказанном примере просто происходит отбой звонка.
Данное поведения указывается в диалплане с помощью ключей t и i. Добавим их в наш конфиг:
exten => 333,1,Answer()
same => n,Background(basic-pbx-ivr-main)
same => n,WaitExten(5)
exten => 1,1,Goto(managers,s,1)
exten => 2,1,Goto(support,s,1)
exten => t,1,Dial(SIP/101)
exten => i,1,Background(invalid)
same => n,Goto(outcaling,333,3)
* где t,1,Dial(SIP/101) — позвонить по номеру 101, если будет превышен таймаут ожидания; i,1,Background(invalid) — сообщить о том, что введен неправильный номер.
Если не работает донабор
Если во время тестирования возникнут проблемы при донаборе внутреннего номера, необходимо проверить режим DTMF. В двух словах, это аналоговый сигнал для набора телефонного номера. Он может отправляться разными способами: inband, rfc2833 / rfc4733, info. При возникновении проблем, попробуйте в настройках клиента выставить rfc2833 или inband.
На стороне Asterisk также можно настроить sip-пир на определенный способ передачи DTMF:
* настройка может быть задана на глобальном уровне, уровне шаблона или для конкретного пира.
Примеры настроек
Рассмотрим некоторые дополнительные примеры настроек диалплана, которые будут полезны при конфигурировании автоинформатора.
1. Расписание
а) Мы можем вызывать различные контексты диалплана в зависимости от времени суток. Для этого вызываем приложение GotoIfTime:
* в данном примере при звонке с 08 до 20:00 в будние дни нас перекинет в контекст working_hours, иначе — в not_working_hours.
б) Чтобы во время нашей работы в рабочие часы мы могли проверить работу автоинформатора в нерабочее время, можно задать исключение для определенного номера:
* в данном примере мы добавили строку с проверкой исходящего номера. Если мы звоним с телефона 9062504869, то звонок всегда перекидывать в контекст not_working_hours.
в) Также мы можем менять направление диалплана в зависимости от времени:
exten => s,1,NoOp(Разные пути в зависимости от времени и дня)
same => n,GotoIfTime(10:00-13:59,mon-fri,*,*?true:false)
same => n(true),NoOp(TRUE)
same => n,Background(wav/true)
same => n,Hangup()
same => n(false),NoOp(FALSE)
same => n,Background(wav/false)
same => n,Hangup()
* в данном примере мы проиграем файл wav/true, если звонок будет совершен в будние дни с 10 до 14, и wav/false — в любое другое время.
Голосовой автоинформатор даты и времени, приятным женским голосом, русским языком, на базе asterisk? Легко
В преддверии выходных не чем себя занять, так как по регламенту не позволены грандиозные настройки? На старом, заброшенном » target=»_blank»>сервере запылился asterisk? Абоненту нечем тестировать телефонную линию? Для тех, кому не с кем поговорить и для тех, кто потерялся во времени.
В этой публикации мы будем делать акцент на падежи порядковых числительных, так как произносимый текст должен быть связан и не резать слух. Попытаемся добиться следующего произношения:
Текущее время пятнадцать часов, двадцать одна минута, двадцать секунд. Сегодня среда, пятнадцатое октября.
Текущее время один час, тридцать пять минут, десять секунд. Сегодня четверг, шестнадцатое октября.
Для простоты и прозрачности внедрения мы не будем пользоваться AGI и попросим железную леди сообщать нам дату и время, по большому счету, поработав лишь с dialplan`ом и say.conf`ом. И если ваш asterisk до сих пор не говорит по-русски — не беда, этому мы его научим. Кому стало интересно, добро пожаловать под хабракат.
Который час?
Думаю, не стоит даже упоминать, что ваш » target=»_blank»>сервер должен знать точное время, опираясь, например, на NTP.
Время на » target=»_blank»>серверах имеет свойство рассинхронизироваться, если его не подводить. Пакет ntp потребуется в любом случае. Для себя я выбрал первый вариант с ntpd, так как другие мои » target=»_blank»>сервера подводят время внутри сети.
Вариант №1. Добавляем » target=»_blank»>сервера по вкусу, в зависимости от региона, в котором находится asterisk. Чем быстрее отклик от » target=»_blank»>сервера времени, тем точнее оно выставится, при прочих равных. Я выберу российский пул.
Проверяем, что демон слушает нужные порты:
Если есть желание раздавать время своим » target=»_blank»>серверам, не забудьте проверить файервол, порт UDP/123. Правило должно встать до завершающего REJECT`а. Не забудьте сохранить.
Вариант №2. Для разовой корректировки подойдет утилита ntpdate, входящая в тот же пакет ntp. Такой вариант годен, если раздача времени с » target=»_blank»>сервера не планируется.
Можно добавить в cron:
Обучим леди русскому языку
Далее предположим, что asterisk установлен, но если это не так, то есть многоматериалов на эту тему. Так же будем считать, что первоначальная настройка хотя бы одного SIP-телефона или софтфона уже произведена.
Создадим каталог, если его нет
Загружаем русские звуки:
Копируем на свое место:
Посмотреть, какие фразы записаны можно в следующих файлах:
sip.conf
Укажем asterisk`у, использовать русский язык для SIP, добавив language=ru в [general]:
say.conf
Контекст [ru-base] в say.conf имеет завершающий (!) восклицательный знак в скобках означает, что это шаблон, который мы в дальнейшем включаем в [ru]
Попробуем разобрать одно правило. Первое, на что стоит обратить внимание, это символы X Z N. Они интерпретируются asterisk`ом как специальные и если эти литеры фигурируют в названии правила чтения, их следует взять в квадратные скобки, например mo[n]th.
Синтаксис достаточно прост и правило совпадает, если входные данные XX — две любые цифры. Проигрываем файл digits/mon-(XX-1), где (XX-1) это арифметическая операция. При X=02 (да, «переваривает» даже такие цифры, что нам очень поможет), 02-1=1, digits/mon-1: «Февраля».
Отдельно стоит упомянуть секунды. Во-первых, в записанных фразах есть только единственная запись: «секунд». Это значит, что на вход этой функции должны приходить округленные данные, например 0, 10, 20, и так далее. А во-вторых, по мнению автора, это облегчит восприятие полученной информации.
extensions.conf
В контексте [informer_100] стоит объяснить строчку, где мы в переменной FreezeEPOCH добавляем 15 секунд к unixtime. Сделано это для компенсации времени, потраченного на проигрывание файлов, предшествующих секундам.
$
$
$
$
Возможно, кто-то из читателей захочет самостоятельно сформировать правила, например, для прочтения рублей. Объема готовых примеров должно быть достаточно, чтобы справиться с этой задачей. А для проверки произношения можно воспользоваться нижеприведенным dialplan`ом.
Бонус: прослушать готовый результат в живую можно по телефону:
ИТ База знаний
Полезно
— Онлайн генератор устойчивых паролей
— Онлайн калькулятор подсетей
— Руководство администратора FreePBX на русском языке
— Руководство администратора Cisco UCM/CME на русском языке
— Руководство администратора по Linux/Unix
Навигация
Серверные решения
Телефония
FreePBX и Asterisk
Настройка программных телефонов
Корпоративные сети
Протоколы и стандарты
Временные группы FreePBX13
Маршрутизация вызова в зависимости от календаря
Временная группа (Time Group) – набор временных диапазонов, который можно применять к условиям проверки вызовов. Диапазон настраивается с учетом минут, часов, дней недели, месяца или года. Каждая временная группа может иметь множество временных диапазонов, каждый из которых будет проверяться. Как мы писали ранее, временная группа ассоциируется с временным условием (Time Condition), которое определяет направление для вызова при условии вхождения в указанный временной диапазон, или наоборот, выход за его рамки. Отметим, что временная группа так же может быть назначена на исходящий маршрут, чтобы лимитировать его использование по времени.
Базовый курс по Asterisk
Мы собрали концентрат всех must have знаний в одном месте, которые позволят тебе сделать шаг вперед на пути к экспертному владению Asterisk
Приступим к настройке. Для этого, в меню Applications, выберем Time Groups

Рассмотрим основные параметры настройки временной группы:
Например, указанная ниже настройка обеспечит настройку вызовов с понедельника по пятницу, с 10:00 до 19:00:

Праздничные дни
Чтобы настроить конкретный праздничный день, необходимо в поле Month Day start и Month Day finish выбрать один и тот же день. Например, вот настройка для праздника 8 марта:

По окончанию настройки, нажмите Save и затем Apply Config
Базовый курс по Asterisk
Мы собрали концентрат всех must have знаний в одном месте, которые позволят тебе сделать шаг вперед на пути к экспертному владению Asterisk
Погружение в диалплан
Для списка всех способов, по которым технология не улучшила
качество жизни, пожалуйста, нажмите три.
Выражения и манипуляции с переменными
По мере того, как мы начинаем погружаться в более глубокие аспекты диалплана, настало время познакомить вас с несколькими инструментами, которые значительно повысят мощь, которую вы можете использовать в своем диалплане. Эти конструкции добавляют невероятный интеллект к вашему диалплану, позволяя ему принимать решения на основе разных критериев, которые вы определяете. Наденьте свой мыслительный колпачок, и давайте начнем.
В этой главе мы используем лучшие практики, которые были разработаны на протяжении многих лет в создании диалплана. Основная из них — вы заметите, что все первые приоритеты начинаются с приложения NoOp(), что означает просто «Нет операции»; ничего функционального не произойдет. Другая заключается в том, что все следующие строки начинаются с same => n, что является ярлыком, который гласит: «Использовать то же расширение, которое было только что определено ранее». Кроме того, отступ составляет четыре пробела.
Базовые выражения
Выражения представляют собой комбинации переменных, операторов и значений, которые вы объединяете вместе для получения результата. Выражение может проверять значения, изменять строки или выполнять математические вычисления. Допустим, у нас есть переменная с именем COUNT. На простом русском языке два выражения, использующие эту переменную, могут быть «COUNT плюс 1» и «COUNT разделить на 2.». Каждое из этих выражений имеет конкретный результат или значение в зависимости от значения данной переменной.
В Asterisk выражения всегда начинаются со знака доллара и открытой квадратной скобки и заканчиваются закрывающей квадратной скобкой, как показано здесь:
Таким образом, мы могли бы написать два наших примера:
Когда Asterisk встречает выражение в диалплане, он заменяет всё выражение полученным значением. Важно отметить, что это происходит после подстановки переменной. Чтобы продемонстрировать, давайте рассмотрим следующий код: 1
same => n,Set(NEWCOUNT=$[$
Во втором приоритете мы присваиваем значение 3 переменной с именем COUNT.
В третьем приоритете задействовано только одно приложение Set() — но на самом деле происходят три вещи:
Попробуйте в своем диалплане.
Операторы
Когда вы создаете диалплан Asterisk, вы действительно пишете код на специализированном языке сценариев. Это означает, что диалплан Asterisk, как любой язык программирования, распознает символы, называемые операторами, которые позволяют вам манипулировать переменными. Давайте посмотрим на типы операторов, которые доступны в Asterisk:
Булевы (логические) операторы
Эти операторы оценивают «истину» утверждения. В вычислительных терминах это в основном относится к тому, является ли оператор чем-то или нет (отличным от нуля или нулевым, истинным или ложным, включенным или выключенным и т.д.). Булевы операторы:
Этот оператор (называемый оператором «или» или «пайп»(труба)) возвращает оценку expr1, если она истинна (не пустая строка, не нуль). В противном случае он возвращает оценку expr2.
Этот оператор (называемый «и») возвращает оценку expr1, если оба выражения истинны (т. е. ни одно выражение не оценивает пустую строку или ноль). В противном случае он возвращает ноль.
expr1 <=, >, >=,
Некоторая дополнительная информация об особенностях операторов регулярных выражений в Asterisk содержится на веб-сайте Walter Doekes.
Если шаблон не содержит подвыражения, возвращается количество совпадающих символов. Это будет 0, если совпадение не выполнено. Если шаблон содержит подэлемент — \(…\) — возвращается строка, соответствующая \1. Если совпадение не выполняется, возвращается пустая строка.
Этот оператор работает так же, как оператор : кроме того, что он не привязан к началу.
В версии Asterisk 1.0 синтаксический анализатор был довольно прост, поэтому потребовалось, чтобы вы поместили хотя бы один пробел между оператором и любыми другими значениями. Следовательно, следующее, возможно, не сработало, как ожидалось:
Оно присвоило переменной TEST строку 2+1 вместо значения 3. Чтобы исправить это, мы помещаем пробелы вокруг оператора, например:
exten => 234,1,Set(TEST=$[2 + 1])
Это больше не требуется в текущих версиях Asterisk, поскольку парсер выражений стал более упрощенным в этих сценариях. Однако, для удобства чтения, мы по-прежнему рекомендуем включать пробелы вокруг ваших операторов.
Чтобы присоединить текст в начало или конец переменной, просто поместите их вместе, например:
Функции диалплана
Функции диалплана позволяют добавлять больше мощи вашим выражениям; вы можете рассматривать их как интеллектуальные переменные. Функции диалплана позволяют вычислять длины строк, даты и время, контрольные суммы MD5 и т. д. все из выражения диалплана.
Вы увидите использование Playback(silence/1) во всех примерах этой главы. Мы делаем это, так как оно ответит на эту строку, если на нее еще не ответили, и воспроизведёт некоторую тишину на линии. Это позволяет другим приложениям, таким как SayNumber() воспроизводить аудио без пробелов.
Синтаксис
Функции диалплана имеют следующий базовый синтаксис:
Вы ссылаетесь на имя функции так же, как на имя переменной, но вы ссылаетесь на значение функции с добавлением знака доллара, открывающейся фигурной скобкой и закрывающейся фигурной скобкой:
Функции также могут инкапсулировать другие функции, например:
Как вы, наверное, уже выяснили, вы должны быть очень осторожны, чтобы убедиться, что у вас есть все круглые скобки и фигурные. В предыдущем примере мы обозначили открывающие круглые скобки и фигурные скобки цифрами и их соответствующими закрывающими аналогами с одинаковыми номерами.
Примеры функций диалплана
Функции часто используются вместе с приложением Set() для получения или установки значения переменной. В качестве простого примера рассмотрим функцию LEN(). Эта функция вычисляет длину строки аргумента. Давайте вычислим длину строки переменной и вернем ее вызывающей стороне:
Давайте рассмотрим еще один простой пример. Если бы мы хотели установить один из различных тайм-аутов канала, мы могли бы использовать функцию TIMEOUT(). Функция TIMEOUT() принимает один из трех аргументов: absolute, digit и response. Чтобы установить тайм-аут с помощью функции TIMEOUT(), мы могли бы использовать приложение Set(), например:
Полный список доступных функций можно найти, набрав core show functions в интерфейсе командной строки Asterisk.
Условное ветвление
Теперь, когда вы немного узнали о выражениях и функциях, пришло время их использовать. Используя выражения и функции, вы можете добавить еще более сложную логику вашему диалплану. Чтобы позволить вашему диалплану принимать решения, вы будете использовать условное ветвление. Давайте посмотрим поближе.
Приложение GotoIf()
Ключом к условному ветвлению является приложение GotoIf(). GotoIf() оценивает выражение и отправляет вызывающего абонента в конкретный пункт назначения основываясь на оценке выражения, выраженном в true или false.
GotoIf() использует специальный синтаксис, который часто называют условным синтаксисом:
Если выражение принимает значение true, вызывающий объект отправляется в destination1. Если выражение принимает значение false, вызывающий объект отправляется во второе назначение. Итак, что истинно и что ложно? Пустая строка и число 0 оцениваются как false. Все остальное оценивается как истинное.
Каждый из пунктов назначения может быть одним из следующих:
Любой из пунктов назначения может быть опущен, но не оба. Если пропущенный пункт назначения должен соблюдаться, Asterisk просто переходит к следующему приоритету в текущем внутреннем номере.
Давайте используем GotoIf() в примере:
same => n,GotoIf($[$
same => n(weasels),Playback(weasels-eaten-phonesys)
same => n(iguanas),Playback(office-iguanas)
Вы заметите, что мы использовали приложение Hangup() после каждого использования Playback(). Это делается для того, что когда мы переходим на метку weasels, вызов останавливается до того, как выполнение переходит к звуковому файлу office-iguanas. Становится все более распространенным видеть расширения, разбитые на несколько компонентов (защищенных друг от друга командой Hangup()), каждая из которых совершает отдельную последовательность шагов, выполняемых после GotoIf().
Предоставление только ложного условного пути
Если бы мы захотели, мы могли бы выполнить предыдущий пример следующим образом:
same => n,GotoIf($[$
; weasels, но это всё равно
same => n(iguanas),Playback(office-iguanas)
Мы действительно не рекомендуем это делать, потому что это трудно читать, но вы увидите диалпланы, подобные этому, поэтому хорошо знать, что этот синтаксис абсолютно корректный.
Как правило, когда у вас есть этот тип разбивки, в котором вы хотите избежать перехода Asterisk на следующий приоритет после того, как вы выполнили этот переход, скорее всего, лучше перейти на отдельные расширения вместо ярлыков приоритета. Во всяком случае, это делает его более понятным при чтении. Мы могли бы переписать предыдущий диалплан следующим образом:
same => n,GotoIf($[$
same => n,Playback(weasels-eaten-phonesys) ; это НЕ метка
; это другое расширение
Изменив значение, присвоенное TEST во второй строке, вы сможете заставить




