Перейти к записям
Янв 4 / MyBlog-IT Admin

Переменные Asterisk | Стандартные канальные переменные Asterisk

Содержание [Скрыть]

Переменные Asterisk — общие понятия

Переменные используются в большинстве языков программирования и в языках написания сценариев. В Asterisk мы можем использовать переменные для упрощения диалплана, и для того, чтобы добавить логику в систему.
Переменная — это просто контейнер, который имеет имя и значение. Например, мы можем воспользоваться переменной с именем COUNT, значение которой будет равно трем. Позже мы покажем, каким образом можно управлять вызовами, пользуясь значением переменных. Но до этого необходимо получить несколько большее представление о переменных.
Регистр в именах переменных играет роль, поэтому COUNT обозначает переменную, отличающуюся от Count или count. Любая переменная канала, созданная системой Asterisk, будет иметь имя, состоящее полностью из заглавных букв. Но для имен переменных канала, которые создаете вы, можно использовать любую комбинацию заглавных и строчных букв по вашему усмотрению.

В Asterisk используются переменные двух типов: канальные переменные и глобальные переменные.

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

Что такое, канальные переменные? Ниже вы узнаете, почему они так важны, и как они упрощают вам жизнь.

Существует два уровня определения параметра, выполняемого в диалплане Asterisk, и задаваемого в файле extensions.conf.

1. Первый, и наиболее часто применяемый, заключается в замене имен переменных их значениями (подстановка значения вместо имени).

2. Кроме того, существует вычисление выражений, выполняемое в $[ .. ]. Оно будет описано ниже.

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

Стандартные канальные переменные Asterisk

Существует ряд переменных, определенных в Asterisk. Ниже приводится их список. Более подробная информация доступна в справочном тексте по каждому приложению. Все эти переменные имеют имена, написанные только ЗАГЛАВНЫМИ БУКВАМИ. Переменные, отмеченные символом *, являются встроенными функциями, их значения установить нельзя, они могут быть только считаны в диалплане. Попытка записать значение в такую переменную игнорируется без вывода сообщения.

Переменные, представленные в Asterisk 1.8 и далее:

${CDR(accountcode)} * — учетный код (если задан)
${BLINDTRANSFER} — имя канала с другой стороны слепого перевода звонка
${BRIDGEPEER} — соединенный пир
${BRIDGEPVTCALLID} — ID для PVT-вызова соединенного пира (для вызова SIP — ID вызова SIP)
${CALLERID(ani)} * — автоматическое определение номера (ANI) вызывающего (каналы PRI)
${CALLERID(ani2)} * дополнительная информация (ANI2) о номере вызывающего, также называемая OLI, или информация о линии вызова
${CALLERID(all)} * — ID вызывающего ${CALLERID(dnid)} * — Идентификатор набранного номера
${CALLERID(name)} * — Только имя из идентификатора вызывающего ${CALLERID(num)} * — Только номер из идентификатора вызывающего
${CALLERID(rdnis)} * — Сервис ID перенаправленного набора номера
${CALLINGANI2} * — ANI2 вызывающего (каналы PRI)
${CALLINGPRES} * — Представление ID вызывающего для входящих вызовов (каналы PRI)
${CALLINGTNS} * — Селектор транзитной сети (каналы PRI)
${CALLINGTON} * — Тип номера вызывающего (каналы PRI)
${CHANNEL} * — Имя текущего канала
${CONTEXT} * — Текущий контекст
${DATETIME} * — Текущие дата и время в формате DDMMYYYY-HH:MM:SS (функция устарела, рекомендуется использовать вместо нее ${STRFTIME(${EPOCH},,%d%m%Y-%H:%M:%S)}) ${DB_RESULT} — результирующее значение функции диалплана DB_EXISTS()
${EPOCH} * — Текущий стиль эры Unix
${EXTEN} * — Текущее расширение
${ENV(VAR)} — Переменная окружения VAR
${GOTO_ON_BLINDXFR} — Переключение на заданный контекст / расширение / приоритет после слепого переключения (При задании этой переменной в диалплане вместо символов / используйте символ ^, чтобы разделить контекст/расширение/приоритет)
${HANGUPCAUSE} * — Причина прерывания звонка в Asterisk (входного/выходного)
${HINT} * — Подсказки канала для данного расширения
${HINTNAME} * — Предполагаемое имя ID вызывающего для данного расширения
${INVALID_EXTEN} — Ошибочное расширение вызова (используется в расширении «i»)
${LANGUAGE} * — Текущий язык (функция устарела, используйте ${CHANNEL(language)})
${LEN(VAR)} — Длина строки VAR (целое) ${PRIORITY} * — Текущий приоритет в диалплане
${PRIREDIRECTREASON} — Причина перевода на PRI, если был произведен перевод вызова.
${TIMESTAMP} * — Текущие дата и время в формате YYYYMMDD-HHMMSS (функция устарела, используйте ${STRFTIME(${EPOCH},,%Y%m%d-%H%M%S)})
${TRANSFER_CONTEXT} — Контекст переведенного вызова
${FORWARD_CONTEXT} — Контекст направленного вызова
${DYNAMIC_PEERNAME} — Имя канала с другой стороны при использовании динамической характеристики
${UNIQUEID} * — Уникальный идентификатор текущего вызова
${SYSTEMNAME} * — Значение опции systemname в asterisk.conf
${ENTITYID} * — Глобальный ID элемента. Устанавливается автоматически, или выбирается из asterisk.conf

Параметры в кавычках

1exten => s,5,BackGround,blabla

Параметр (blabla) может быть взят в кавычки («blabla»). В этом случае, запятая не является ограничителем поля. Однако в данном примере двойные кавычки будут переданы в команду Background.

Кроме того, в кавычки могут быть взяты символы, управляющие подстановкой переменных, вычислением выражений и т.п. (см. ниже). Например, чтобы буквально использовать символ $ в строке «$1231″, следует взять его в кавычки с символом переключения. Специальными символами, которые должны браться в кавычки, являются [ ] $ » \. (для написания самого символа \ нужно использовать обратный слеш.)

Эти двойные кавычки и символы переключения вычисляются на уровне, на котором Asterisk распознает файл конфигурации.

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

Установка и использование значений канальных переменных

Переменные могут входить в строки параметров. Имена переменных представляют собой произвольные строки. Они хранятся в соответствующей структуре канала. Для того чтобы установить значение переменной, необходимо сделать следующее:

1exten => 1,2,Set(имя_переменной=значение)

Значение переменной можно использовать в любом месте, задав ${имя_переменной}.

Ниже приводится простой пример.

1exten => 1,1,Set(COUNT=3)
2exten => 1,n,SayNumber(${COUNT})

Во второй строке примера Asterisk заменит текст ${COUNT} значением переменной COUNT, в результате чего будет выполнен вызов SayNumber (3).
В другом примере, для конкатенации значений строк $varname2 и $varname3 с сохранением результата в переменной $varname1, нужно выполнить следующее:

1exten => 1,2,Set(varname1=${varname2}${varname3})

Существует два способа обращаться к переменной — ссылка по имени, и ссылка по значению. Для обращения к переменной по имени (например, в качестве аргумента функции, которая требует переменную) просто указывается имя переменной. Для того чтобы использовать значение переменной, следует имя переменной заключить в ${}. Например, Set принимает в качестве первого аргумента (перед знаком =) имя переменной, поэтому:

1exten => 1,2,Set(varname1=varname2)
2exten => 1,3,Set(${varname1}=value)

В приведенном примере в переменную «varname1″ заносится значение «varname2″, а в переменную «varname2″ заносится значение «value». Фактически, все вхождения последовательности ${here} будут заменены значением переменной «here».

Однократное наследование

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

1exten = 1234,1,Set(_FOO=bar)

Множественное наследование

Если у имени переменной в канале используется префикс «__» (два символа подчеркивания), то переменная наследуется, и в новом канале префикс остается неизменным. Следовательно, любой канал, созданный в новом канале, также получит доступ к переменной с префиксом «__», обеспечивая неограниченное наследование.

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

1exten = 1234,1,Set(__FOO=bar)

Выбор символов из переменных

Формат выбора символов из значения переменной может быть выражен следующим образом:

1${имя_переменной [:смещение[:длина]]}

Если вы хотите удалить первые N символов из строки, представляющей значение переменной, задайте только двоеточие и число символов, пропускаемых с начала строки.

1; Удаление первого символа расширения и присвоение результата переменной "number"
2exten => _9X.,1,Set(number=${EXTEN:1})

Если мы набираем номер 918005551234, то значение, сохраненное в переменной ‘number’ будет равно 18005551234. Это полезно в ситуациях, когда мы требуем от пользователя набирать номер для доступа к внешней линии, но не хотим передавать первую цифру.

Если вы используете отрицательное смещение, то Asterisk начнет отсчет с конца строки, и затем выберет все, после новой позиции. В следующем примере, переменной ‘number’ будет присвоено значение 1234 (если мы набрали номер 918005551234).

1; Удаление всех символов, кроме последних четырех в набранном номере
2exten => _9X.,1,Set(number=${EXTEN:-4})

Также можно ограничить число символов, которые мы хотим использовать, начиная с нашей позиции смещения. Это делается заданием второго двоеточия и количества символов в значение переменной. В следующем примере переменной ‘number’ будут присвоены цифры 555.

1;Сохранение только средних цифр 555 из строки 918005551234 
2exten => _9X.,1,Set(number=${EXTEN:5:3})

Значение длины также можно использовать и при задании отрицательного смещения. Это может быть полезным в случае, когда общая длина строки неизвестна, но известны ее замыкающие символы. В следующем примере, переменной ‘number’ будут присвоены цифры 555, даже если строка начинается с количества символов, превышающим предполагаемое (в отличие от предыдущего примера).

1; Сохранение в переменной 'number' средних цифр
2exten => _9X.,1,Set(number=${EXTEN:-7:3})

Если указывается отрицательная длина строки, то Asterisk удалит это количество символов от конца строки.

1; Присвоить переменной 'pin' все, кроме последнего #.
2exten => _XXXX#,1,Set(pin=${EXTEN:0:-1})

Выражения

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

1exten => 1,1,Set(lala=$[1 + 2])
2exten => 1,2,Set(koko=$[2 * ${lala}])

значением переменной koko будет «6», а затем,

1exten => 1,1,Set,(lala=$[ 1 + 2 ])

будет выполняться, как и ожидалось. Дополнительные пробелы игнорируются.

Пробелы в значениях переменных

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

1exten => s,6,GotoIf($[ "${CALLERID(name)}" : "Privacy Manager" ]?callerid-liar,s,1:s,7)

Значение переменной CALLERID (name) могла быть равно «DELOREAN MOTORS» (с пробелом), но в приведенном примере, выражение получит значение

«DELOREAN MOTORS» : «Privacy Manager»

что даст значение 0.

Использование данного примера без кавычек приведет к значению выражения

DELOREAN MOTORS : Privacy Manager

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

Операторы

Ниже перечисляются операторы в порядке увеличения приоритета. Операторы с одинаковым приоритетом объединяются в символы { }.

выражение1 | выражение2
Возвращает значение выражения1, если ни одно из этих выражений не имеет нулевое значение или пустую строку. В противном случае возвращает значение выражения2.

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

выражение1 {=, >, >=, <, <=, !=} выражение2
Если оба выражения числовые, то оператор возвращает результат сравнения чисел с плавающей точкой. В противном случае возвращается результат сравнения строк, используя локализацию схемы сортировки. Результат каждого сравнения равен 1, если указанное отношение выполняется, или равен 0 в противном случае.

выражение1 {+, -} выражение2
Возвращает результат сложения или вычитания аргументов, имеющих числовые значения с плавающей точкой.

выражение1 {*, /, %} выражение2
Возвращает результат умножения, деления или остатка от деления аргументов, имеющих числовые значения с плавающей точкой.

— выражение1
Возвращает результаты вычитания выражения1 из 0. Это унарный оператор, он вычисляется справа налево, и имеет такой же приоритет, как и оператор !

! выражение 1
Возвращает результат логического дополнения выражения1. Другими словами, если выражение1 равно 0, пустой строке, или строке «0», то возвращается 1. В противном случае возвращается 0. Данный оператор имеет такой же приоритет, как и унарный оператор -. Он также вычисляется справа налево.

выражение1 : выражение2
Данный оператор сопоставляет выражение1 с выражением2, которое должно быть регулярным выражением. Регулярное выражение сцепляется с началом строки при помощи неявной `’. Если сопоставление проходит успешно, и регулярное выражение содержит хотя бы одно регулярное подвыражение `’, то возвращается строка, соответствующая `\1′. В противном случае оператор возвращает количество сопоставленных символов. Если сопоставление не проходит, и регулярное выражение содержит регулярное подвыражение, то возвращается пустая строка. Иначе, возвращается 0.
Обычно, двойные кавычки, обрамляющие строку, остаются в качестве части строки. Для оператора «:» это катастрофично. Следовательно, перед сопоставлением с регулярным выражением начальная и конечная кавычки должны быть удалены как из строки, так и из регулярного выражения.

выражение1 =~ выражение2
То же самое, что и оператор «:», за исключением того, что сопоставление не привязано к началу строки. Приносим извинения за схожесть операторов в других языках программирования. Операторы «:» и «=~» имеют один и тот же приоритет.

выражение1 ? выражение2 :: выражение3
Традиционный условный оператор. Если выражение1 является числом со значением 0 (false), то результатом становится значение выражения3. В противном случае результатом будет значение выражения2. Если выражение1 является пустой строкой, или состоит из двух кавычек («»), то в качестве результата берется значение выражения3. В противном случае, результатом станет значение выражения2. В Asterisk будут «вычисляться» все три выражения. Если выражение1 имеет значение «true», то в качестве результат будет использовано значение выражения3, иначе, в качестве результата будет использовано значение выражения3. Этот оператор имеет самый низкий приоритет.

выражение1 ~~ выражение2
Оператор конкатенации. Оба выражения вычисляются, и преобразуются в строки, с которых убираются обрамляющие двойные кавычки. Затем эти строки сцепляются в одну строку без пробелов между ними. Данный оператор введен в версии 1.6.0. Он не требуется в существующем коде extensions.conf. Благодаря способу, которым Asterisk вычисляет конструкции [] (рекурсивно, снизу вверх), при вычислении содержимого [] не существует ничего. То есть, элементы языка уже обычно прошли подстановку к моменту вычисления. Но в AEL различные выражения вычисляются в исходном виде, и [] собирается и трактуется, как набор лексических элементов. Кроме того, в AEL, никакие два элемента не могут находиться друг с другом без оператора, разделяющего их. Поэтому в AEL конкатенация должна задаваться в выражениях явным образом. Этот новый оператор будет играть свою роль в будущем, когда выражения (конструкторы) сливаются в одной грамматике. Для группирования операторов обычным образом используются скобки. Приоритет операторов применяется так же, как и в С и в других языках, порожденных от C.

Числа с плавающей точкой

В версии 1.6 и выше мы перешли к вычислению выражений $[…] при помощи чисел с плавающей точкой, вместо использования целых чисел. Мы используем, везде, где возможно, числа формата ‘long double’. Этот формат обеспечивает 12-байтовые числа с точностью в 16 цифр. Для задания констант с плавающей точкой следует использовать формат D.D, где D представляет строку цифр по основанию 10. То есть, вы можете написать, скажем, 0.10, но не можете писать .10 или 20., и мы надеемся, что это не очень жесткое ограничение! Числа с плавающей точкой преобразуются в строки при помощи формата ‘%g’/’%Lg’ функции printf. Это позволяет числам «выглядеть» целыми, когда учитывается их целочисленное поведение. Если вы хотите, чтобы число 1/4 было вычислено, как 0, вам теперь не требуется использовать функцию TRUNC(1/4). Список всех возможностей отсечения/округление приведен в следующем параграфе.

Встроенные функции выражения2

В версии 1.6 и выше мы обновили выражения $[], чтобы они обрабатывали числа с плавающей точкой. Из-за этого, пользователи, рассчитывающие на целочисленное поведение, будут испытывать неудобство. Чтобы обеспечить возможность получения тех же результатов, к ядру программы распознавания выражения2 были добавлены некоторые функции отсечения и округления дробной части. Действительно, функции диалплана могут быть вызваны из выражений $[..] без использования операторов ${…}. Единственная проблема может быть связана с тем, что аргументы этих функций должны быть заданы через запятую. Например, если вы попытаетесь вызвать функцию MATH, и попробуете ввести 3 + MATH(7*8), то разбор выражения заменит 7*8 на 56, и скорее всего функция MATH сообщит, что ее входные параметры не имеют смысла. Мы также предоставили доступ к большинству функций с плавающей точкой из библиотеки C (хотя и не ко всем таким функциям). Хотя мы не ожидаем, что кто-то будет проводить анализ Фурье в диалплане, мы также не хотим и препятствовать этому. Ниже приведен список «встроенных» функций в выражение2. Все остальные функции диалплана доступны простым их вызовом (только для чтения). Другими словами, вам не требуется окружать выражения $[…] обрамлением ${…}. Но не торопитесь с выводами — вам все еще необходимо обрамлять фигурными скобками имена переменных!

  • COS(x) х задается в радианах. Результат принадлежит интервалу от -1 до 1.
  • SIN(x) х задается в радианах. Результат принадлежит интервалу от -1 до 1. TAN(x) x задается в радианах.
  • ACOS(x) x должен быть в интервале от -1 до 1.
  • ASIN(x) x должен быть в интервале от -1 до 1.
  • ATAN(x) возвращает значение арктангенса в радианах в диапазоне от -PI/2 до PI/2.
  • ATAN2(x,y) возвращает результат, похожий на ATAN (x/y), за исключением того, что для определения квадранта, в который попадает результат, учитываются знаки обоих аргументов. Результат возвращается в радианах в диапазоне от -PI до PI.
  • POW(x,y) возвращает значение x, возведенное в степень y.
  • SQRT(x) возвращает квадратный корень из х.
  • FLOOR(x) округляет x до ближайшего меньшего целого.
  • CEIL(x) округляет x до ближайшего большего целого.
  • ROUND(x) округляет х до ближайшего целого. Числа, лежащие строго посредине между двумя целыми, округляются в сторону от нуля.
  • RINT(x) округляет х до ближайшего целого. Числа, лежащие строго посредине между двумя целыми, округляются в сторону ближайшего четного целого.
  • TRUNC(x) округляет х до ближайшего целого, не превышающего х по абсолютному значению.
  • REMAINDER(x,y) вычисляет остаток от деления x на y, Возвращаемое значение равно x — n*y, где n равно значению x/y, округленному до ближайшего целого. Если частное от деления равно 1/2, то оно округляется до ближайшего четного целого.
  • EXP(x) возвращает e в степени x.
  • EXP2(x) возвращает 2 в степени x.
  • LOG(x) возвращает натуральный логарифм x.
  • LOG2(x) возвращает логарифм x по основанию 2.
  • LOG10(x) возвращает логарифм x по основанию 10.

Условия

Существует единственное применение условий — условный оператор перехода:

1exten => 1,2,GotoIf(условие? метка1:метка2)

Если условие истинно, то осуществляется переход к метке1, иначе управление передается к метке2. Метки интерпретируются в точности так же, как и в обычной команде goto. «Условие» представляет собой строку. Если эта строка пустая, или равна «0», то условие считается ложным. В противном случае условие считается истинным. Условие может использоваться вместе с синтаксисом выражения, описанным выше, например:

1exten => 1,2,GotoIf($[${CALLERID(all)} = 123456]?2,1:3,1)

Пример использования:

1exten => s,2,Set(vara=1) 
2exten => s,3,Set(varb=$[${vara} + 2])
3exten => s,4,Set(varc=$[${varb} * 2])
4exten => s,5,GotoIf($[${varc} = 6]?99,1:s,6)

Ошибки грамматического разбора

Синтаксические ошибки теперь выводятся в три строки. Если файл extensions.conf содержит строку типа

1exten => s,6,GotoIf($[ "${CALLERID(num)}" = "3071234567" & & "${CALLERID(name)}" : "Privacy Manager" ]?callerid-liar,s,1:s,7)

то вы можете увидеть следующее сообщение об ошибке в /var/log/asterisk/messages:

Jul 15 21:27:49 WARNING[1251240752]: ast_yyerror(): syntax error: parse error, unexpected TOK_AND, expecting TOK_M INUS or TOK_LP or TOKEN; Input: "3072312154" = "3071234567" & & "Steves Extension" : "Privacy Manager" ^ 

Журнал сообщает вам о том, что была обнаружена синтаксическая ошибка. Он также сообщает вам (в стандартном формате), что неожиданно обнаружен элемент «AND» (&), в то время как ожидался MINUS, LP (левая скобка), или простой лексический элемент (с трока или число). В следующей строке показано вычисленное выражение, и в последней строке символом «^» отмечено место в выражении, где грамматический разбор обнаружил ошибку.

Пустые строки

Для проверки, является ли строка пустой, можно использовать один из двух способов:

1exten => _XX.,1,GotoIf($["${calledid}" != ""]?3)

или:

1exten => _XX.,1,GotoIf($[foo${calledid} != foo]?3)

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

Предупреждения в выражениях

Если вам необходимо выполнять со строками сложные действия, то выражения в Asterisk, скорее всего, НЕ являются лучшим способом делать это. Для этой цели прекрасную возможность предоставляют сценарии AGI, давая доступ к полной мощности того языка, который вам нужен, будь это Perl, C, C++, Cobol, RPG, Java, Snobol, PL/I, Scheme, Common Lisp, Shell scripts, Tcl, Forth, Modula, Pascal, APL, ассемблер, и т.д.

Советы по отладке выражений

Существуют два подхода, которые вы можете использовать для помощи в отладке $[ ] в вашем файле extensions.conf. Первый, и наиболее упрощенный подход заключается в использовании команды

1make testexpr2

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

1testexpr2 '2*2+2/2'

В этом же каталоге вы можете подать команду

1make check_expr

в результате выполнения которой будет создан небольшой исполнительный модуль. Он проверит файл, заданный в первом аргументе командной строки, пытаясь найти любые выражения, которые вызовут проблемы, когда вы перейдете к flex-2.5.31. Этот способ первоначально был разработан для помощи в обнаружении несовместимостей при переходе от версий, предшествующим 2.5.31, к обновленным версиям грамматического разбора. Затем к check_expr были добавлены дополнительные возможности, которые увеличили его общую применимость. Теперь эта утилита выполняет простые вычисления всех переменных, а затем передает их в грамматический разбор выражений $[]. Если в процессе грамматического разбора будут обнаружены ошибки, сообщения о них будут помещены в журнал. Вы можете использовать check_expr для быстрой проверки выражений в вашем файле extensions.conf, чтобы убедиться в том, что все выражения проходят грубую синтаксическую проверку. «Простое» вычисление переменных заменяет ссылки на переменную ${varname} значением ‘555’. Вы можете вместо 555 использовать значения переменных, введя аргументы var=val после имени файла в командной строке. Таки образом,

1check_expr /etc/asterisk/extensions.conf CALLERID(num)=3075551212 DIALSTATUS=TORTUE EXTEN=121

заменит все вхождения переменной ${CALLERID(num)} на 3075551212, все вхождения переменной ${DIALSTATUS на ‘TORTURE’, и все вхождения переменной ${EXTEN} на ‘121’. Если в ссылке на переменную появятся уточнения, типа ${EXTEN:2}, то замена работать не будет. Все, что находится в ${…} должно совпадать точно. Поэтому, для подстановки вместе ${EXTEN:2} лучше написать

1check_expr /etc/asterisk/extensions.conf CALLERID(num)=3075551212 DIALSTATUS=TORTURE EXTEN:2=121

В потоке stdout вы увидите что-то вроде:

OK - $[ "${DIALSTATUS}" = "TORTURE" | "${DIALSTATUS}" = "DONTCALL" ] at line 416

В журнальном файле expr2_log, который будет при этом сгенерирован, вы увидите текст:

line 416, evaluation of $[ "TORTURE" = "TORTURE" | "TORTURE" = "DONTCALL" ] result: 1

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

Переменные, представленные в Asterisk 11 и выше:

${AGIEXITONHANGUP} — устанавливается в 1 для обеспечения поведения вызова в AGI, совпадающего с поведением в версии 1.4, где сценарий AGI немедленно завершается по обнаружению прекращения вызова в канале.
${CALENDAR_SUCCESS} * — Состояния функции CALENDAR_WRITE. Устанавливается в 1, если эта функция завершилась успешно. В противном случае возвращает 0.
${SIP_RECVADDR} * — адрес, откуда был получен запрос SIP MESSAGE
${VOICEMAIL_PLAYBACKSTATUS} * — состояние приложения VoiceMailPlayMsg. Если голосовая почта была проиграна успешно, возвращается SUCCESS, в противном случае {{FAILED}

Основы глобальных переменных

Глобальные переменные, это такие переменные, которые не привязаны к одному каналу. Они действуют для всех вызовов в системе. Эти переменные имеют глобальную область действия. Существует два пути установки глобальной переменной. Первый способ заключается в объявлении переменной в секции [globals] файла extensions.conf, следующим образом:

1[globals]
2MYGLOBALVAR=somevalue

Кроме того можно определить глобальные переменные в логике диалплана, используя функцию диалплана GLOBAL() с приложением Set(). Для этого просто используйте следующий синтаксис:

1exten=>6124,1,Set(GLOBAL(MYGLOBALVAR)=somevalue)

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

Основы работы с переменными

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

${variable[:skip[docs::length]}

Необязательное поле skip сообщает Asterisk, сколько цифр надо убрать вначале значения. Например, если значение NUMBER было установлено равным 98765, то ${NUMBER:2} сообщит Asterisk, что нужно убрать первые две цифры и вернуть значение 765. Если поле skip имеет отрицательное значение, то Asterisk вернет указанное количество цифр, расположенное в конце значения. Например, если значение NUMBER равно 98765, то ${NUMBER:-2} вернет две последние цифры, 65. Если указано необязательное поле length, то Asterisk вернет не больше указанного количества цифр. Например, если значение NUMBER равно 98765, то ${NUMBER:0:3} сообщит Asterisk, что не нужно предварительно пропускать никаких символов, но требуется вернуть только три символа с этой точки, то есть 987. А конструкция ${NUMBER:1:3} вернет 876.

Обработчики прекращения вызова

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

Замечания:

— Учтите, что момент, когда выполняются обработчики прекращения вызова по отношению к расширению h, не определен. Они могут выполниться как до, так и после расширения h.

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

— Обработчики прекращения вызова могут быть присоединены к любому вызову, использующему предварительные обработчики.

Предупреждения:

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

— Добавление обработчика вызова в расширении h или в процессе выполнения обработчика вызова, приводит к неопределенному поведению.

— Как и расширение h, обработчики прекращения вызова должны выполняться быстро, поскольку они находятся в последовательности действий прекращения со стороны вызова. Специфические протоколы драйвера канала, такие как ISDN и SIP могут оказаться неспособными обработать большие задержки, связанные с завершением последовательности операций прекращения вызова.

Приложения и функции диалплана

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

hangup_handler_push
Используется для присоединения к каналу обработчика прекращения вызова. same => n,Set(CHANNEL(hangup_handler_push)=[[context,]exten,]priority[(arg1[,...][,argN])]);
hangup_handler_pop
Используется для отсоединения от канала обработчика прекращения вызова. Возможна замена отсоединяемого обработчика другим обработчиком. same => n,Set(CHANNEL(hangup_handler_pop)=[[[context,]exten,]priority[(arg1[,...][,argN])]])
hangup_handler_wipe
Удаляет все обработчики прекращения вызова в канале. Возможно присоединение к каналу нового обработчика прекращения вызова. same => n,Set(CHANNEL(hangup_handler_wipe)=[[[context,]exten,]priority[(arg1[,...][,argN])]]);

Примеры

Добавление обработчика к каналу

В данном примере к каналу добавляются три обработчика: hdlr3, hdlr2, и hdlr1. Когда канал прекращает вызов, они буду вызваны в порядке, обратном тому, в котором были присоединены — вначале будет выполнен hdlr1, затем hdlr2, а затем hdlr3.

1; Расширение диалплана some
2same => n,Set(CHANNEL(hangup_handler_push)=hdlr3,s,1(args));
3same => n,Set(CHANNEL(hangup_handler_push)=hdlr2,s,1(args));
4same => n,Set(CHANNEL(hangup_handler_push)=hdlr1,s,1(args));
5; Продолжение расширения диалплана some
6[hdlr1] exten => s,1,Verbose(0, Executed First) same => n,Return()
7[hdlr2] exten => s,1,Verbose(0, Executed Second) same => n,Return()
8[hdlr3] exten => s,1,Verbose(0, Executed Third) same => n,Return()

Удаление и замена обработчиков прекращения вызова

В этом пример к каналу добавлены три обработчика : hdlr3, hdlr2, и hdlr1. Используя значение hangup_handler_pop функции CHANNEL, обработчик hdlr1 удаляется из стека обработчиков. Затем, используя значение hangup_handler_pop, обработчик hdlr2 заменяется обработчиком hdlr4. Когда канал прекрати вызов, будет вызван обработчик hdlr4, а затем будет выполнен hdlr3.

01; расширение диалплана some
02same => n,Set(CHANNEL(hangup_handler_push)=hdlr3,s,1(args));
03same => n,Set(CHANNEL(hangup_handler_push)=hdlr2,s,1(args));
04same => n,Set(CHANNEL(hangup_handler_push)=hdlr1,s,1(args));
05 
06; удаление hdlr1
07same => n,Set(CHANNEL(hangup_handler_pop))
08; замена hdlr2 на hdlr4
09same => n,Set(CHANNEL(hangup_handler_pop)=hdlr4,s,1(args));
10 
11; продолжение расширения диалплана some
12[hdlr1]
13exten => s,1,Verbose(0, Not Executed)
14same => n,Return()
15 
16[hdlr2]
17exten => s,1,Verbose(0, Not Executed)
18same => n,Return()
19 
20[hdlr3]
21exten => s,1,Verbose(0, Executed Second)
22same => n,Return()
23 
24[hdlr4]
25exten => s,1,Verbose(0, Executed First)
26same => n,Return()

Команды CLI

Один канал
core show hanguphandlers <chan>

Вывод Channel Handler
<имя канала>
<первый выполняемый обработчик>
<второй выполняемый обработчик>
<третий выполняемый обработчик>

Все каналы
core show hanguphandlers all

Вывод
Channel Handler <имя канала1>
<первый выполняемый обработчик>
<второй выполняемый обработчик>
<третий выполняемый обработчик> <имя канала2>
<первый выполняемый обработчик> <имя канала3>
<первый выполняемый обработчик>
<второй выполняемый обработчик>

В Asterisk 11 добавлены предварительные обработчики

Обзор

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

Существует два способа вызова предварительного обработчика:

— режим ‘B’ выполняет в канале вызывающего подпрограмму диалплана до того, как будут созданы каналы вызываемых номеров.

— режим ‘b’ выполняет подпрограмму диалплана на каждом канале вызываемого номера, после того как канал создан, но до того, как вызов размещен на оконечном устройстве.

Предварительные обработчики поддерживаются в приложениях Dial и FollowMe.

Предупреждения:

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

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

Синтаксис

Обработчики вызываются, с использованием такой же номенклатуры, как и другие опции (такие как M или U) в приложениях Dial или FollowMe, обеспечивая выполнение некоторой части диалплана.

1b([[context^]exten^]priority[(arg1[^...][^argN])])
2B([[context^]exten^]priority[(arg1[^...][^argN])])

Если контекст или расширение не заданы, то используются текущие значения канала вызывающего.

Примеры

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

SIP/foo вызывает SIP/bar, SIP/baz, или оба
SIP/foo — вызывающий
SIP/bar — вызываемый
SIP/baz — другой вызываемый

Пример 1 — выполнение предварительного обработчика в канале вызывающего

[default]
exten => s,1,NoOp()
same => n,Dial(SIP/bar,,B(default^caller_handler^1))
same => n,Hangup()
exten => caller_handler,1,NoOp()
same => n,Verbose(0, In caller pre-dial handler!)
same => n,Return()

Вывод CLI для примера 1

<SIP/foo-123> Dial(SIP/bar,,B(default^caller_handler^1))
<SIP/foo-123> Executing default,caller_handler,1
<SIP/foo-123> In caller pre-dial handler!
<SIP/foo-123> calling SIP/bar-124

Пример 2 – выполнение предварительного обработчика в канале вызываемого

[default]
exten => s,1,NoOp()
same => n,Dial(SIP/bar,,b(default^callee_handler^1))
same => n,Hangup()
exten => callee_handler,1,NoOp()
same => n,Verbose(0, In callee pre-dial handler!)
same => n,Return()

Вывод CLI примера 2

<SIP/foo-123> Dial(SIP/bar,,b(default^callee_handler^1))
<SIP/bar-124> Executing default,callee_handler,1
<SIP/bar-124> In callee pre-dial handler!
<SIP/foo-123> calling SIP/bar-124

Пример 3 – выполнение предварительного обработчика на нескольких каналах вызываемых

[default]
exten => s,1,NoOp()
same => n,Dial(SIP/bar&SIP/baz,,b(default^callee_handler^1))
same => n,Hangup()
exten => callee_handler,1,NoOp()
same => n,Verbose(0, In callee pre-dial handler!)
same => n,Return()

Вывод CLI для примера 3

<SIP/foo-123> Dial(SIP/bar&SIP/baz,,b(default^callee_handler^1))
<SIP/bar-124> Executing default,callee_handler,1
<SIP/bar-124> In callee pre-dial handler!
<SIP/baz-125> Executing default,callee_handler,1
<SIP/baz-125> In callee pre-dial handler!
<SIP/foo-123> calling SIP/bar-124
<SIP/foo-123> calling SIP/baz-125

 

 

Один комментарий

Оставить комментарий

Трекбэки и Пингбэки

  1. Конфигурация Asterisk extensions.conf | 2-IT
Оставить комментарий