First time here? Check out the FAQ!

Пожалуйста, войдите здесь. Часто задаваемые вопросы О нас
Задайте Ваш вопрос

Как реализовать цикл в диалплане

1

Здравствуйте. Есть строка вида

a1-a2;b1-b2;c1-c2;d1-d2......

Нужно пробежаться по ней в цикле. Не смог придумать ничего умнее AGI.

#!/usr/bin/perl
use Asterisk::AGI

$AGI
= new Asterisk::AGI;
my %input = $AGI->ReadParse();
my @list = split(';', $input{'arg_1'});
my @token;

my $index = $AGI->get_variable('index');

if ($index < scalar(@list)) {
  @token
= split('-', $list[$index]);
  $AGI
->set_variable('X1', $token[0]);
  $AGI
->set_variable('X2', $token[1]);
} else {
  $AGI
->set_variable('break', 'true');
}

exit 0;

Диалплан

exten => _X.,1,Noop
  same
=> n,Set(input_string=a1-a2;b1-b2;c1-c2;d1-d2) ; строка вытягивается из БД
  same
=> n,Set(index=0)
  same
=> n,Set(break=false)
  same
=> n(loop),AGI(blah-blah.pl,${input_string)
  same
=> n,GotoIf($["${break}"="true"]?end)
 
... тут манипулируем содержимым очередного цикла итерации (X1, X2)
  same
=> n,Set(index=$[${index}+1])
  same
=> n,Goto(loop)
  same
=> n(end),Noop

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

спросил Jul 17 '13

bb2kp Gravatar bb2kp
105 7 1 8

3 Ответа

4

в астриске есть функция CUT

работает прекрасно

ораганизовываете цикл в котором просто берете следующую подстрочку.

agi не нужен.

пример я писал вот тут http://asterisk-support.ru/question/13916/dialplan-balansirovka-i-tsikl-mezhdu-trankami/#19951

а порстейший цикл с использованием cut выглядит вот так

exten => s,1,Set(var=1-2-3-4-5)
exten
=> s,n(loop),Set(val=${CUT(var,-,1)})
exten
=> s,n,Set(var=${CUT(var,-,2-)})
exten
=> s,n,Noop(тело цикла, переменные var=${var} val=${val})
exten
=> s,n,GotoIF($[ "${var}" == "" ]?end_of_loop)
exten
=> s,n,Goto(loop);
exten
=> s,n(end_of_loop),Noop(" тут пишите что дальше делать")

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

А еще таких примеров(правда большей частью выполненых на 3ку) полно в диалплане freepbx. Полезно его почитать.

ссылка удалить спам редактировать

ответил Jul 17 '13

meral Gravatar meral flag of Ukraine
23347 24 20 177
http://pro-sip.net/

обновил Jul 17 '13

Comments

Подскажите как, я только хотел писать вопрос и увидел этот, можно ли строку неизвестного размера например 101-102-103-104... Как то в цикле обходить и вызывать DIAL для каждого номера. Идея в том что из базы вытягивается набор сип номеров который нужно обзвонить. Вот только загвоздка в том что я не знаю заранее размера строки, есть ли способ распарсить строку неизвестного размера по заданому разделителю и получить каждый элемент этой строки для передачи функции Dial ?

godlike (Jul 17 '13)edit

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

bb2kp (Jul 17 '13)edit
1

крутить func POP не сработает? здесь http://www.voip-info.org/wiki/view/Asterisk+func+fieldqty

octopas (Jul 17 '13)edit

2bbkp хз. у меня все работает. в данном примере вообще не важна длина строки.

meral (Jul 17 '13)edit

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

meral (Jul 17 '13)edit

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

godlike (Jul 17 '13)edit

че там непонятного? он берет самый первый аргумент и строке присваивает все остальные(второй и дльше). и так пока строка не кончится.

meral (Jul 18 '13)edit

2meral в добавлении и в качестве реторики и новичкам на заметку - по поводу полной грамматики диалплана - goto это общепризнанный анти-паттерн в программировании, используется повсеместно в астерисковском диалплане что показывает что ничего более-менее комплексного без AEL/AGI/lua для * реализовывать не рекомендуется (а с учетом того что рано или поздно грамотному админу скорее всего придется - это все равно что переучиваться с бейсика на C). смысл использовать 3 оператора где можно заменить одним ...

octopas (Jul 18 '13)edit

давайте не путать гармматики и языки высокого уровня. диаплан - это граматика. вы бы еще посетовали что ни в одном процессоре в ассемблере нету команд типа repeat/function. а смысл использовать cut вместо pop - совместимость. но вам она не нужна, успокойтесь.

meral (Jul 19 '13)edit
0

Вот мой код с циклом слегка модифицированный и исправленный (под 1.8): Может кому пригодиться:

exten => X.,1,Macro(inbound,101-106-109-110-125-130)

[macro-inbound]
exten
=> s,1,Set(i=0)
same
=> n(loop),Set(i=$[${i} + 1])
same
=> n,NoOp(${i})
same
=> n,Set(donow=${CUT(ARG1,-,${i})})
same
=> n,GotoIF($[ "${donow}" == "" ]?end)
same
=> n,Set(numlist=${numlist}SIP/${donow}&)
same
=> n,Goto(s,loop)
same
=> n(end),Set(nums=${numlist:0:-1})
same
=> n,NoOp(--------------- ${nums})
same
=> n,Dial(${nums},60)

Парсяться номера, и звонят одновременно.

ссылка удалить спам редактировать

ответил Mar 26 '15

etpu Gravatar etpu
1 1

обновил Mar 26 '15

Comments

WHILE для слабаков?

zzuz (Mar 26 '15)edit

а чем он лучше предыдущего?

meral (Mar 26 '15)edit

Видимо тем , что нагружен излишними переменными. Так выглядит эпичней и громадней.

zzuz (Mar 26 '15)edit
0

Согласен, While всё-таки более по-человечески, а вместо CUT, функция SHIFT лучше подойдет в данном случае:

same => n,while ("${SET(var=${SHIFT(array)})}" != "")
same
=> n,Verobse(${var})
same
=> n,EndWile                               }

в ael ещё проще:

while ("${SET(var=${SHIFT(array)})}" != "") 
   
{
       
Verbose(${var});
   
}
ссылка удалить спам редактировать

ответил Apr 3 '15

kolos Gravatar kolos
1 1

обновил Apr 3 '15

Comments

ну и нафига все это? вы когда исползуете новые конструкции, не забывайте добавить с какой версии это вообще работает. вы тут подразумеваете array, который явно явлется излишеством для задачи. и вообще на дату темы смотрели?

meral (Apr 3 '15)edit

Ваш ответ

Please start posting your answer anonymously - your answer will be saved within the current session and published after you log in or create a new account. Please try to give a substantial answer, for discussions, please use comments and please do remember to vote (after you log in)!
[скрыть предварительный просмотр]

Закладки и информация

Добавить закладку

подписаться на rss ленту новостей

Статистика

Задан: Jul 17 '13

Просмотрен: 70,454 раз

Обновлен: Apr 03 '15

Проект компании "АТС Дизайн"
Asterisk® и Digium® являются зарегистрированными торговыми марками компании Digium, Inc., США.
IP АТС Asterisk распространяется под лицензией GNU GPL.