基于星号的会议室

前言


下午好

有两件事促使我写这篇文章:很少或缺少有关Asterisk“芯片”的现代工作示例,以及专家不愿意与其他人共享这些“芯片”。 现在我是关于RU社区的。 论坛上的各种“祖父”更可能给您充斥污垢,并让您阅读十年前的书,而不是或多或少地提供有用的信息。 论坛主题本身(创建于2005-2010年)非常过时,有时在当前版本的星号中已经看到一些内容,并且需要重做一些内容才能使其正常工作。

所以在这里。
由于放弃了CUCM,取而代之的是Asterisk,管理层的任务是以最原始的形式保存用户中最受欢迎的服务,以免使人们感到沮丧。 其中之一是创建会议。 到那时,我已经对Asterisk熟悉了,但还不那么熟悉,所以花了大约一个半星期的时间来整理各种会议选项,最终决定了另一个任务。

问题是,从与类似的解决方案类似,有一篇文章提到了过时的约会,还有某种我仍然无法工作的怪物 。 我建议不要那么笨重。

纸浆


我不会描述什么是共轭,是什么负责特定配置中的什么部分,以及该选项是什么,我将仅获得此信息,并且它是最新的。 现在讨论整个决策。

目标:使会议可以在对话期间创建,然后邀请那里的更多订户。 主要问题是channelredirect函数无法正常运行。 也就是说,如果您在通话过程中从拨号方案中执行该命令,则其中一个通道将在需要时自动关闭,而第二个通道将崩溃,并将整个拨号方案爬到2行并在Dials上注册g选项是很懒的。 而且我不明白为什么在大多数手册中,每个人都试图仅通过拨号计划来解决问题,却忽略了星号与外部脚本和AMI配合使用的能力。

这样啊 星号14.4.0

2个选项的会议脚本(带注释):

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); } } 


编程大师可以通过编写糖果来修复代码,我尽力编写了代码。
接下来,我们开始直接在Asterisk本身中使用此脚本。

为了创建会议,我选择了组合* 1。 简要地说,不与主要编号相交。

将具有所需变量的脚本调用添加到features.conf

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

然后,要使其起作用,请在[globals]部分的Dialplan中创建一个变量,然后添加我们的功能

 DYNAMIC_FEATURES=conference 

要将新参与者添加到已创建的会议中,您需要在confbridge.conf中注册代码。

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

好吧,现在最好的部分是extensions.ael:

要创建会议(php脚本在此处处理两个对话通道):

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

要添加新用户(dialplan_exec地址在此处):

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

仅此而已。 拨号计划中没有成千上万的代码。 一切都很宽敞。 * 1在对话中,而您又在conf中,* 1蜂鸣和拨号,添加该人。

成长


由于用户的困惑,我开始开发此功能。

接下来的机会是从头开始创建会议(而不是从对话中),以及按会议号进入已创建的会议,而不必等待邀请呼叫

添加到拨号计划:

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

添加到脚本:

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); 


我还必须修改_ * X行。

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

现在,要进入会议或从头开始创建会议,您只需拨打* 1和一个电话,例如* 15234。

该服务的最后一个变种是所谓的“小组会议”。 这是当大老板们懒得手动添加所有人时,但是我想按一个按钮,然后一切都组装好了。 为此,我决定单独编写服务代码(* XXX),以使人们自己不会感到困惑。 对于我们的组织而言,在未来100年内不太可能需要超过1000个会议组,因此应该有足够的编号储备。 在家里,您可以添加为其他前缀,因此分配不同的编号能力。

拨号方案:

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

参与者自己的尖叫声:

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); } 


所有组均按照“组,编号,名称,描述”的结构存储在数据库中。 如果出现一个新组,则只需将其添加到数据库。

现在,例如,要召集所有董事参加会议,一般将只需要拨* 100。 通常,大老板有大电话。 因此,我们将* 100绑定到任何快速拨号键,将其签名为“ director”,并且用户不必理会键入什么内容。 我按下了按钮-我召集了会议。

现在预料到您的问题:

为什么使用脚本和ami? 因为通过拨号计划,我无法在不丢失两个频道的情况下合理地重定向两个频道。 在ami中,在重定向功能中,您可以附加一个频道+为此设置一个变量(例如,会议号,以便他也可以向其中添加一个人)。

您可能还会注意到,我将要素放在单独的service_code-ael上下文中。 当您具有多个功能部件时,这很方便。 我决定使它们通过*,因此,在任何情况下,我都只写_ *X。 和在这种情况下的地址。 也许有人会找到一个更优雅的解决方案,但几个月来我一直没有找到它。 并且此功能吸引了用户。

为什么选择ael,而不是conf? 好吧,因为它更结构化且更易于阅读。
更容易理解 一个gotoif函数值得。 我还没到lua。

为什么在大量收集示例中是通过bash而不是通过AMI来完成的? 问题在于,通过ami通过连续执行一堆原始操作,系统会等待上一个完成,以给出下一个。 如果没有人拿起电话,并且有20秒钟no_ans和这5件东西? 您可以等到晚上收集。

好吧,这可能就是全部。 我希望本文能为那些寻求快速,舒适地为用户提供服务的求职者提供帮助,而最重要的是,将来保持该系统对我自己来说很方便,可以说对将来有保留。

Source: https://habr.com/ru/post/zh-CN427117/


All Articles