Asterisk™: будущее телефонии Второе издание
Шрифт:
• Открыть описатели файла для STDIN, STDOUT и STDERR (в более новых версиях PHP один или более этих описателей файла уже могут быть открыты; в предыдущем фрагменте кода показано, как сделать это красиво для большинства версий PHP).
• Прочитать переменные из STDIN, используя функцию fgets.
• Использовать функцию fwrite для записи данных в STDOUT и STDERR.
• Всегда вызывать функцию fflush после записи в STDOUT или STDERR.
Библиотека AGI для PHP
Для более продвинутого программирования AGI
Написание сценариев 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 = %s\n" % (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
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 %d\n" % (prompt, timelimit, digcount)) sys.stderr.flush
sys.stdout.write("GET DATA %s %d %d\n" % (prompt, timelimit, digcount)) sys.stdout.flush
result = sys.stdin.readline.strip result = checkresult(result) sys.stderr.write("digits are %s\n" % 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);