Чтение онлайн

ЖАНРЫ

Asterisk™: будущее телефонии Второе издание
Шрифт:

Теперь мы уже рассмотрели два разных языка программирования с целью продемонстрировать, что общего в написании сценария AGI на PHP и Perl и чем они отличаются. При создании сценария AGI на PHP помните, что необходимо:

• Запускать PHP с ключом -q; это отключает HTML в сообщениях об ошибках.

• Отключить ограничение по времени или задать для него приемлемое значение (более новые версии PHP автоматически отключают ограничение по времени при запуске PHP из командной строки).

• Отключить буферизацию вывода с помощью команды ob_implicit_ flush(false).

• Открыть

описатели файла для 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 = %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

по своему назначению практически идентична подпрограмме 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 %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);

Поделиться с друзьями: