📜 ⬆️ ⬇️

Asterisk conference rooms

Foreword


Good day.

I was inspired by two things to write this article: a small number or the lack of modern working examples on Asterisk "chips", as well as the reluctance of experts to share these same "chips" with the rest. This is me now about the RU-community. Any "grandfathers" on the forums would rather shower you with mud and send you to read books a decade ago, than give you a little bit of useful information. The themes of the forums created in 2005-2010 are very outdated and sometimes something has already been cut out of the current version of the asterisk, and something needs to be redone very much to make it work.

So here.
As a result of the refusal of CUCM in favor of Asterisk, the management was tasked with keeping the most popular services among users in the most original state in order not to disturb people. One of these was the creation of conferences. By that time, I was already familiar with Asterisk, but not so deeply, so it took me about a week and a half to sort through all sorts of conference options, and another task pushed me to the final decision.

The problem is that, from a solution that is similar to a solution, there is an article with an outdated meetme, as well as some kind of monster , which I never managed to get to work with. I suggest something not so cumbersome.

Pulp


Describe what confbridge is, what sections in a particular config are responsible for, and what kind of option it is, I will not, this information is available and relevant. Now about the decision as a whole.
')
Task: to make it so that a conference can be created during a conversation, and then invite more subscribers there. The main problem is that the channelredirect function does not work as I would like. That is, if you execute it from the dialplan during a call, then one of the channels will fly away to the right place, and the second one will collapse, and climbing around the entire dialplan for 2k lines and setting the g option on the Dials was lazy. And I don’t understand at all why in most manuals everyone is trying to solve the task only through dialplan, ignoring the possibility of the asterisk to work with external scripts and ami.

So. Asterisk 14.4.0

Conference script for 2 options (with comments):

conference.php
<?php //    $host = "192.168.1.1"; $port = "5038"; $timeout = "10"; $user = "conference"; $pass = "1111"; // ,    1   2  $kusok = $argv[1]; //       if ($kusok == 1){ //  $channel = $argv[2]; $bridgepeer = $argv[3]; $confnum = $argv[4]; print_r($bridgepeer); print_r($confnum); // $sconn = fsockopen ($host, $port, $timeout) or die ("Connection to $host:$port failed!"); fputs ($sconn, "Action: Login\r\n"); fputs ($sconn, "Username: $user\r\n"); fputs ($sconn, "Secret: $pass\r\n\r\n"); //   fputs ($sconn, "Action: Setvar\r\n"); fputs ($sconn, "Channel: $channel\r\n"); fputs ($sconn, "Variable: CONFNUM\r\n"); fputs ($sconn, "Value: $confnum\r\n\r\n"); fputs ($sconn, "Action: Setvar\r\n"); fputs ($sconn, "Channel: $bridgepeer\r\n"); fputs ($sconn, "Variable: CONFNUM\r\n"); fputs ($sconn, "Value: $confnum\r\n\r\n"); // fputs ($sconn, "Action: Redirect\r\n"); fputs ($sconn, "Channel: $bridgepeer\r\n"); fputs ($sconn, "ExtraChannel: $channel\r\n"); fputs ($sconn, "Context: service_code-ael\r\n"); fputs ($sconn, "Exten: conference\r\n"); fputs ($sconn, "Priority: 1\r\n\r\n"); fputs($sconn, "Action: Logoff\r\n\r\n"); sleep(2); fclose ($sconn); } //     if ($kusok == 2) { //  $confnum = $argv[2]; $inviten = $argv[3]; $sconn = fsockopen ($host, $port, $errno, $errstr, $timeout) or die ("Connection to $host:$port failed!"); // fputs ($sconn, "Action: Login\r\n"); fputs ($sconn, "Username: $user\r\n"); fputs ($sconn, "Secret: $pass\r\n\r\n"); //     fputs ($sconn, "Action: Originate\r\n"); fputs ($sconn, "Channel: Local/".$inviten."@out-ael\r\n"); fputs ($sconn, "Context: service_code-ael\r\n"); fputs ($sconn, "Exten: conference\r\n"); fputs ($sconn, "Priority: 1\r\n"); fputs ($sconn, "Variable: CONFNUM=".$confnum."\r\n\r\n"); fputs($sconn, "Action: Logoff\r\n\r\n"); sleep(2); fclose ($sconn); } } 


Programming gurus can fix the code by making candy out of it, I wrote as best I could.
Next, we start using this script directly in Asterisk itself.

In order to create a conference, I chose the combination * 1. Briefly and does not intersect with the main numbering.

Add a script call to features.conf with passing the required variables to it

 [applicationmap] conference => *1,self,System(/usr/bin/php /home/script/conference.php 1 ${CHANNEL} ${BRIDGEPEER} ${CALLERID(num)}) 

Then, to make it work, we create a variable in the [globals] section of the dialplan and add our feature

 DYNAMIC_FEATURES=conference 

To add new participants to the already created conference, you will need to register the code in confbridge.conf

 [default_menu] type = menu *1=dialplan_exec(service_code-ael,conference_add,1) 

And now the most delicious, extensions.ael:

To create a conference (here the php script addresses both conversational channels):

  conference => { ConfBridge(${CONFNUM},,,default_menu); } 

To add a new user (here addresses dialplan_exec):

 conference_add => { Read(INVITEN,dial,11,i); System(/usr/bin/php /home/script/conference.php 2 ${CALLERID(num)} ${INVITEN}); } 

Everything. No kilotons of code in the dialplan. Everything is capacious. * 1 in the conversation and you're in the box, once again * 1 beep and dialing someone to add.

Galls


Driven by the wishes of users, I began to develop this feature.

The next was the ability to create conferences from scratch (not from a conversation), as well as to enter already created conferences by their number, and not wait for an inviting call.

Add to dialplan:

 _*1XXXX => { NoOp(${CONFCHAN}); Set(__CONFNUM=${EXTEN:2}); System(/usr/bin/php /home/script/conference.php 3 ${CONFCHAN} ${CONFNUM} ); } 

Add to script:

conference.php
 //     if ($kusok == 3){ //  $channel = $argv[2]; $confnum = $argv[3]; // $sconn = fsockopen ($host, $port, $timeout) or die ("Connection to $host:$port failed!"); fputs ($sconn, "Action: Login\r\n"); fputs ($sconn, "Username: $user\r\n"); fputs ($sconn, "Secret: $pass\r\n\r\n"); //   fputs ($sconn, "Action: Setvar\r\n"); fputs ($sconn, "Channel: $channel\r\n"); fputs ($sconn, "Variable: CONFNUM\r\n"); fputs ($sconn, "Value: $confnum\r\n\r\n"); // fputs ($sconn, "Action: Redirect\r\n"); fputs ($sconn, "Channel: $channel\r\n"); fputs ($sconn, "Context: service_code-ael\r\n"); fputs ($sconn, "Exten: conference\r\n"); fputs ($sconn, "Priority: 1\r\n\r\n"); fputs($sconn, "Action: Logoff\r\n\r\n"); sleep(2); fclose ($sconn); 


I also had to modify the _ * X line.

  _*X. => { set(__CONFCHAN=${CHANNEL}); Dial(Local/${EXTEN}@service_code-ael); 

Now to enter the conference or create it from scratch, simply make a call to * 1 and a number, for example * 15234.

The final mutation of this service is the so-called “group conference”. This is when big bosses are too lazy to add everything manually, but I want to press one button and everything in the collection. For this, I decided to make separate service codes (* XXX) in order for people not to be confused too. For our organization, it is unlikely that over1000 conference groups will be required in the next 100 years, so the numbering reserve should be enough. At home, you can add another prefix as well as allocate another numbering capacity.

Dialplan:

  _*XXX=> { Set(CONFNUM=${CALLERID(num)}); System(/usr/bin/php /home/script/groups.php ${EXTEN:1} ${CONFNUM}); ConfBridge(${CONFNUM},,,default_menu); } 

The squeak of the collection of participants

groups.php
 //  function call ($group, $confnum) { $many = count($group); //       for ($i=0; $many>$i; $i++) { //    $num = trim(array_shift($group[$i])); // system("asterisk -rx \"channel originate Local/$num@out-ael application ConfBridge $confnum\""); } } //    function conf_group ($groupid) { //   $opt = array( PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC ); $pdo = new PDO("odbc:mssql_asterisk, "asterisk, "121212", $opt); //   $sql = "SELECT extension FROM [asterisk].[dbo].[conf_groups] where groupid = $groupid"; $select = $pdo->query($sql); $result = $select->fetchAll(); // $pdo = NULL; return $result; } //  ,    $groupid = $argv[1]; //   $confnum = $argv[2]; //   $group=conf_group($groupid); // call($group, $confnum); } 


All groups are stored in a database according to the structure “Groups, Number, Name, Description”. If a new group appears, then simply add it to the database.

Now, to collect, for example, all the directors for a meeting, the general just needs to dial * 100. And as a rule, big bosses have big phones. Therefore, the bindim * 100 on any speeddial key, we sign as a “director” and the user does not bother at all what to type. Button pressed - the meeting gathered.

Now anticipating your questions:

Why scripts and ami? Because I didn’t manage to make a sane redirect of both channels using the dialplan tools without losing them on the way. In ami, in the redirect function, you can attach an additional channel + set a variable to it (for example, a conference number, so that it can also add someone to it).

Also, you may have noticed that I rendered features in a separate context service_code-ael. This is convenient when all sorts of features you have more than a couple of pieces. I decided to do them through *, therefore in any context I just write _ * X. and address in this context. Perhaps someone will find a more elegant solution, but I haven’t found it in a few months. And this functionality came to users like.

Why ael, but not conf? Well, because it is more structured and easier to read.
and clearer. One gotoif function is worth something. To lua, I have not yet matured.

Why in the example of a massive collection originate made through bash, and not through AMI? The problem is that performing a bunch of originate in a row through ami, the system waits until the previous one is completed to give the next one. And if no one picks up the phone, and there 20 seconds no_ans and such 5 pieces? It will be possible to wait until the evening of the gathering.

Well, perhaps that's all. I hope this article will help the same seekers as I was when it all needed to be done quickly, comfortably for users, and most importantly, in the future it was convenient to maintain this system myself, so to speak, with the future.

Source: https://habr.com/ru/post/427117/


All Articles