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

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

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 нельзя, но и цикл такой мне видится кривым. В первую очередь в точки зрения производительности. Как оптимально решить задачу ?

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

спросил 2013-07-17 15:51:57 +0400

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. Полезно его почитать.

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

ответил 2013-07-17 17:31:46 +0400

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

обновил 2013-07-18 00:58:08 +0400

Comments

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

godlike ( 2013-07-17 17:39:20 +0400 )редактировать

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

bb2kp ( 2013-07-17 21:44:20 +0400 )редактировать
1

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

octopas ( 2013-07-17 22:02:41 +0400 )редактировать

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

meral ( 2013-07-18 00:33:50 +0400 )редактировать

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

meral ( 2013-07-18 00:42:24 +0400 )редактировать

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

godlike ( 2013-07-18 01:22:07 +0400 )редактировать

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

meral ( 2013-07-18 10:27:41 +0400 )редактировать

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

octopas ( 2013-07-19 00:04:02 +0400 )редактировать

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

meral ( 2013-07-19 19:25:06 +0400 )редактировать
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)

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

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

ответил 2015-03-26 18:44:48 +0400

etpu Gravatar etpu
1 1

обновил 2015-03-26 18:46:35 +0400

Comments

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

zzuz ( 2015-03-26 19:40:52 +0400 )редактировать

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

meral ( 2015-03-26 21:04:34 +0400 )редактировать

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

zzuz ( 2015-03-27 01:13:30 +0400 )редактировать
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}); 
    }
ссылка удалить спам редактировать

ответил 2015-04-03 07:43:22 +0400

kolos Gravatar kolos
1 1

обновил 2015-04-03 07:43:43 +0400

Comments

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

meral ( 2015-04-03 12:57:36 +0400 )редактировать

Ваш ответ

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 ленту новостей

Статистика

Задан: 2013-07-17 15:51:57 +0400

Просмотрен: 66,875 раз

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

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