Глава 3

Основы диалплана

Всё должно быть изложено так просто, как только возможно,

но не более того.

— Альберт Эйнштейн.

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

Эта глава расскажет самую суть концепции диалплана. Изложенная здесь информация является критичной для понимания вами кода диалплана и является основой для любого диалплана, который вы напишите сами. Примеры, описанные ниже, следуют связанно друг за другом, и поэтому мы не рекомендуем пропускать слишком большую часть этой главы, потому что это является фундаментально важным для понимания Астериск. Просим не рассматривать также данную главу как исчерпывающий обзор всех возможностей, которые можно реализовать посредством диалплана; наша цель состоит в том, чтобы охватить только самое необходимое. Мы рассмотрим более расширенные возможности диалплана в последующих главах. Вам предлагается поэкспериментировать.

Синтаксис диалплана

Диалплан Астериска задаётся в конфигурационном файле extensions.conf.

Файл extensions.conf обычно расположен в директории /etc/asterisk, но его расположение может быть совершенно различным в зависимости от того как вы инсталлировали Астериск. Другие возможные места структуры Asterisk — /usr/local/etc/asterisk и /opt/etc/asterisk.

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

Примерный конфигурационный файл

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

Но хочется всё же заметить, что пример extensions.conf содержит фантастические ресурсы, он полон примеров и идей, которые вы можете использовать после того, когда изучите основные концепции. Если вы следовали инструкциям при инсталляции, то найдёте файл extensions.conf.sample в каталоге ~/src/asterisk-complete/asterisk/11/configs (там же, где много и других примеров конфигурации).

Контекст

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

Как простой пример, представьте, что у нас две компании используют один разделяемый сервер Asterisk. Если мы помещаем автосекретаря с приветствием1 компании в соответствующий ему контекст, то они полностью отделены друг от друга. Это также позволит независимо указывать что произойдёт при нажатии, скажем, на 0: позвонившие в интерактивное меню компании А нажавшие 0 соединятся с секретарём компании А, в то время как позвонившие и нажавшие 0 в интерактивном меню компании Б соединятся с секретарём компании Б. Здесь мы подразумеваем, разумеется, что мы сообщили Asterisk делать трансфер на секретаря если позвонивший нажимает 02.)

Контекст определяется именем/названием, которое помещается в квадратные скобки ([ ]). Имя может содержать буквы от A до Z (большие и маленькие), цифры от 0 до 9, дефис и подчёркивание3. Контекст для входящих вызовов может быть таким:

[incoming]

Названия/имя контекста должно быть не более 79 символов (80 символов минус один, нуль).

Все инструкции, расположенные под названием контекста являются частью этого контекста, пока ниже этого не будет определено название следующего контекста. В начале диалплана определены два специальных контекста: [general] и [globals]. Первый — [general] содержит список общих установок диалплана (о которых, возможно, вам вообще не придётся беспокоиться), и мы позже обсудим контекст [globals] в разделе «Глобальные переменные» на стр. . Сейчас просто важно знать про эти две метки не являются контекстами. Избегайте использования [general], [default] и [globals] в качестве имен контекстов, но в противном случае называйте свои контексты как хотите.

Когда вы определяете канал (что не делается в файле extensions.conf, но для этого используются такие файлы, как sip.conf, iax.conf, chan_dahdi.conf, и тд), одним из обязательных параметров в каждом определении канала является context. Контекстэто точка в диалплане, где будут начинаться соединения с этим каналом. Настройка контекста для канала — это способ подключения канала к диалплану. На Рисунке 6-1 показана связь между файлами конфигурации канала и контекстами в диалплане.

Рисунок 6-1. Связь между файлом конфигурации канала и контекстом в диал-плане

Это является одной из важнейших концепций для понимания как соотносятся между собой каналы и диал-план. Когда вы поймёте связь в определении контекста для канала, чтобы находить соответствие ему в диалплане, вы найдёте это лёгким и удобным для поиска проблем в прохождении вызовов через Asterisk-систему.

Наиболее важный смысл использования контекстов (а возможно и самый важный) — обеспечить безопасность. При правильном использовании контекстов вы можете дать определённым пользователям доступ к особым функциональным возможностям (таким как возможность совершать международные вызовы), которые недоступны простым пользователям. Если вы небрежно отнесётесь к построению своего диалплана, то можете несознательно дать возможность посторонним лицам использовать вашу систему в мошеннических целях. Пожалуйста, помните об этом при построении вашей Asterisk-системы; в Интернете уже существует множество специально написанных ботов для обнаружения и внедрения в небрежно настроенные Asterisk-системы.

Asterisk wiki содержит несколько шагов, которые необходимо предпринять для обеспечения безопасности Asterisk-системы. (Глава 26 этой книги также посвящена вопросам безопасности.) Жизненно важно прочесть и понять эту страницу. Если вы проигнорируете меры безопасности, изложенные там, вы можете в конечном итоге позволить кому-либо, и вообще всем, совершать междугородние или платные звонки за ваш счет!

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

Расширения (Extensions)

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

Внутри каждого контекста мы можем использовать множество (или несколько) расширений, сколько нам потребуется. Когда запрашивается обычное расширение (на входящем вызове или по набору цифр в канале), Asterisk выполняет последовательно шаги, указанные для этого расширения. Это расширение, таким образом, описывает то, что должно произойти с вызовом, который попадает по своему пути в соответствующий диалплан. Расширения могут, разумеется, использоваться как специфические телефонные внутренние номера в традиционном смысле (например — расширение 153 будет вызывать SIP-телефон на столе у Ивана), но в диалплане Asterisk они могут использоваться для гораздо большего.

Синтаксис процедур для расширений начинается со слова exten, затем следуют символы — знаки равно и больше, в виде стрелки вправо, как в примере ниже:

exten =>

Далее следует имя (или номер) расширения. Если набирается в/из традиционных телефонных систем, мы предполагаем обработку вызываемого расширения как номера, который набирается чтобы послать вызов на другой телефонный аппарат. В Asterisk вы получаете несколько больше возможностей; например, имя в качестве расширения, которое может содержать как буквы, так и цифры. В рамках краткого курса в этой главе мы рассмотрим как цифровые, так и буквенно-цифровые расширения.

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

Каждый шаг в расширении имеет три компонента:

  • Имя (или номер) расширения
  • Приоритет (каждое расширение может содержать несколько шагов; номер шага и называется «приоритет»)
  • Приложение (или команда), которое выполняется на этом шаге

Эти три компонента разделяются запятыми, как например показано ниже:

exten => name,priority,application()

Вот самый простейший пример как обрабатывается реальный внутренний номер:

exten => 123,1,Answer()

В этом примере имя расширения (или внутренний номер) 123, приоритет 1, и приложение Answer().

Приоритеты

Каждое расширение может иметь несколько шагов, называемых приоритетами. Приоритеты нумеруются последовательно, начиная с 1, и каждый шаг выполняет одно специфическое действие. Например, следующее ниже расширение выполнит ответ на звонок (поднимет трубку на приоритете 1) и затем положит трубку (на приоритете 2):

exten => 123,1,Answer()

exten => 123,2,Hangup()

Довольно очевидно, что этот код не делает ничего полезного. Мы ещё доберемся до него. Ключевым моментом здесь является то, что для конкретного расширения Asterisk следует приоритетам по порядку. Этот стиль синтаксиса диалплана все еще виден время от времени, хотя (как вы увидите скоро) он обычно больше не используется в новом коде:

exten => 123,1,Answer()

exten => 123,2,делаем что-то

exten => 123,3,делаем что-то ещё

exten => 123,4,сделаем ещё одну вещь

exten => 123,5,Hangup()

Ненумерованные приоритеты

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

Начиная с версии 1.2, разработчики Asterisk решили эту проблему: ввели использование приоритета n, который означает «next» (следующий). Каждый раз, когда Астериск встречает приоритет с именем n, он берет номер предыдущего приоритета и добавляет 1. Это упрощает внесение изменений в диал-план, так как вам не нужно изменять нумерацию всех шагов. Например, ваш диалплан может выглядеть примерно так:

exten => 123,1,Answer()

exten => 123,n,делаем что-то

exten => 123,n,делаем что-то ещё

exten => 123,n,сделаем ещё одну вещь

exten => 123,n,Hangup()

Внутри себя Asterisk будет вычислять следующий номер приоритета каждый раз, когда он встречает n4. Имейте в виду, что вы всегда должны указать вначале приоритет номер 1. Если вы случайно поставили n вместо 1 для первого приоритета (распространенная ошибка даже среди опытных кодеров диалплана), то после перезагрузки диалплана вы обнаружите, что расширение не будет существовать.

Оператор same =>

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

exten => 123,1,Answer()

same => n,делаем что-то

same => n,делаем что-то ещё

same => n,сделаем ещё одну вещь

same => n,Hangup()

Отступ не требуется, но это может облегчить чтение. Этот стиль диалплана также облегчит копирование кода из одного расширения в другое. Мы предпочитаем этот стиль сами, и очень рекомендуем его.

Метки приоритетов

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

exten => 123,n(label),application()

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

Наиболее распространённая ошибка при написании диалплана с метками — это указание метки после запятой, между n и скобкой (, как здесь:

exten => 123,n,(label),application() ;<— ЭТО НЕ БУДЕТ РАБОТАТЬ

Эта ошибка разрушит часть вашего диалплана и вы получите сообщение об ошибке, что приложение не найдено.

Приложения

Приложения — это рабочие лошадки диалплана. Каждое приложение выполняет определённое действие в текущем канале, типа — воспроизвести звуки, принять набор сигналов DTMF, найти что-то в базе данных, сделать вызов в канал, повесить трубку или что-то иное. В предыдущем примере мы показали два простых приложения: Answer() и Hangup(). Вы узнаете больше о том как это моментально работает.

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

Иногда вместо запятой в качестве разделителя аргументов может использоваться символ пайп ( | ). Начиная с Asterisk 1.6.0 поддержка пайпа в качестве разделителя была удалена (кроме некоторых разделов в voicemail.conf).

Приложения Answer(), Playback(), и Hangup()

Приложение Answer() используется для ответа на вызывающий канал. Оно производит начальную настройку на канале, который получает входящий вызов. Как мы упоминали ранее, Answer() не принимает аргументов. Answer() не всегда вообще требуется (фактически, в некоторых случаях он вообще нежелателен), но в остальных случаях он вполне годен, чтобы подключить канал прежде чем начать последующие действия.

Приложение Progress()

Иногда полезно иметь возможность передавать информацию обратно в сеть перед ответом на вызов. Приложение Progress() пытается предоставить исходному каналу информацию о ходе выполнения вызова. Некоторые операторы ожидают этого и таким образом Вы можете быть в состоянии решить странные проблемы сигнализации, вставив Progress() в диалплан куда поступают ваши входящие вызовы. С точки зрения биллинга, использование Progress() позволяет оператору знать, что вы обрабатываете вызов без запуска тарификации.

Приложение Playback() используется для воспроизведения предварительно записанных звуковых файлов. При этом аудиовход от пользователя игнорируется, подразумевается что вы не хотите использовать Playback() в автоответчиках (автосекретаре), например — просто не хотите принимать аудио данные в этой точке5.

Астериск поставляется с большим количеством профессионально записанных звуковых файлов, которые находятся в каталоге звуков по умолчанию (обычно /var/lib/asterisk/sounds). При компиляции Asterisk можно выбрать установку различных наборов звуковых файлов, записанных на различных языках и в различных форматах. Мы будем использовать эти файлы во многих наших примерах. Некоторые из файлов в наших примерах взяты из дополнительного звукового пакета, поэтому, пожалуйста, найдите время, чтобы установить его (см. Главу 3). Вы также можете иметь свои собственные звуковые подсказки, записанные в тех же голосах, что и стоковые подсказки, посетив http://www.theivrvoice.com. Далее в книге мы поговорим о том, как использовать телефонный аппарат и диалплан для создания собственных системных записей и управления ими.

Чтобы использовать Playback() укажите имя файла (без расширения) в качестве аргумента. Например, Playback(filename) воспроизведёт файл filename.wav, предполагая, что он расположен в дефолтной для звуковых файлов директории. Заметим, что можно также включать полный путь к файлу, если необходимо, как указано ниже:

Playback(/home/john/sounds/filename)

В приведённом примере мы воспроизвели filename.wav из директории /home/john/sounds.

Можно также использовать относительные пути к именам файлов относительно к основной директории звуковых файлов, как например ниже:

Playback(custom/filename)

В этом примере будет проигран файл filename.wav из поддиректории /custom в директории где обычно хранятся звуковые файлы (то есть /var/lib/asterisk/sounds/custom/filename.wav). Имейте ввиду, что если указанная директория содержит более, чем один файл с одинаковым именем, но разными расширениями, Asterisk автоматически воспроизведет лучший по качеству файл6.

Приложение Hangup() делает именно то, что отражено в его названии: закрывает активный канал. Необходимо использовать его в конце контекста, если хотите завершить текущий канал, чтобы быть уверенным, что действия, которые, возможно, и не предполагались, в активном канале не продолжатся. Приложение Hangup() не требует аргументов, но, если хотите, в него можно передать ISDN код завершения, например Hangup(16).

В процессе работы над книгой мы познакомим вас со многими приложениями Астериск.

Простой диал-план.

OK, хватит теории. Откройте в редакторе файл /etc/asterisk/extensions.conf, и посмотрите на ваш первый диалплан (который был создан в предыдущей Главе 5). Мы будем дополнять его.

Hello World

Наиболее типичным примером для многих книг по технологиям (точнее — книг по программированию) является первый пример под названием «Привет, мир!» (“Hello World!”).

Первым приоритетом нашего расширения мы отвечаем на вызов. Затем, на втором шаге мы воспроизводим файл с названием hello-world и затем, третьим шагом мы просто кладём трубку завершая вызов. Интересующий нас код для этого примера выглядит вот так:

exten => 200,1,Answer()

same => n,Playback(hello-world)

same => n,Hangup()

Если вы прошли Главу 5 вы уже получили сконфигурированный один или два канала, а также пример диалплана, содержащий наш код. Если нет, то всё, что вам нужно — просто добавить в файл extensions.conf в директории /etc/asterisk следующий код:

[LocalSets] ; это название контекста

exten => 100,1,Dial(SIP/0000FFFF0001) ; замените 0000FFFF0001 на имя вашего

; устройства

exten => 101,1,Dial(SIP/0000FFFF0002) ; замените 0000FFFF0002 на имя вашего

; устройства

exten => 200,1,Answer()

same => n,Playback(hello-world)

same => n,Hangup()

Если у вас ещё нет сконфигурированных к этому моменту каналов, то сейчас самое время сделать это. Существует реальное удовлетворение, которое приходит от вашего первого вызова в диалплан в Asterisk-системе, которую вы построили с нуля. Люди обычно ощущают забавную ухмылку на своих лицах, поскольку они понимают, что только что создали телефонную систему. Это удовольствие может быть получено и вами, поэтому, пожалуйста, не двигайтесь дальше, пока не сделаете это небольшое задание по диалплану. Если при этом вы столкнётесь с какими-то проблемами, вернитесь к Главе 5 и проработайте примеры оттуда.

Если у вас ещё нет этого кода в диалплане, пора его вставить и применить через перезагрузку диал-плана командой CLI:

*CLI> dialplan reload

или из командной оболочки:

$ sudo /usr/sbin/asterisk -rx «dialplan reload»

Вызов расширения 200 с преднастроенного телефона даст возможность услышать голос Элиссон Смит, которая скажет “Hello, world!”

Если это не работает, смотрите в консоль Астериска на предмет сообщений об ошибках, и убедитесь в том, что ваш канал привязан к контексту LocalSets.

Мы не рекомендуем двигаться дальше по этой главе, прежде чем вы не проверите следующее:

  1. Вызовы между внутренними номерами 100 и 101 работают
  2. Вызов на внутренний номер 200 воспроизводит “Hello World”

Несмотря на то, что этот пример очень короткий и простой, он подчеркивает основные понятия контекстов, расширений, приоритетов и приложений. Теперь у вас есть фундаментальные знания, на которых строятся все диалпланы.

Построение интерактивного диал-плана

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

Приложения Goto(), Background() и WaitExten()

Как понятно из названия, приложение Goto() используется для отсылки вызова в другой участок диалплана. Синтаксис приложения Goto() потребует от нас указать данные: контекст назначения, расширение и приоритет в качестве аргументов, как указано ниже:

same => n,Goto(context,extension,priority)

Давайте создадим новый контекст TestMenu и укажем ещё одному расширению в нашем контексте LocalSets перенаправить вызовы туда через Goto():

exten => 201,1,Goto(TestMenu,start,1) ; добавим эту строку в конце

; контекста [LocalSets]

[TestMenu]

exten => start,1,Answer()

Теперь, если любое устройство в контексте LocalSets наберёт 201 вызов перенаправится на расширение start в контексте TestMenu (в котором пока ещё нет ничего интересного, ибо его код мы напишем позже).

Мы используем расширение start в этом примере, хотя можно использовать вообще любое имя в качестве расширения, включая цифры и буквы. Мы предпочитаем использовать буквенные расширения, хотя их и не набрать с цифровой панели телефона, но зато это даёт более читаемый диалплан. В нашем примере мы могли бы использовать 123 или xyz123, или же 99luftballons или вообще что угодно вместо выбранного нами start. Само слово “start” ничего специально не означает в диалплане; это просто произвольное название расширения.

Одним из наиболее полезных приложений в интерактивном диалплане Asterisk является приложение Background()7. Как и Playback() оно воспроизводит записанный звуковой файл. Однако, в отличие от Playback() при нажатии клавиши (или серии клавиш) на клавиатуре телефона, оно прерывает воспроизведение и передает вызов на добавочный номер, соответствующий набранным цифрам. Если абонент нажимает 5, к примеру, Asterisk сразу передаст вызов на первый приоритет расширения 5 (предполагая, что расширение 5 существует для обработки вызова).

Чаще всего приложение Background() используется для создания голосовых меню (часто называемых автосекретарями8 или телефонными деревьями). Многие компании используют голосовые меню, чтобы направить абонентов в соответствующие отделы, тем самым избавляя операторов от необходимости отвечать на каждый вызов.

Background() имеет такой же самый синтаксис как и Playback():

[TestMenu]

exten => start,1,Answer()

same => n,Background(enter-ext-of-person)

Если хотите, чтобы Asterisk ожидал донабор от позвонившего после приветствия, то можно использовать WaitExten(). Приложение WaitExten() ожидает от позвонившего сигналы DTMF (нажатие цифр) и указывается сразу за приложением Background() как указано ниже:

[TestMenu]

exten => start,1,Answer()

same => n,Background(enter-ext-of-person)

same => n,WaitExten()

Если необходимо, чтобы приложение WaitExten() ожидало ввода только в течение определённого количества секунд (вместо дефолтного значения таймаута)9 просто укажите эту цифру в скобках в качестве аргумента в WaitExten() как ниже:

same => n,WaitExten(5) ; Мы всегда передаём аргумент в приложение WaitExten()

Оба приложения — Background() и WaitExten() позволяют вводить цифры в виде донабора DTMF. После чего Астериск пытается найти расширение в текущем контексте, соответствующее введённым цифрам. Если такое совпадение найдено, Asterisk посылает вызов согласно этому расширению. Давайте продемонстрируем это добавлением нескольких строк в нашем примере диалплана:

[TestMenu]

exten => start,1,Answer()

same => n,Background(enter-ext-of-person)

same => n,WaitExten(5)

exten => 1,1,Playback(digits/1)

exten => 2,1,Playback(digits/2)

После выполнения этих изменений нужно сохранить и перезагрузить диалплан:

*CLI> dialplan reload

Если вы звоните на номер 201 вы должны услышать приветствие “Введите внутренний номер сотрудника чтобы соединиться с ним.” Система будет ожидать ввода цифр в течение 5 секунд. Если вы нажмёте 1 или 2, то Астериск найдёт соответствующее расширение и прочитает его вам. Так как мы не прописали там никаких других инструкций к выполнению, то наш вызов на этом завершится. Вы также можете попробовать вводить другие цифры (например 3), которых нет в диалплане и, потому, он не будет выполняться.

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

[TestMenu]

exten => start,1,Answer()

same => n,Background(enter-ext-of-person)

same => n,WaitExten(5)

exten => 1,1,Playback(digits/1)

same => n,Goto(TestMenu,start,1)

exten => 2,1,Playback(digits/2)

same => n,Goto(TestMenu,start,1)

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

Если вы рассмотрите внимательно возможности приложения Goto(), то увидите возможность передавать вызов в это приложение с одним, двумя и тремя аргументами. Если передаётся один аргумент, то Asterisk предположит что это приоритет назначения в текущем расширении. Если передаётся два аргумента, то Астериск будет рассматривать их как расширение и приоритет для перехода в текущем контексте.

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

Обработка неверных значений и Таймаутов

После того, как мы создали вместе наше первое голосовое интерактивное меню, давайте добавим в него некоторые дополнительные специальные расширения. Для начала нам нужно расширение для обработки неверных, несуществующих расширений. Asterisk получив в контексте запрос на обработку несуществующего в текущем контексте расширения (например – нажатие 9 в примере выше), перенаправит вызов в расширение i. Нам также понадобится специальное расширение для обработки ситуаций, когда позвонивший вообще ничего не нажал в течение определённого времени (дефолтный таймаут 10 секунд). Вызов так же будет перенаправлен в расширение t если абонент слишком поздно нажал что-то после WaitExten() при вызове. Посмотрите как будет выглядеть наш диалплан после того, как мы добавим эти два расширения:

[TestMenu]

exten => start,1,Answer()

same => n,Background(enter-ext-of-person)

same => n,WaitExten(5)

exten => 1,1,Playback(digits/1)

same => n,Goto(TestMenu,start,1)

exten => 2,1,Playback(digits/2)

same => n,Goto(TestMenu,start,1)

exten => i,1,Playback(pbx-invalid)

same => n,Goto(TestMenu,start,1)

exten => t,1,Playback(vm-goodbye)

same => n,Hangup()

Использование расширений i10 и t делает наше меню более надежным и дружественным по отношению к пользователям. Тем не менее, оно все еще довольно ограничено, потому что внешние абоненты по-прежнему не имеют возможности связаться с живым человеком. Для этого нам нужно узнать о другом приложении, называемом Dial().

Использование приложения Dial()

Одной из наиболее ценных функций Asterisk является возможность соединения разных абонентов друг с другом. Это особенно полезно, когда абоненты используют различные методы связи. Например, абонент А может общаться по традиционной аналоговой телефонной сети, в то время как пользователь Б может сидеть в кафе на другом конце света и говорить по IP-телефону. К счастью, Asterisk берёт на себя большую часть тяжелой работы по соединению и трансляции вызовов между разрозненными сетями. Все что вам нужно сделать, это научиться использовать приложение Dial().

Синтаксис приложения Dial() более сложен, чем другие приложения, которые мы использовали до сих пор, но это не должно вас пугать. В приложение Dial() передаётся до четырёх аргументов, которые мы рассмотрим ниже.

Аргумент 1: назначение

Первый аргумент – это назначение: т.е. куда вы хотите позвонить, который (в простой форме) содержит технологию (или транспорт), посредством которой выполняется вызов, далее знак слэш — / и адрес удалённой конечной точки или ресурса. Наиболее типичные примеры технологий включают в себя DAHDI (для аналоговых и цифровых T1/E1/J1, PRI & BRI каналов), SIP и IAX2.

Например, если мы хотим совершить вызов на конечное устройство DAHDI, идентифицируемого как DAHDI/1, которое является фактически аналоговым FXS каналом с подключенным к нему аналоговым телефоном. Технология вызова будет DAHDI и ресурс (или идентификатор канала) будет 1. Точно так же вызов на SIP устройство (которое описано в sip.conf) может иметь назначение вида SIP/0004F2001122, а вызов IAX устройства (описанного в iax.conf) может иметь назначение вида IAX2/Softphone11. Если мы собираемся позвонить через Asterisk в канал DAHDI/1 за которым закреплён в диал-плане внутренний номер 105, мы добавим следующее расширение:

exten => 105,1,Dial(DAHDI/1)

Можно также делать одновременный вызов нескольких каналов, разделяя назначения знаком амперсанд (&), как показано ниже:

exten => 105,1,Dial(DAHDI/1&SIP/0004F2001122&IAX2/Softphone)

Приложение Dial() позвонит всем указанным назначениям одновременно, и соединит входящий вызов с первым ответившим каналом назначения (остальные назначения при этом прекращают звонить). Если приложение Dial() не может соединиться ни с одним назначением, Asterisk установит переменную вызова DIALSTATUS в значение с причиной невозможности набрать назначение, и продолжит выполнение со следующего приоритета в расширении12.

Приложение Dial() также даёт возможность установить соединение с удалённым конечным VoIP-устройством, даже не указанным ранее в конфигурационных файлах соответствующего канала. Полный синтаксис команды имеет вид:

Dial(technology/user[:password]@remote_host[:port][/remote_extension])

В качестве примера вы можете позвонить на демонстрационный сервер компании Digium используя протокол IAX2 и следующее расширение:

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

Полный синтаксис приложения Dial() несколько отличается для каналов DAHDI:

Dial(DAHDI/[gGrR]channel_or_group[/remote_extension])

Например, если вы набираете номер 1-800-555-1212 через DAHDI канал под номером 413:

exten => 501,1,Dial(DAHDI/4/18005551212)

Аргумент 2: тайм-аут

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

Если тайм-аут не указан, Dial() будет продолжать звонить на указанные каналы до тех пор, пока кто-либо не поднимет трубку. Давайте добавим 10-ти секундный тайм-аут в наше расширение:

exten => 502,1,Dial(DAHDI/1,10)

Если абонент ответит до истечения таймаута, то каналы соединяются и диалплан на этом закончится. Если же абонент просто не отвечает, занят, или даже недоступен по каким-то причинам, Asterisk устанавливает это значение в переменной DIALSTATUS и продолжает выполнение следующего приоритета в текущем расширении.

Давайте соорудим сейчас то, что мы изучили в следующем примере:

exten => 502,1,Dial(DAHDI/1,10)

same => n,Playback(vm-nobodyavail)

same => n,Hangup()

Как мы видим в этом примере, звуковой файл vm-nobodyavail.gsm будет воспроизведён в случае, если вызов не отвечен.

Аргумент 3: опции

Третий аргумент в Dial() — строка опций. Она может содержать один или больше знаков, которые модифицируют поведение приложения Dial(). Список всех возможных опций слишком огромен, чтобы рассматривать его в рамках этого раздела. Например, одна из популярных опций – m. Если букву m указать третьим аргументом, вызывающая сторона будет слышать музыку вместо гудков вызова, который совершается в этот момент вызываемой стороне (разумеется мы предполагаем, что музыка на удержание у нас уже правильно сконфигурирована). Добавим опцию m в наш последний пример, чуть изменив первую строчку:

exten => 502,1,Dial(DAHDI/1,10,m)

same => n,Playback(vm-nobodyavail)

same => n,Hangup()

Аргумент 4: URI

Четвёртый и последний аргумент в приложении Dial() — это URI. Если канал назначения поддерживает приём вызовов по URI, то указанный URI будет передаваться (например, если у вас есть IP-телефон, поддерживающий приём URI, то он появится на экране телефона; в случае использования софтфона URI может появиться в виде всплывающего окна на экране компьютера). Этот аргумент очень редко используется.

Некоторые телефоны (если у вас такие есть) поддерживают информацию URI, которая к ним передаётся. Если вы ищете что-то типа всплывающих окон, рекомендуем обратиться к Главе 18, и более детально к разделу о Jabber в «Использование XMPP (Jabber) с Asterisk» на странице .

Обновление диалплана

Давайте изменим расширения 1 и 2 в нашем меню, где используем приложение Dial():

[TestMenu]

exten => start,1,Answer()

same => n,Background(enter-ext-of-person)

same => n,WaitExten(5)

exten => 1,1,Dial(SIP/0000FFFF0001,10) ; Замените 0000FFFF0001 на имя своего

; устройства

same => n,Playback(vm-nobodyavail)

same => n,Hangup()

exten => 2,1,Dial(SIP/0000FFFF0002,10) ; Замените 0000FFFF0002 на имя своего

; устройства

same => n,Playback(vm-nobodyavail)

same => n,Hangup()

exten => i,1,Playback(pbx-invalid)

same => n,Goto(TestMenu,start,1)

exten => t,1,Playback(vm-goodbye)

same => n,Hangup()

Пустые аргументы

Заметим, что второй, третий и четвёртый аргументы могут быть пустыми; обязательным является только первый аргумент. Например, если требуется указать строковую опцию, но без таймаута, просто оставьте аргумент тайм-аут незаполненным, как указано ниже:

exten => 1,1,Dial(DAHDI/1,,m)

Использование переменных

Переменные могут использоваться в диалплане Asterisk чтобы уменьшить набор строк кода, увеличить понимание или добавить логику. Если у вас есть опыт по программированию, то вы уже понимаете что такое переменные. Если нет – мы кратко расскажем что такое переменные и как они используются. Переменные являются жизненноважной концепцией диалплана Asterisk (и вы не найдете их в диалплане любой проприетарной АТС).

Переменная — это именованный контейнер, который может содержать некоторое значение. Преимущество переменной заключается в том, что её содержимое может изменяться, но её имя не меняется, то есть можно написать код, который ссылается на имя переменной и не беспокоиться о её содержимом. Например, мы можем создать переменную JOHN и присвоить ей значение DAHDI/1. И, когда мы пишем наш диалплан, мы можем указать канал John по имени, вместо того, чтобы помнить, что John использует канал с именем DAHDI/1. Если в какой-то момент мы изменим канал John на что-то другое, нам не придется менять код, ссылающийся на переменную JOHN, нам нужно только изменить значение, присвоенное переменной.

Имеется два способа ссылаться на переменную. Чтобы сослаться на имя переменной, просто напишите имя переменной, например LEIF. Другим способом можно сослаться на значение переменной указав знак доллара, открывающую фигурную скобку, имя переменной и закрывающую фигурную скобку (в случае если мы будем ссылаться на значение переменной с ${LEIF}). Вот как мы можем использовать переменную внутри приложения Dial:

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

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

В нашем примере диалплана, каждый раз, когда происходит обращение к ${LEIF}, Астериск автоматически изменяет её на значение, которое было перед этим присвоено переменной с именем LEIF.

Помните, что названия переменных чувствительны к регистру. Переменная LEIF совсем не та же, что с названием Leif. Для большей читабельности все наши переменные в примерах мы будем писать в верхнем регистре. Вам надо также в дальнейшем знать, что все переменные в Asterisk будут также в верхнем регистре. Некоторые переменные, такие как CHANNEL и EXTEN, зарезервированы в Asterisk. Не пытайтесь назначить какие-то значения этим переменным. Распространённым также является запись глобальных переменных в верхнем регистре, а канальных переменных в формате языков Pascal/Camel.

Можно использовать три типа переменных в нашем диал-плане: глобальные переменные, канальные переменные и переменные окружения. Рассмотрим каждый из них.

Глобальные переменные

Как следует из самого названия, глобальные переменные всегда доступны всем каналам. Глобальные переменные полезны тем, что их можно использовать в любом месте диалплана для повышения удобочитаемости и управляемости. Представьте на мгновение, что у вас есть большой диалплан и несколько сотен обращений к каналу SIP/0000FFFF0001. Теперь вообразите, что вы передвигаетесь по диалплану и меняете все ссылки на SIP/0000FFFF0002. Это будет долгим процессом, и не без ошибок, как минимум.

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

Глобальные переменные декларируются в контексте [globals] в самом начале файла extensions.conf. Например, мы создадим глобальную переменную с именем LEIF и значением SIP/0000FFFF0001. Эта переменная устанавливается каждый раз, когда Asterisk перечитывает диалплан:

[globals]

LEIF=SIP/0000FFFF0001

Канальные переменные

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

Имеется множество предопределённых переменных канала для использования их в диалплане, они описаны подробно в Asterisk wiki. Канальные переменные устанавливаются через приложение Set():

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

same => n,SayNumber(${MagicNumber})

Вы можете увидеть и другие различные канальные переменные. Почитайте!

Переменные среды

Переменные среды – это способ получить переменные Unix среды из среды Asterisk. Это делается при помощи функции диалплана ENV()14. Синтаксис ${ENV(var)}, где var — переменная среды Unix на которую вы ссылаетесь. В большинстве случаев переменные среды не используются в диалпланах Asterisk, но то, что они доступны, вам необходимо знать.

Добавление переменных в ваш диал-план

Теперь, когда мы изучили переменные, давайте мы заставим их работать в нашем диалплане. Мы начнём с добавления трёх глобальных переменных, ассоциированных с их канальными именами:

[globals]

LEIF=SIP/0000FFFF0001

JIM=SIP/0000FFFF0002

RUSSELL=SIP/0000FFFF0003

[LocalSets]

exten => 101,1,Dial(${LEIF})

exten => leif,1,Dial(${LEIF})

exten => 102,1,Dial(${JIM})

exten => jim,1,Dial(${JIM})

exten => 103,1,Dial(${RUSSELL})

exten => russell,1,Dial(${RUSSELL})

exten => 201,1,Goto(TestMenu,start,1) ; доступ к контексту TestMenu

[TestMenu]

exten => start,1,Answer()

same => n,Background(enter-ext-of-person)

same => n,WaitExten()

exten => 1,1,Dial(DAHDI/1,10)

same => n,Playback(vm-nobodyavail)

same => n,Hangup()

exten => 2,1,Dial(SIP/Jane,10)

same => n,Playback(vm-nobodyavail)

same => n,Hangup()

exten => i,1,Playback(pbx-invalid)

same => n,Goto(TestMenu,start,1)

exten => t,1,Playback(vm-goodbye)

same => n,Hangup()

Вы заметили, что мы добавили имена-псевдонимы в качестве внутренних номеров. В разделе “Расширения” на стр. 112, мы поясняли уже, что для Asterisk нет никакой разницы по какой схеме имён идентифицируются внутренние номера. Мы просто добавляем оба – номерные и именные расширения для связи с каждым конечным устройством; внутренний номер 101 и leif оба приведут к устройству SIP/0000FFFF0001; внутренний номер 102 и jim оба приведут к устройству SIP/0000FFFF0002; а 103 и russell попадают на SIP/0000FFFF0003. Устройства, нами определены при помощи глобальных переменных ${LEIF}, ${JIM}, и ${RUSSELL}, соответственно, и мы можем набирать их используя приложение Dial().

В нашем тестовом меню мы просто укажем несколько различных конечных устройство для набора, как DAHDI/1 и SIP/Jane. Они могут быть заменены на любые конечные устройства, какие мы пожелаем. В нашем контексте TestMenu, который мы создаем, чтобы иметь представление как выглядит диалплан Asterisk, может дать вам идеи как это лучше сделать.

Совпадение по шаблонам

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

Синтаксис сравнения по шаблонам

При использовании сопоставления, определённые конкретные буквы и символы представляют то, с чем мы сравниваем. Шаблон всегда начинается с подчёркивания (_). Это сообщает Asterisk, что мы собираемся сравнивать с шаблоном, а не ожидаем точное имя расширения.

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

После подчёркивания можно использовать следующие одну или несколько букв:

X

Совпадение одной цифры от 0 до 9.

Z

Совпадение одной цифры от 1 до 9.

N

Совпадение одной цифры от 2 до 9.

Другая распространённая ошибка – использование букв X, Z, и N в словах, составляющих шаблон совпадения; чтобы это обойти – используйте эти буквы в квадратных скобках (чувствительны к регистру), например _[n]o[x]ious-XXX.

[15-7]

Совпадение одного знака из указанного диапазона цифр. В данном случае совпадение будет найдено при цифре 1, а также других цифрах в диапазоне 5, 6, 7.

. (точка)

Свободное совпадение по шаблону; совпадёт один или более символов, независимо от того, что они представляют.

Если вы не очень заботитесь о точности, свободный шаблон с точкой даст непредсказуемое поведение в вашем диалплане (например – совпадение встроенных специальных расширений, таких как i или h). Нужно использовать точку в шаблонах после одной или нескольких цифр, которые найдены, если возможно, сравнением набранного номера с шаблоном. Например, вот такой шаблон никогда не должен использоваться:

_.

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

_X.

Или такой пример, отвечает на совпадение любой цифры или буквы:

_[0-9a-zA-Z].

! (восклицание)

Подстановочный знак соответствия; соответствует нулю или более символов, независимо от того, что они представляют.

Для использования шаблонов в вашем диалплане просто поместите шаблон в качестве имени (или номера) расширения:

exten => _NXX,1,Playback(silence/1&auth-thankyou)

В этом примере с шаблоном сравнивается любой трёхзначный внутренний номер от 200 до 999 (буква N определяет цифры от 2 до 9, а каждая X определяет цифры от 0 до 9). Тем самым мы говорим, что любой, кто наберёт трёхзначный номер от 200 до 999 в этом контексте, услышит аудио файл auth-thankyou.gsm.

Ещё одно важное дополнение для понимания как набранный номер сопоставляется с шаблоном, если Asterisk нашёл более чем один шаблон для набранного номера. В таком случае будет использоваться наиболее конкретный (просчитывая сравнение слева направо). Скажем, вы указали следующие два шаблона, и абонент набрал 555-1212:

exten => _555XXXX,1,Playback(silence/1&digits/1)

exten => _55512XX,1,Playback(silence/1&digits/2)

В этом случае будет выбрано второе расширение , потому что оно точнее подходит.

Примеры совпадения по шаблонам

Следующий шаблон соответствует любому семизначному номеру, если первая цифра равна 2 или больше:

_NXXXXXX

Приведённый выше шаблон описывает все семизначные локальные номерные планы в Северной Америке.

В региональных 10-значных кодах этот шаблон будет выглядеть следующим образом:

_NXXNXXXXXX

Обратите внимание, что ни один из этих двух шаблонов не будет обрабатывать междугородние вызовы. Мы рассмотрим их в ближайшее время.

NANP и мошенничество с тарифами

Североамериканский номерной план (NANP) является открытой схемой телефонной нумерации, охватывающей 19 стран Северной Америки и Карибского архипелага. Все эти страны имеют международный код 1.

В Соединённых Штатах и Канаде правила регуляции в области телекоммуникаций схожи (и рациональны) и достаточны для совершения международных вызовов в страны с кодом 1 и ожидаемой адекватной стоимостью звонка. Однако большинство людей в 17 странах (кроме США и Канады) не реализуют возможности, заложенные правилами регуляции, которые сильно отличаются в этих странах. Смотрите правила NANP.

Одна из популярных афер использования NANP — попытка обмануть наивных Североамериканцев для вызовов по дорогим поминутным тарифам на номера в Карибские страны; абоненты считают, что, поскольку они набрали номер 1-NPA-NXX-XXXX, то они платят по стандартному национальному международному тарифу. Поскольку данная страна может иметь правила, которые позволяют эту форму вымогательства, абонент сам несет ответственность за стоимость звонка.

Единственный способ предотвратить подобные действия — блокировать вызовы определенных региональных кодов (например, 809) и снимать ограничения только по мере необходимости.

Рассмотрим ещё один:

_1NXXNXXXXXX

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

И наконец – такой:

_011.

Обратите внимание на точку в конце шаблона. Он описывает все номера, которые начинаются с 011 и далее одну или более цифр. В зоне действия NANP будет определяться как иностранный номер. (Мы будем использовать этот шаблон в следующем разделе при добавлении возможностей исходящих вызовов в нашем диалплане.)

Шаблоны, используемые в других странах

В этой секции показаны шаблоны ориентированные на NANP, но базирующиеся на логике применения в любой стране. Ниже даны примеры для некоторых стран (обратите внимание, что мы не проверяли их, и они почти наверняка неполные):

; UK, Германия, Италия, Китай и т.д.

_00. ; международный телефонный код

_0. ; национальный префикс набора

Австралия

_0011. ; международный телефонный код

_0. ; национальный префикс набора

Это никоим образом не является всеобъемлющим, но должно дать вам общее представление о шаблонах, которые вы можете применять для своей собственной страны.

Использование канальной переменной ${EXTEN}

Что произойдёт, если вы хотите использовать шаблон для сравнения набранных номеров, но при этом хотите знать какие именно цифры были при этом набраны? Укажите переменную канала ${EXTEN}. Каждый раз, когда набран какой либо номер, Asterisk установит переменную канала ${EXTEN} в значение набранных цифр. Мы можем использовать приложение SayDigits() чтобы протестировать это:

exten => _XXX,1,Answer()

same => n,SayDigits(${EXTEN})

В этом примере приложение SayDigits() прочитает нам набранный трёхзначный номер.

Часто могут быть полезными манипуляции с ${EXTEN} отрезая определённое количество цифр впереди внутреннего номера. Это достигается синтаксисом ${EXTEN:x}, где x — количество цифр, которые нужно пропустить в переменной слева направо. Например, если значение переменной ${EXTEN} равно 95551212, то ${EXTEN:1} будет возвращать 5551212. Давайте попробуем такой пример:

exten => _XXX,1,Answer()

same => n,SayDigits(${EXTEN:1})

В этом примере приложение SayDigits() стартует со второй цифры и проговорит только две последние цифры из набранного внутреннего номера.

Продвинутые возможности манипуляций с цифрами

Переменная ${EXTEN} в общем случае имеет полный синтаксис ${EXTEN:x:y}, где x – начальная позиция и y – количество возвращаемых цифр. Например, при набранном:

94169671111

мы можем выделить следующие цифры используя конструкцию ${EXTEN:x:y}:

  • ${EXTEN:1:3} вернёт нам 416
  • ${EXTEN:4:7} вернёт нам 9671111
  • ${EXTEN:-4:4} отсчитает 4 цифры с конца и вернёт четыре цифры, мы получим 1111
  • ${EXTEN:2:-4} отсчитает две цифры и отнимет последние четыре цифры, мы получим 16967
  • ${EXTEN:-6:-4} отсчитает шесть цифр с конца и отнимет последние четыре цифры, мы получим 67
  • ${EXTEN:1} вернёт нам все цифры после первой, то есть 4169671111 (если количество возвращаемых цифр будет пустым, будет возвращена вся строка)

Это очень мощная конструкция, но большинство этих вариаций не нужны при обычном использовании. Большей частью вы будете использовать просто ${EXTEN} (или, возможно — ${EXTEN:1} если потребуется отрезать внешний префикс, такой как приставка 9 перед набором).

Включения (инклюды)

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

Оператор include имеет следующую форму, где context – название другого контекста, который мы включаем в текущий контекст:

include => context

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

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

Мы продолжим разговор о директиве include дальше в Главе 7.

Вывод

И наконец у вас есть он — простой, но вполне функционирующий диалплан. Есть ещё многие вещи, которые мы не рассмотрели пока, но у вас уже есть все фундаментальные основы. В следующих главах мы продолжим строить на этих основах.

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

1Автоответчики рассматриваются в Главе 15.

2Это очень важное соображение. По сравнению с традиционными УАТС, где, как правило, существует набор значений по умолчанию для таких отделов, как приёмная (что означает — если вы забудете определить эти значения, то они, вероятно, будут работать в любом случае). В Астериск верно обратное: если вы не укажете Астериск как обрабатывать каждую ситуацию и он столкнется с чем-то, что он не сможет обработать, вызов, как правило, будет отклонен. Мы рассмотрим некоторые лучшие примеры из практики, которые помогут убедиться, что этого не произойдет, позже. Дополнительные сведения см. в разделе «Обработка неверных записей и таймаутов» на стр. 133.

3Заметим, что пробелы не входят в список допустимых символов. Не используйте имена контекстов с пробелами — ибо результат этого вам совсем не понравится!

4Астериск допускает простую арифметику в пределах приоритета, например n+200 и приоритет s (для same), но их использование несколько устарело из-за существования меток приоритета. Обратите внимание, что расширение s и приоритет s — это два разных понятия.

5Это будет другое приложение называемое Background(), которое почти идентично Playback() кроме того, что разрешает входящий аудиопоток от абонента. Вы можете более подробно прочесть об этом приложении в Главах 15 и 17.

6Asterisk выбирает лучший файл с точки зрения издержек трансляции кодеков (транскодинга) — таким образом затрачиваются наименьшие ресурсы по загрузке ЦПУ при конвертации в родной аудио-формат. Когда запускается Asterisk, вычисляются издержки трансляции между различными форматами аудио (они часто различаются в различных системах). Вы можете увидеть это набрав в командной строке своего Asterisk core show translation. Цифры в таблице показывают скорость перекодирования (в миллисекундах) односекундного аудио. Мы поговорим больше о различных аудио форматах (более известных как кодеки) в разделе «Кодеки» в Приложении B.

7Следует отметить, что некоторые люди ожидают что Background() из-за его имени, продолжит движение вперед, следуя шагам в диалплане во время воспроизведения звука. На самом деле его имя относится к тому, что он играет звук в фоновом режиме, ожидая DTMF на переднем плане.

8Дополнительную информацию об автосекретаре вы найдёте в Главе 15.

9Загляните в функцию диалплана TIMEOUT() чтобы узнать как можно изменить значение таймаутов по умолчанию. См. Главу 10 по списку всех функций диалплана.

10Расширение i для обработки несуществующих назначений поддерживается в основном для таких приложений как Background(). Оно не используется для обработки неверно набранных расширений или не попадающих в шаблон расширений.

11Если это рабочая конфигурация (а не тестовый пример) то не очень удачное название для этого устройства. Если вы добавите больше чем один софтфон (или планируете это в будущем) – как вы будете их различать?

12Мы рассмотрим переменные в разделе Использование переменных. В следующей главе мы обсудим как задавать выполнение диалплана основываясь на значениях DIALSTATUS.

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

14Мы рассмотрим функции диалплана позже. Не беспокойтесь о слишком многих переменных среды прямо сейчас. Это не так важно для понимания диалплана.

15Если вы выросли в Северной Америке, то можете поверить, что 1, которую вы набираете перед междугородным звонком, — это «междугородный код». Это неверно. Цифра 1 — это международный код страны для NANP. Имейте это в виду, если Вы пришлете свой номер телефона кому-то в другой стране, получатель может не знать ваш код страны и, таким образом, не сможет позвонить вам только с вашим кодом города и номером телефона. Ваш полный номер телефона с кодом страны +1 NPA NXX XXXX (где NPA-ваш код города) — например, +1 416 555 1212.

Остались вопросы?

Я - Компаниец Никита, менеджер компании Voxlink. Хотите уточнить детали или готовы оставить заявку? Укажите номер телефона, я перезвоню в течение 3-х секунд.

VoIP оборудование


ближайшие курсы

10 доводов в пользу Asterisk

Распространяется бесплатно.

Asterisk – программное обеспечение с открытым исходным кодом, распространяется по лицензии GPL. Следовательно, установив один раз Asterisk вам не придется дополнительно платить за новых абонентов, подключение новых транков, расширение функционала и прочие лицензии. Это приближает стоимость владения станцией к нулю.

Безопасен в использовании.

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

Надежен в эксплуатации.

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

Гибкий в настройке.

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

Имеет огромный функционал.

Во многом именно Asterisk показал какой должна быть современная телефонная станция. За многие годы развития функциональность Asterisk расширилась, а все основные возможности по-прежнему доступны бесплатно сразу после установки.

Интегрируется с любыми системами.

То, что Asterisk не умеет сам, он позволяет реализовать за счет интеграции. Это могут быть интеграции с коммерческими телефонными станциями, CRM, ERP системами, биллингом, сервисами колл-трекинга, колл-бэка и модулями статистики и аналитики.

Позволяет телефонизировать офис за считанные часы.

В нашей практике были проекты, реализованные за один рабочий день. Это значит, что утром к нам обращался клиент, а уже через несколько часов он пользовался новой IP-АТС. Безусловно, такая скорость редкость, ведь АТС – инструмент зарабатывания денег для многих компаний и спешка во внедрении не уместна. Но в случае острой необходимости Asterisk готов к быстрому старту.

Отличная масштабируемость.

Очень утомительно постоянно возвращаться к одному и тому же вопросу. Такое часто бывает в случае некачественного исполнения работ или выбора заведомо неподходящего бизнес-решения. С Asterisk точно не будет такой проблемы! Телефонная станция, построенная на Asterisk может быть масштабируема до немыслимых размеров. Главное – правильно подобрать оборудование.

Повышает управляемость бизнеса.

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

Снижает расходы на связь.

Связь между внутренними абонентами IP-АТС бесплатна всегда, независимо от их географического расположения. Также к Asterisk можно подключить любых операторов телефонии, в том числе GSM сим-карты и настроить маршрутизацию вызовов по наиболее выгодному тарифу. Всё это позволяет экономить с первых минут пользования станцией.