Asterisk™: будущее телефонии Второе издание
Asterisk™: будущее телефонии Второе издание читать книгу онлайн
Внимание! Книга может содержать контент только для совершеннолетних. Для несовершеннолетних чтение данного контента СТРОГО ЗАПРЕЩЕНО! Если в книге присутствует наличие пропаганды ЛГБТ и другого, запрещенного контента - просьба написать на почту [email protected] для удаления материала
• Открыть описатели файла для STDIN, STDOUT и STDERR (в более новых версиях PHP один или более этих описателей файла уже могут быть открыты; в предыдущем фрагменте кода показано, как сделать это красиво для большинства версий PHP).
• Прочитать переменные из STDIN, используя функцию fgets.
• Использовать функцию fwrite для записи данных в STDOUT и STDERR.
• Всегда вызывать функцию fflush после записи в STDOUT или STDERR.
Библиотека AGI для PHP
Для более продвинутого программирования AGI на PHP, вероятно, пригодится проект PHPAGI, который можно найти по адресу http:// phpagi.sourceforge.net. Изначально он был написан Мэттью Ашамом (Matthew Asham) и дорабатывался несколькими членами сообщества разработчиков Asterisk.
Написание сценариев AGI на Python
Сценарий AGI, который мы напишем на Python, называется «Игра в вычитание». Источником идей для его написания стала программа на Perl, созданная Эдом Гаем (Ed Guy) и представленная им на конференции AstriCon в 2004 году. Эд рассказывал, в какой восторг он пришел от мощи и простоты Asterisk, когда обнаружил, что может написать короткий сценарий на Perl, чтобы помочь своей дочери с математикой. Поскольку мы уже написали Perl-программу, использующую AGI и Эд создал свою математическую программу на Perl, мы решили заняться реализацией этой задачи на Python! Итак, разберем наш сценарий на Python: #!/usr/bin/python
Данная строка указывает системе выполнять этот сценарий в интерпретаторе Python. Для небольших сценариев в эту строку можно добавить опцию -u, что обеспечит выполнение Python в режиме без буферизации. Однако это не рекомендуется для больших или часто используемых сценариев AGI, поскольку может сказаться на производительности системы. import sys import re import time import random
Здесь импортируются несколько библиотек, которые будут использоваться в сценарии AGI.
# Читаем и игнорируем среду AGI (читать до пустой строки)
env = {} tests = 0;
while 1:
line = sys.stdin.readline().strip()
if line == '': break
key,data = line.split(':') if key[:4] <> 'agi_':
# игнорируем ввод, который начинается не с agi_ sys.stderr.write("Did not work!n"); sys.stderr.flush() continue key = key.strip() data = data.strip() if key <> '':
env[key] = data
sys.stderr.write("AGI Environment Dump:n");
sys.stderr.flush()
for key in env.keys():
sys.stderr.write(" -- %s = %sn" % (key, env[key])) sys.stderr.flush()
Данный фрагмент кода читает переменные, передаваемые в сценарий из Asterisk, и сохраняет их в словарь env. Затем эти значения записываются в STDERR для целей отладки.
def checkresult (params): params = params.rstrip() if re.search('"200',params): result = re.search('result=(d+)',params) if (not result):
sys.stderr.write("FAIL ('%s')n" % params) sys.stderr.flush() return -1 else:
result = result.group(1)
#debug("Result:%s Params:%s" % (result, params)) sys.stderr.write("PASS (%s)n" % result) sys.stderr.flush() return result
else:
sys.stderr.write("FAIL (unexpected result '%s')n" % params)
sys.stderr.flush()
return -2
Функция checkresult по своему назначению практически идентична подпрограмме checkresult в примере AGI-сценария на Perl, который рассматривался ранее в этой главе. Она читает результат выполнения команды Asterisk, проводит синтаксический разбор результата и сообщает, была команда выполнена успешно или нет. def sayit (params):
sys.stderr.write("STREAM FILE %s ""n" % str(params)) sys.stderr.flush()
sys.stdout.write("STREAM FILE %s ""n" % str(params)) sys.stdout.flush()
result = sys.stdin.readline().strip() checkresult(result)
Функция sayit - это просто оболочка для команды STREAM FILE.
def saynumber (params):
sys.stderr.write("SAY NUMBER %s ""n" % params) sys.stderr.flush()
sys.stdout.write("SAY NUMBER %s ""n" % params) sys.stdout.flush()
result = sys.stdin.readline().strip() checkresult(result)
Функция saynumber - это просто оболочка для команды SAY NUMBER.
def getnumber (prompt, timelimit, digcount):
sys.stderr.write("GET DATA %s %d %dn" % (prompt, timelimit, digcount)) sys.stderr.flush()
sys.stdout.write("GET DATA %s %d %dn" % (prompt, timelimit, digcount)) sys.stdout.flush()
result = sys.stdin.readline().strip() result = checkresult(result) sys.stderr.write("digits are %sn" % result) sys.stderr.flush() if result:
return result else:
result = -1
Функция getnumber вызывает команду GET DATA для получения DTMF-вво- да от вызывающего абонента. Она используется в нашей программе для получения ответов абонента на поставленные задачи по вычитанию.
limit=20
digitcount=2
score=0
count=0
ttanswer=5000
Здесь выполняется задание исходных значений нескольким переменным, которые будут использоваться в программе.
starttime = time.time() t = time.time() - starttime
В этих строках переменной starttime задается текущее время, а переменной t - начальное значение 0. Переменная t будет использоваться для отсчета времени с момента запуска сценария AGI в секундах.
sayit("subtraction-game-welcome")
Далее, мы рады приветствовать абонента в нашей игре на вычитание.
while ( t < 180 ):
big = random.randint(0,limit+1) big += 10
subt= random.randint(0,big) ans = big - subt count += 1
#постановка задачи:
sayit("subtraction-game-next");
saynumber(big);
sayit("minus");
saynumber(subt);
res = getnumber("equals",ttanswer,digitcount);
if (int(res) == ans) : score+=1
sayit("subtraction-game-good"); else :
sayit("subtraction-game-wrong"); saynumber(ans);
t = time.time() - starttime Это сердце сценария AGI. При циклическом выполнении данного фрагмента кода абоненту в течение 180 с предлагаются задачи на вычитание. В начале цикла берутся два случайных числа и вычисляется их разность. Затем абоненту предлагается решить эту задачу. Читается ответ абонента. Если ответ неверен, дается правильный ответ. pct = float(score)/float(count)*100; sys.stderr.write("Percentage correct is %dn" % pct) sys.stderr.flush() sayit("subtraction-game-timesup") saynumber(score) sayit("subtraction-game-right") saynumber(count) sayit("subtraction-game-pct") saynumber(pct)
После того как абонент закончил решение примеров, ему сообщается, сколько баллов он набрал.
Как видите, при написании сценариев AGI на Python следует помнить такие основные моменты:
• Выходной буфер должен очищаться после каждой записи. Это гарантирует, что AGI-программа не зависнет из-за того, что Asterisk будет ожидать освобождения буфера для записи, а Python - ответа от Asterisk.
• Чтение данных из Asterisk осуществляется с помощью команды sys.stdin.readline.
• Запись команд в Asterisk выполняется с помощью команды sys. stdout.write. После записи не забывайте вызывать sys.stdout.flush.
Библиотека AGI для Python
Если вы планируете много работать с Python для AGI, вероятно, вам пригодится модуль Python Pyst, созданный Карлом Патлэндом (Karl Putland). Его можно найти по адресу http://sourceforge.net/projects/pyst.
Отладка в AGI
Отладка программ AGI, как и любых других программ, может приводить в уныние. К счастью, при отладке сценариев AGI есть два преимущества. Во-первых, поскольку весь обмен информацией между Asterisk и программой AGI происходит через STDIN и STDOUT (и конечно, STDERR), у вас должно получиться выполнять сценарий AGI непосредственно из операционной системы. Во-вторых, в Asterisk есть удобная команда для отображения всех взаимодействий между ним и сценарием AGI - agi debug.