Pull to refresh

Comments 50

Всякие «Деды» на форумах скорее обольют тебя помоями и отправят читать книжки десятилетней давности


Кажется, я знаю, про кого идет речь :-D
Кажется, я знаю, про кого идет речь :-D


Это который оверквоттинг не любит?
О да, это известная в узких кругах личность ;)
Да. Дед иногда пишет, когда лучше промолчать. Кстати, рекомендую #asterisk там вполне вменяемо отвечают, и зачастую, если кто-то сталкивался с проблемой ответят.
Проблема в том, что выполняя кучу originate подряд через ami, система ждет, пока завершится предыдущий, чтобы дать следующий. А если никто не берет трубку, а там 20 секунд no_ans и таких 5 штук? Можно будет до вечера ждать сбора.

Так ведь async есть.
Async — Set to true for fast origination.

А так все как вроде красиво. У меня управление сделано через веб интерфейс, всякие drag'n'drop, dropdown… Так что функций слегка больше.
Небольшое дополнение. Не сочтите за критику.
1. Вместо Action SetVar на канале, делайте Rdirect и Originate на Exten: CONFNUM.
2. В конференцию напрямую можно дозвонится и так. Скрипты и AMI излишние.
3. Чтобы одной кнопкой просто позвонить всем можно использовать Page, он правда закроет все каналы если инициатор выйдет.
4. Проверьте открытые соединения AMI. Вызов скрипта у вас прерывается, когда вы отрываете канал редиректом, это может работать, а может и нет, но скорее всего у вам часть соединений будет болтатся открытыми. Правильно бы было вызов скрипта оторвать от треда астериска, каким-нибудь daemonize.

1. Я подумал, что раз уже залез в AMI, то почему бы и не сделать там SetVar.
2. Можно, но почему то тогда по *1 срабатывает не dialplan_exec, а DYNAMIC_FEATURES.
3. Этого хотелось избежать, так как инициатор может по каким то причинам выйти из конфы, например чтобы пригласить в кого то, сидящего за IVR.
4. Вроде не болтается, но спасибо.
2. Можно, но почему то тогда по *1 срабатывает не dialplan_exec, а DYNAMIC_FEATURES.

В смысле? Вам же тупо нужно дозвониться в ConfBridge. Это чистый dialplan.
А если этот дозвонившийся захочет добавить в конференцию своего друга?
У меня почему то, в таком случае, отрабатывает *1 именно из DYNAMIC_FEATURES, хотя по логике должно из dialplan_exec, так как он уже сидит в конфе. Может баг, может фича. Когда делал не было времени выяснять, надеюсь, что выясню в будущем
Мужик, немедленный плюс тебе в карму. Возможно я ниосилятор но кто бы знал сколько боли мне в свое время принесла именно настройка конференции в астериске, а про пхп я даже не подумал, хотя неплохо его знаю. В следующий раз буду копать в эту сторону.
Спасибо как минимум за идеи, но от скриптования дальше диалпланов я бы отказался… Как-то это… Костыльно… Для себя это в некоторой мере может быть и удобно, а вот для последователей может оказаться не совсем очевидно.
Ну на самом деле не все вещи можно сделать в диалплане. И если у вас много динамических параметров, то план набора становится очень большой и не менее костыльный и уж точно не очевидней.
Простите, а можно доказать утверждение «не все вещи можно сделать в диалплане»?
Фигня то в том, что диалплан явлется полной граматикой, а если вы училися в любом из отечественных университетов, у вас была хоть гдето теорема о том, что любую задачку грамматикой можно решить, ну из тех, которые вы вообще решить можете используя любой язык программированния.
Громоздкий и костыльный диаплан становится у тех, кто не умеет пользоваться преимуществами граматик. Учитывая наличия функций работы со строчками, мат функций и regexp — диалплан обычно можно написать примерно в то же количество строк, что и программу на любом ЯП. Ну c точностью до o(1).
Насколько я знаю, данная задача в диалплане не разрешима, если только вы agi не считаете таковым. Плюс. есть всякие приложения, которые требуют отложенного выполнения, и вы их будете делать петлей через внешнее приложение.
Я не писал, что дилплан прям убог. Или, как Мэт Джоржан — пишите все в ARI. Но задачи, которые неразрешимы только его средствами присутствуют.
Какая задача неразрешима в диалплане, уточните. Ато вы както начинаете спорить с доказаными теоремами.
Возможно да, возможно нет. Но их точно можно сделать петлей через Originate и Wait.
Я не спорю не с чем.
Я имел ввиду закинуть оба плеча звонка в конференцию с помощью кастом приложения.
Закинуть оба плеча с помощью диалплана можно. Надо сделать detach и подождать 0.1 секунды перед забросом. Нет проблемы.
detach где?
Я что-то не помню не в приложениях не в их опциях.
detach/fork — это стандартный примитив програмирования. В диалпане используется Orginate.
После Orginate у вас получается новый thread(call) и он не зависит от главного. Чем не detach?
Как сделать несколько Originate из диалплана — я уже написал ниже же.
Я знаю, что это означает.
Суть в том, как вы это в application map впишите, и как избежать того, что бридж развалится как только вы оторвете одно из плеч.
если вы про application/features — оно должно просто форкнуть звонок и закрыться. После чего форкнутый звонок становится управляющим, звонит на оригинатор с использованием auto-answer и на все остальные телефоны по необходимости(но надо подождать, пока hangup отработает).

С бридажами там не очевидно. Там не все разваливатся, надо смотреть. Там надо Transfer с двумя аргументами использовать.

Могу только сказать, что я делал 3-way call на чистом диалпане и оно работало. А не, у меня там был один внешний скрипт, он AMI Transfer выполнял( не использую System для таких вещей).
Могу только сказать, что я делал 3-way call на чистом диалпане и оно работало.
Блин, вот в этом подвох.
Там нужно быть уверенным, что у тебя за предыдущей командой hangup не отработает быстрее чем ты схватишь этот канал. Ну и как бы из диалплана не особо вариантов управления другими каналами.
В моем случае, я бы все сделал через вэб-хук и AMI. Тем более что у меня уже есть функция кидающая оба звонка в конференцию.
wait(0.2) поставьте после dial. делов то.
Проблемы, конечно, бывают. Но решаемые.

Зачем вам web сервер держать, если есть fastagi? Который еще и переменные сразу передаст и проще на порядок. Можно через xinetd запускать по мере необходимости.

Потому-что у меня полноценный веб интерфейс на сервер. Со всякими свистоперделками, одна и который это drag'n'drop звонка в конференцию. Но в любом случае, я пока вижу выход только через скрипт, как он будет запущен, будь-то через AGI или через веб-хук, разницы нет. Хотя для интереса нужно будет как-то попробовать.
Отрыв плеча не опасен сам по себе. После отрыва termination плеча origination плечо уходит дальше по диаплану(параметр g команды Dial).
Но вы ведь не знаете, где этот звонок. То есть, у вас должны везде одинаково отрабатываться завершение. И еще нужно какую-то переменную закинуть на этот канал, а фича у нас отрабатывала на другом.
О, вы начали понимать, что PBX должна проектироваться, а не писаться по кусочкам.
Да, у вас должен быть стандартный диалплан завершения звонка и стандартная команда собственно звонка.
Ну хватит, пожалуйста.
У меня все стандартное по максимуму, но в новой системе, я немного отошел и сейчас сделал несколько типов Dial'a в зависимости от вызывающего приложения.
Ну и asterisk, пока еще пишется людьми и распространяется свободно.
У меня ~120 серверов с системой. На одном из них на прошлой неделе вылез баг с LOCAL переменной. Я в ней храню счетчики попыток для IVR. На всех серверах этот контекст отрабатывается нормально, на этом — нет. Переменная затирается при переходе на t или i. Пришлось отказаться от использования локальной переменной.
Ну на самом деле еще спорно, что будет для последователей сложнее, вникать в навороченный диалплан или все же в отдельные скриптики по одному на каждую задачу.
Просто скриптики имеют такое противное свойство теряться при бекапах и восстановлениях системы.
А еще даже на перле скриптики перестают работать через 10 лет(сталкивался).
На самом деле самый правильный вариант — диалплан + один fastagi сервер в стандартном месте. Внутри которого разложены по функциям ваши «скриптики».
ОЧЕНЬ не советую вообще использовать команду System внутри диалпланов астериска.
ОСОБЕННО не советую это делать тем, кто не понимает причин необходимости экранированния переменных.

Я, вобщемто, догадываюсь, почему топик стартеру не нравится ded. Тут вон даже не использованы стандартные php-agi библиотеки, вместо них лютый велосипедизм.

Давайте рассмотрим вот этот фрагментик.
System(/usr/bin/php /home/script/conference.php 2 ${CALLERID(num)} ${INVITEN})

А теперь внимательно подумаем. А есть ли хоть что-то, что запрещает в современном астериске вписать сюда… да что угодно, включая спецсиволы баша.
А ведь вообще ничего. Чтоб убедится, делаем вот такой простой диалплан
exten => 1111,1,Answer
same => n,Playback(beep)
same => n,Set(CALLERID(num)=ops)
same => n,NOOP(CALLERID NUM = ${CALLERID(num)})
same => n,Hangup


смотрим
pro-sip*CLI> core set verbose 3
— Executing [1111@test:1] Answer(«IAX2/iaxtest-7530», "") in new stack
— Executing [1111@test:2] Playback(«IAX2/iaxtest-7530», «beep») in new stack
— <IAX2/iaxtest-7530> Playing 'beep.gsm' (language 'en')
— Executing [1111@test:3] Set(«IAX2/iaxtest-7530», «CALLERID(num)=ops») in new stack
— Executing [1111@test:4] NoOp(«IAX2/iaxtest-7530», «CALLERID NUM = ops») in new stack
— Executing [1111@test:5] Hangup(«IAX2/iaxtest-7530», "") in new stack

Остальное даже анализировать както не хочется. Не делайте так, как написано. Используйте библиотеки и fastagi/ami
Я так понимаю, у них in-house решение. И учитывая, что этот вопрос ТС решался таким путем, я думаю, что у простых смертных там не особо есть возможности что-либо менять.
А так-то да, agi тут как нельзя кстати.
Ну так прийдет им callerid(num)=`rm /etc/asterisk/ -f` от партнера, и удачи, че.
Инхауз.
Не надо тут AGI. Щас допишу решение одной из «проблем». Тут все диапланом делается.
От оператора связи такой ерунды не придет, а вся внутренняя кухня только в моих руках.
Ну и я не утверждаю, что это идеальный вариант. Каждый переделает так, как считает нужным и под свою задачу. Это, скорее, мысли на бумаге.
Ага, ага. Пишите дальше. И екстеншены вам не взломают, и оператора не взломают. И у оператора все ок будет(мало кто из операторов вообще говоря фильтрует это поле).
Хах… А вы давно работаете с VoIP и связью вообще?
Ну вообще почти 4 года в федеральном операторе связи. И я не разу не видел, чтобы что то подобное было в части номера. Не знаю, что там у мелких виртуальных voip операторов, у которых ни лицензии, ни своих номеров, но у нас все поля, относящиеся к src и dst жестко контролировались на каждом узле.
А я 20 лет. И я такое ВИДЕЛ.
У вас может и контролируются, но вы же это выложили в сеть и оно 100% будет использовано на узлах, где не контролируется. Да хоть пользователь в софтфоне может написать.
4 года это джун вообще говоря.
Я не думаю, что операторы будут использовать это на своих узлах. Это решение не операторского уровня, а для себя.
пользователь в софтфоне может написать

Не может, callerid прописывает сам астериск абоненту при каждом звонке.
Может, вам два человека уже сказало, что так бывает.
Просто экранируйте переменные, ОСОБЕННО переменную callerid.
Я использую отдельные переменные на пирах для хранения номеров.
А я сейчас с американцами работаю. И у меня отлично прилетают спутанные CLID и CNAM.
Ну давайте решим одну случайно взятую проблему, изза которой понадобился баш через диалпан.

Итак, проблема
Проблема в том, что выполняя кучу originate подряд через ami, система ждет, пока завершится предыдущий, чтобы дать следующий


Что, говорите не решается?
А как вы это в баше делаете? Ну как как… паралельно запускаете. В чем проблема проделать это в диалплане? Нет проблемы… Просто надо думать диалпланом. Смотрим

;func_odbc.conf
; тут можно было получить всю строчку целиком за счет sql, но мы же повторяем логику в php скрипте, потому просто получаем список куда звонить
[GET_GROUPS]
dsn=asterisk
SELECT group_concat(extension) FROM asteriskconf_groups where groupid = '${SQL_ESC(${ARG1})}'
; group_concat возвращает одно значение состоящее из екстеншенов через запятую, принадлежит стандарту slq92 или гдето там.

;extensions.conf
[call_all_group]
exten => _X.,1,Set(list=${ODBC_GET_GROUPS(${EXTEN})}); берем список, ид=текущий екстеншен.
same => n,Execif($[ "${list}" == "" ]?Hangup); ничего нет.
same => n,Set(res=)
same => n,Set(i=1); ставим счетчик в 0. Стандартный for цикл в испольнении астериска.
same => n(loop),GotoIF($[ "${CUT(list,\,,${i}}" == "" ]?endfor); если нет больше ничего, выходим
same => n,Set(res=${res}Local/${CUT(list,\,,${i}}@originate_conf/n&); добавляем строчку звонка. Тут немного магии, да.
smae => n,Set(i=$[ ${i} + 1 ]); увеличение параметра цикла. стандартно.
same => n,Goto(loop)
same => n(endloop),Dial(${res}); запускаем цикл из N дозвонов, параллельно.

[originate_conf]
exten => _X.,1,Originate(SIP/${EXTEN},app,Confbridge,1000); звоним каждому, посылаем в конференцию.


И что, говорите, длиннее получилося?
ps написано только что, без заготовок, время написания 20 минут(смотрите время коментов), не проверялося, если случайно работает считать невозможным чудом. Все совпадения случайны и так далее.
Что-то я немного запутался.
Инициирующий канал куда делся?
После первого ответа Dial не сбросит остальные каналы?
ну просто у вас малый скил параллельного программирования.
первый диал выполняет стандартную группу RINGALL. Например вот так при двух экстеншенах.
Dial(Local/1000@originate_conf/n&Local/1001@originate_conf)

Дальше все.
Каждый звонок в контекст originate_conf будет неотвечен, но создаст еще один канал, который собственно и звонит.
будут выполнены ОБА звонка одновременно. Соответсвенно оба одновременных originate.
Что случится с начальным каналом — неважно. можете там hangup дописать.
Только что курил, понял, там все каналы по сбросу закончатся.
А инициатора забросить в ту же конференцию.
Это ж написано на коленке и не тестилося. Дальше делайте чего хотите.

Я просто написал типичное решение «нерешаемой» проблемы в диаплане.

Тут просто две стандартный структуры. for-loop (в первом контексте) и fork(во втором).
А, еще третья — доступ к БД, но это совсем просто.
Я выше уточнил проблему, которую я имел ввиду.
Ну и, пожалуйста, можете слегка спуститься? Я не из Непала… И хоть работал с ним меньше вашего, но тоже немало.
Поделитесь пожалуйста причиной отказа от CUCM в пользу Asterisk? У вас уже был внедрённый CUCM и вы с него переезжаете?
Решение отказаться было принято до моего прихода в компанию.
Я так понимаю, что отделам было важно собирать ту или иную статистику по звонкам + записи разговоров, что CUCM с его не самыми удобными CDR дать не мог. + он был на площадке оператора и наши возможности на нем были ограничены.
Ну и главное, что астериск бесплатен, а за CUCM надо платить оператору его предоставляющему
Sign up to leave a comment.

Articles