Quantcast
Channel: IP АТС Asterisk
Viewing all 1052 articles
Browse latest View live

FreePBX Call Recordings + Asternic CDR Stats 1.5.1

$
0
0

FreePBX Call Recordings + Asternic CDR Stats 1.5.1

Данная модификация включает отображение записей разговоров FreePBX
в модуле Asterisk CDR StatsСкачать asternic_cdr-1.5.1.tgz исправленный Скачать asternic_cdr-1.5.1.tgz исправленный

код модификации

Замените файл:

/var/www/html/admin/modules/asternic_cdr/functions.inc.phpмодуля Asternic.

на файл именем с модифицированным кодом:

[root@localhost asternic_cdr]# ls -la | grep fu
-rw-r--r--  1 asterisk asterisk 16431 Feb 13 16:17 functions.inc.php
-rw-r--r--  1 asterisk asterisk 16163 Feb 13 16:16 functions.inc.php.bk

<?php

if(isset($_SERVER['PATH_INFO'])) {
    define("SELF",  substr($_SERVER['PHP_SELF'], 0, (strlen($_SERVER['PHP_SELF']) - @strlen($_SERVER['PATH_INFO']))));
} else {
    define("SELF",  $_SERVER['PHP_SELF']);
}

function asternic_cdr_get_config($engine) {
    // Executed on APPLY in FreePBX, we regenerate the fop2buttons if needed
    global $amp_conf, $db, $active_modules;


}

function asternic_cdr_query() {

    global $active_modules, $amp_conf, $db;

    $sql = "SELECT exten,privacy,label,`group`,email,channel,queuechannel,originatechannel,customastdb,spyoptions,external FROM fop2buttons";
    $results = $db->getAll($sql, DB_FETCHMODE_ASSOC);
    if(DB::IsError($results)) {
        die($results->getMessage());
    }
    foreach ($results as $result) {
        $fopprivacy[$result['exten']]   = $result['privacy'];
        $foplabel[$result['exten']]     = $result['label'];
        $fopgroup[$result['exten']]     = $result['group'];
        $fopemail[$result['exten']]     = $result['email'];
        $fopchannel[$result['exten']]   = $result['channel'];
        $fopqchannel[$result['exten']]  = $result['queuechannel'];
        $fopochannel[$result['exten']]  = $result['originatechannel'];
        $fopcustastdb[$result['exten']] = $result['customastdb'];
        $fopspyoption[$result['exten']] = $result['spyoptions'];
        $fopexternal[$result['exten']]  = $result['external'];
    }

}

function return_timestamp($date_string)
{
  list ($year,$month,$day,$hour,$min,$sec) = preg_split("/-|:| /",$date_string,6);
  $u_timestamp = mktime($hour,$min,$sec,$month,$day,$year);
  return $u_timestamp;
}

function swf_bar($values,$width,$height,$divid,$stack)
{
    global $config;

    if ($stack==1) {
        $chart = "images/barstack.swf";
    } else {
        $chart = "images/bar.swf";
    }
    $return = "<div id='$divid'>\n";
    $return.= "</div>\n";
    $values = html_entity_decode($values);
    $return.= "<script type='text/javascript'>\n";
    $return.='$(document).ready(function() {'."\n";

    $variables = split("&",$values);
    if(isset($config['no_animation'][''])) {
        $variables[] = "noanimate=1";
    }

    $return .= "var flashvars = {\n";
    $param = Array();
    foreach($variables as $deauna) {
        $pedazos = split("=",$deauna);
        $param[]="'$pedazos[0]': '$pedazos[1]'";
    }
    $texti = implode(",\n",$param);
    $return.=$texti;
    $return.=" };\n";

    $return.= "swfobject.embedSWF('$chart', '$divid', '$width', '$height', '9.0.0', '#336699', flashvars, {wmode:'transparent'});\n";
    $return.= "});</script>\n";
    echo $return;
}

function print_exports($header_pdf,$data_pdf,$width_pdf,$title_pdf,$cover_pdf) {
        global $lang;
        global $language;
        $head_serial = serialize($header_pdf);
        $data_serial = serialize($data_pdf);
        $width_serial = serialize($width_pdf);
        $title_serial = serialize($title_pdf);
        $cover_serial = serialize($cover_pdf);
        $head_serial = rawurlencode($head_serial);
        $data_serial = rawurlencode($data_serial);
        $width_serial = rawurlencode($width_serial);
        $title_serial = rawurlencode($title_serial);
        $cover_serial = rawurlencode($cover_serial);

        $complete_self = $_SERVER['REQUEST_URI'];
                //echo "<br/><form method=post action='modules/asternic_cdr/export.php'>\n";
        echo "<br/><form method='post' action='$complete_self'>\n";
        foreach($_REQUEST as $kkey=>$vval) {
                echo "<input type='hidden' name='$kkey' value='".$vval."' />\n";
        }
                echo "<input type='hidden' name='action' value='export' />\n";
                echo "<input type='hidden' name='head' value='".$head_serial."' />\n";
                echo "<input type='hidden' name='rawdata' value='".$data_serial."' />\n";
                echo "<input type='hidden' name='width' value='".$width_serial."' />\n";
                echo "<input type='hidden' name='title' value='".$title_serial."' />\n";
                echo "<input type='hidden' name='cover' value='".$cover_serial."' />\n";
                echo "<a href='javascript:void()' class='info'><input type=image name='pdf' src='images/asternic_pdf.gif' style='border:0;'><span>";
                echo _('Export to PDF');
                echo "</span></a>\n";
                echo "<a href='javascript:void()' class='info'><input type=image name='csv' src='images/asternic_excel.gif' style='border:0;'><span>";
                echo _('Export to CSV/Excel');
                echo "</span></a>\n";
                echo "</form>";
}

function seconds2minutes($segundos) {
    $horas    = intval($segundos / 3600);
    $minutos  = intval($segundos % 3600 ) / 60;
    $segundos = $segundos % 60;
    $ret = sprintf("%02d:%02d:%02d",$horas,$minutos,$segundos);

//    return "$minutos:$segundos";
    return $ret;
}

function remove_quotes($argument) {
    return substr($argument,1,-1);
}

function asternic_download($file) {
    include("download.php");
}

function asternic_getrecords( $MYVARS ) {
    global $active_modules, $amp_conf, $db;

    $channel = $MYVARS['channel'];
    $start   = $MYVARS['start'];
    $end     = $MYVARS['end'];
    $gtype    = $MYVARS['direction'];
    $condicionextra="";

    if($gtype=='outgoing') {
        $chanfield = "channel";
        $otherchanfield = "dstchannel";
    } else {
        $chanfield = "dstchannel";
        $otherchanfield = "channel";
    }

$query = "SELECT substring($chanfield,1,locate(\"-\",$chanfield,length($chanfield)-8)-1) AS chan1,";
//$query = "SELECT IF($chanfield like 'Local/%',CONCAT('SIP',RIGHT(substring(replace($chanfield,'-','/'),1,instr($chanfield,'@')-1),instr(reverse(substring(replace($chanfield,'-','/'),1,instr($chanfield,'@')-1)),'/'))),substring($chanfield,1,locate(\"-\",$chanfield,length($chanfield)-8)-1)) as chan1, ";
//$query.= "billsec,duration,duration-billsec as ringtime,src,";
//изменение
$query.= "billsec,duration,duration-billsec as ringtime,src,recordingfile,";
$query.="IF(dst='s',dcontext,dst) as dst,calldate,disposition,accountcode,userfield,uniqueid FROM asteriskcdrdb.cdr ";
$query.= "WHERE calldate >= '$start' AND calldate <= '$end' AND (duration-billsec) >=0 $condicionextra ";
$query.= "HAVING chan1 IN ('$channel') ORDER BY calldate";


$me=true;

$res = $db->query($query);

if(DB::IsError($res)) {
    die($res->getMessage());
}

$ftype = $_REQUEST['type'];
$fdisplay = $_REQUEST['display'];
$ftab = $gtype;

$cont=0;
while ($res->fetchInto($row, DB_FETCHMODE_ASSOC)) {

      if (!(substr($row['accountcode'],0,5)=='Local' && $dispo[$row['disposition']]=='BUSY' && $row[9]=='ResetCDR')) {
         $cont++;
         $disposition = $row['disposition'];

         if(!isset($detail[$row['chan1']])) {
             $detail[$row['chan1']]="";
         }

         $me = ! $me;
         if($me==true) {
             $odclass="class='odd'";
         } else {
             $odclass="";
         }
         $bill_print = seconds2minutes($row['billsec']);

         $detail[$row['chan1']].= "<tr $odclass>\n<td>$cont</td>\n";
         $detail[$row['chan1']].= "<td style='text-align: center;' >".$row['calldate']."</td>\n";
         $detail[$row['chan1']].= "<td>".$row['src']."</td><td>".$row['dst']."</td>\n";
         $detail[$row['chan1']].= "<td align=right>".$bill_print."</td>\n";
         $detail[$row['chan1']].="<td align=right>".$row['ringtime']." "._('secs')."</td>\n";
         $detail[$row['chan1']].= "<td style='text-align: center;'>";

         if($row['disposition']=="NO ANSWER" || $row['disposition']=="FAILED") {
            $detail[$row['chan1']].="<span style='color: red;'>";
         } elseif($row['disposition']=="BUSY") {
            $detail[$row['chan1']].="<span style='color: orange;'>";
         } else {
            $detail[$row['chan1']].="<span style='color: green;'>";
         }

          $detail[$row['chan1']].= $row['disposition'];
          $detail[$row['chan1']].= "</span></td>";
//изменение
if ($row['recordingfile']) {
            $rec_parts = explode('-',$row['recordingfile']);
            $fyear = substr($rec_parts[3],0,4);
            $fmonth = substr($rec_parts[3],4,2);
            $fday = substr($rec_parts[3],6,2);
            $monitor_base = $amp_conf['MIXMON_DIR'] ? $amp_conf['MIXMON_DIR'] : $amp_conf['ASTSPOOLDIR'] . '/monitor';
            $recordingfile = "$monitor_base/$fyear/$fmonth/$fday/" . $row['recordingfile'];
            if (!file_exists($recordingfile)) {
                $recordingfile = '';
                $detail[$row['chan1']].= "\n<td>";
            }
            else {
            $detail[$row['chan1']].= "\n<td style='text-align: center;' title=\"$row[recordingfile]\"><a href=\"".$PHP_SELF."?getRec=".base64_encode($recordingfile)."\" target=\"_blank\"><img src=\"images/asternic_playicon.png\" alt=\"Call recording\" /></a>";
            }
        } else {
            $recordingfile = '';
            $detail[$row['chan1']].= "\n<td>";
        }
          $detail[$row['chan1']].= "</td>\n";


//изменение
//          $detail[$row['chan1']].= "\n<td>";
//
//          $uni = $row['uniqueid'];
//          $uni = str_replace(".","",$uni);
//
//             if($row['userfield']<>"") {
//              $detail[$row['chan1']].="<a href=\"javascript:void(0);\" onclick='javascript:playVmail(\"".$row['userfield']."\",\"play".$uni."\");'>";
//              $detail[$row['chan1']].="<div class='playicon' title='Play' id='play".$uni."'  style='float:left;'>";
//              $detail[$row['chan1']].="<img src='images/blank.gif' alt='pixel' height='16' width='16' border='0'>";
//              $detail[$row['chan1']].="</div></a>";
//              $detail[$row['chan1']].="<a href=\"javascript:void(0); return false;\" onclick='javascript:downloadVmail(\"".$row['userfield']."\",\"play".$uni."\",\"$ftype\",\"$fdisplay\",\"$ftab\"); return false;'>";
//              $detail[$row['chan1']].="<div class='downicon' title='Download' id='dload".$uni."'  style='float:left;'>";
//              $detail[$row['chan1']].="<img src='images/blank.gif' alt='pixel' height='16' width='16' border='0'>";
//              $detail[$row['chan1']].="</div></a>";
//          } else {
//              $detail[$row['chan1']].= "&nbsp;";
//          }
//          $detail[$row['chan1']].= "</td>\n";
          $detail[$row['chan1']].= "\n</tr>\n";
      }

}

echo "<table width='99%' cellpadding=3 cellspacing=3 border=0 id='table${channel}' class='sortable'>\n";
echo "<thead><tr><td bgcolor='#ddcc00'>#</td>";
echo "<td bgcolor='#ddcc00' align='center'>"._('Date')."</td>\n";
echo "<td bgcolor='#ddcc00'>"._('From')."</td>\n";
echo "<td bgcolor='#ddcc00'>"._('To')."</td>\n";
echo "<td bgcolor='#ddcc00' align='right'>"._('Billable Time')."</td>\n";
echo "<td bgcolor='#ddcc00' align='right'>"._('Ring Time')."</td>\n";
echo "<td bgcolor='#ddcc00' align='center'>"._('Disposition')."</td>\n";
echo "<td bgcolor='#ddcc00' align='center'>"._('Listen')."</td></tr></thead>\n";
echo "<tbody>".$detail[$channel]."</tbody>\n";
echo "</table>\n";


$complete_self = $_SERVER['REQUEST_URI'];
echo "<form id='downloadform' method='get' action='$complete_self'><input type=hidden name='file' id='downloadfile' value=''><input type=hidden name='action' value='download'><input type='hidden' name='type' id='dtype' value=''><input type='hidden' id='idisplay' name='display' value=''> <input type='hidden' id='itab' name='tab' value=''></form>";

}


define('FPDF_FONTPATH',dirname(__FILE__).'/lib/font/');
include_once(dirname(__FILE__) . "/lib/fpdf.php");

class PDF extends FPDF
{

function Footer()
{
    global $lang;
    global $language;
    //Go to 1.5 cm from bottom
    $this->SetY(-15);
    //Select Arial italic 8
    $this->SetFont('Arial','I',8);
    //Print centered page number
    $this->Cell(0,10,$lang["$language"]['page'].' '.$this->PageNo(),0,0,'C');
}

function Cover($cover)
{
    $this->SetFont('Arial','',15);
    $this->MultiCell(150,9,$cover);
    $this->Ln();
}

function Header()
{
    global $title;
    //Select Arial bold 15
    $this->SetFont('Arial','B',15);
    //Move to the right
    $this->Cell(85);
    //Framed title
    $this->Cell(30,10,$title,0,0,'C');
    //Line break
    $this->Ln(10);
}

function TableHeader($header,$w)
{
    $this->SetFillColor(255,0,0);
    $this->SetTextColor(255);
    $this->SetDrawColor(128,0,0);
    $this->SetLineWidth(.3);
    $this->SetFont('','B',11);

    for($i=0;$i<count($header);$i++)
        $this->Cell($w[$i],10,$header[$i],1,0,'C',1);
    $this->Ln();
}

//Colored table
function FancyTable($header,$data,$w)
{

    $this->TableHeader($header,$w);

    //Color and font restoration
    $this->SetFillColor(224,235,255);
    $this->SetTextColor(0);
    $this->SetFont('');
    //Data
    $fill=0;
    $supercont=1;
    foreach($data as $row)
    {
        $contador=0;
        foreach($row as $valor) {
            $this->Cell($w[$contador],6,$valor,'LR',0,'C',$fill);
            $contador++;
        }
        $this->Ln();
        $fill=!$fill;
        if($supercont%40 == 0) {
            $this->Cell(array_sum($w),0,'','T');
            $this->AddPage();
            $this->TableHeader($header,$w);
            $this->SetFillColor(224,235,255);
            $this->SetTextColor(0);
            $this->SetFont('');
        }
        $supercont++;
    }
    $this->Cell(array_sum($w),0,'','T');
}
}

function asternic_export_csv($header,$data) {
    header("Content-Type: application/csv-tab-delimited-table");
    header("Content-disposition: filename=table.csv");

    $linea="";
    foreach($header as $valor) {
        $linea.="\"$valor\",";
    }
    $linea=substr($linea,0,-1);

    print $linea."\r\n";

    foreach($data as $valor) {
        $linea="";
        foreach($valor as $subvalor) {
            $linea.="\"$subvalor\",";
        }
        $linea=substr($linea,0,-1);
        print $linea."\r\n";
    }
}

function asternic_export($REQ) {

    $header = unserialize(rawurldecode($REQ['head']));
    $data   = unserialize(rawurldecode($REQ['rawdata']));
    $width  = unserialize(rawurldecode($REQ['width']));
    $title  = unserialize(rawurldecode($REQ['title']));
    $cover  = unserialize(rawurldecode($REQ['cover']));

    if(isset($_REQUEST['pdf']) || isset($REQ['pdf_x'])) {
        $pdf=new PDF();
        $pdf->SetFont('Arial','',12);
        $pdf->SetAutoPageBreak(true);
        $pdf->SetLeftMargin(1);
        $pdf->SetRightMargin(1);
        $pdf->AddPage();
        if($cover<>"") {
            $pdf->Cover($cover);
        }
        $pdf->AddPage();
        $pdf->FancyTable($header,$data,$width);
        $pdf->Output("export.pdf","D");
    } else {
        asternic_export_csv($header,$data);
    }
}

//изменение
function recordfile_uri($path) {
    $size = filesize($path);
    $name = basename($path);
    $extension = strtolower(substr(strrchr($name,"."),1));
    // This will set the Content-Type to the appropriate setting for the file
    $ctype ='';
    switch( $extension ) {
        case "WAV":
            $ctype="audio/x-wav";
            break;
        case "wav":
            $ctype="audio/x-wav";
            break;
        case "ulaw":
            $ctype="audio/basic";
            break;
        case "alaw":
            $ctype="audio/x-alaw-basic";
            break;
        case "sln":
            $ctype="audio/x-wav";
            break;
        case "gsm":
            $ctype="audio/x-gsm";
            break;
        case "g729":
            $ctype="audio/x-g729";
            break;
        default: //not downloadable
            // echo ("<b>404 File not found! foo</b>");
            // TODO: what to do if none of the above work?
        break ;
    }

  $fp=fopen($path, "rb");
  if ($size && $ctype && $fp) {
    header("Pragma: public");
    header("Expires: 0");
    header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
    header("Cache-Control: public");
    header("Content-Description: audio file");
    header("Content-Type: " . $ctype);
    header("Content-Disposition: attachment; filename=" . $name);
    header("Content-Transfer-Encoding: binary");
    header("Content-length: " . $size);
    $chunksize = 1*(1024*1024);
    while (!feof($fp)) {
        $buffer = fread($fp, $chunksize);
        echo $buffer;
        ob_flush();
        flush();
    }
    fclose($fp);
  }
}
if(isset($_GET['getRec'])){
    recordfile_uri(base64_decode($_GET['getRec']));
    die();
}

?>

Источник, с подробными разъяснениями

FreePBX


Asterisk CLI - интерфейс командной строки

$
0
0

Asterisk CLI - интерфейс командной строки

asterisk -vvvvvv

Командная строка является мощным инструментом для мониторинга и управления работой Asterisk PBX. При запуске asterisk с флагом -r или -c, появиться следующие приглашение:

# asterisk   -vvvr
*CLI> 

Введите core show helpи нажмите enter для получения полного списка команд:

Командная строка поддерживает вывод доступных команд по неполному вводу нажатием 'Tab':

Для получения дополнительной информации о конкретной команде, вы можете ввести core show help<command>. Например:

*CLI> core show help manager
                manager reload Reload manager configurations
    manager set debug [on|off] Show, enable, disable debugging of the manager code
          manager show command Show a manager interface command
         manager show commands List manager interface commands
        manager show connected List connected manager interface users
           manager show eventq List manager interface queued events
         manager show settings Show manager global settings
            manager show users List configured manager users
             manager show user Display information on a specific manager user
*CLI> 

Вот некоторые полезные команды:

Core

  • core set verbose <0-9> - порог отображаемой информации.
  • core reload - перечитать все конфиги
  • core restart gracefullyперезагрузить Asterisk по завершению всех текущих вызовов (свободные каналы закрываются)
  • core restart now Restart перезагрузить Asterisk немедленно
  • core restart when convenientперезагрузить Asterisk если нет разговоров

SIP

  • sip show peersпоказать существующие SIPекстеншены и их статус
  • sip show peer 100 отображает информацию о конкретном SIPекстеншене
  • sip show registryотображает состояние зарегистрированных транков

PJSIP

  • pjsip set logger {on|off|host} – Enable/Disable PJSIP Logger Output
  • pjsip show aors– Show PJSIP Aors

   Aor:  <Aor..............................................>  <MaxContact>
    Contact:  <Aor/ContactUri.................................>  <Status....>  <RTT(ms)..>
 =========================================================================================

      Aor:  1000                                                 1
    Contact:  1000/sip:1000@192.168.1.32:5060;transport=UDP;rin  Avail               9.645

      Aor:  1001                                                 1
  • pjsip show aor– Show PJSIP Aor

localhost*CLI> pjsip show aor 1000

      Aor:  <Aor..............................................>  <MaxContact>
    Contact:  <Aor/ContactUri.................................>  <Status....>  <RTT(ms)..>
 =========================================================================================

      Aor:  1000                                                 1
    Contact:  1000/sip:1000@192.168.1.32:5060;transport=UDP;rin  Avail              13.017


 ParameterName        : ParameterValue
 ==========================================================================================
 authenticate_qualify : false
 contact              : sip:1000@192.168.1.32:5060;transport=UDP;rinstance=56471484e9cd2c68
 default_expiration   : 3600
 mailboxes            :
 max_contacts         : 1
 maximum_expiration   : 7200
 minimum_expiration   : 60
 outbound_proxy       :
 qualify_frequency    : 60
 remove_existing      : true
 support_path         : false

DAHDI

  • dahdi show statusсостояние портов dahdi
  • dahdi show channelsпоказать существующие каналы

Кодеки

  • core show translation recalcрасчет перекодировки кодеков
Spoiler

ещё

  • module show like mysqlотобразить загруженные модули содержащие в названии mysql
  • pri set debug {on|off} span 1 Enables PRI debugging on a span
  • rtp set debug {on|off|ip} Enable/Disable RTP debugging

Простые CLI приемы

Есть несколько трюков, которые помогут вам в интерфейсе командной строки Asterisk. Очень удобно завершение неполного ввода клавишей TAB. Если вы введете начало команды и нажмите клавишу Tab, Asterisk попытается завершить имя команды, или покажет возможные команды, которые начинаются с буквы, которые Вы ввели. Например, введите 'co', а затем нажмите клавишу Tab.

 localhost*CLI> co
 confbridge  config      core
 localhost*CLI> co

Теперь наберите 'cor', и нажмите TAB снова. На этот раз Asterisk завершит слово, т.к. 'core' является единственной командой, которая начинается с 'cor'. Этот трюк также работает с под-командами. Например, наберите 'core show' и нажмите TAB. (Возможно, вам придется дважды нажать вкладку, если вы не поставили пробел после слова 'show'.) Asterisk покажет вам все под-команды.

localhost*CLI> core show [Tab]
application     applications    calls           channel         channels
channeltype     channeltypes    codec           codecs          config
file            function        functions       hanguphandlers  help
hint            hints           image           license         profile
settings        sound           sounds          switches        sysinfo
taskprocessors  threads         translation     uptime          version
warranty
localhost*CLI> core show

Повторение предыдущих команд.

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

Run Linux Shell Commands from The Asterisk CLI

Восклицательный знак перед командой позволяет предавать команды оболочке Linux.

 localhost*CLI> !whoami
 root
 localhost*CLI>

Настройка Asterisk

FreePBX

$
0
0

FreePBX

Настройка FreePBX Asterisk GUI Документация Мануал

FreePBX это полнофункциональный веб-интерфейс для конфигурации Asterisk PBX.

Если Вы знакомы с Asterisk, то знаете, настройка ATCосуществляется при помощи конфигурационных файлов. FreePBX предлагает простой, интуитивно понятный интерфейс для настройки и управления Asterisk PBX.
FreePBX также поставляется со многими дистрибьютивами:
AsteriskNOW, FreePBX Distro, Trixbox, Elastix
Документация Мануал FreePBX Asterisk Gui

Скачать FreePBX

Документация

Общее

Уязвимости

Admin modules

Документация по административным модулям FreePBX

Applications

Документация по модулям приложений FreePBX

Connectivity

Документация по модулям входящих исходящих соединений FreePBX.

  • Inbound Routes - Наведение входящих вызовов , DID.
  • Outbound Routes - Маршрутизирует исходящие вызовы по требуемым транкам.
  • Zap Channel DIDs - Назначение DIDдля конкретных ZAP каналов.
  • Trunks - Управляет ZAP (Dahdi), SIPпротокол, IAXканалами для выхода в общую телефонную сеть, или соединения АТС.

Settings Modules

Документация по модулям глобальных настроек каналов и приложений FreePBX

UCP

Примеры

Устаревшее

FreeSWITCH CDR Viewer

$
0
0

FreeSWITCH CDR Viewer

Просмотр данных CDR FreeSWITCH при помощи веб интерфейса Asterisk-CDR-Viewer

Подготовим FreeSWITCH для работы с MySQL через ODBC

Предполагается, что сервер mysql ( mariadb) установлен.

 yum install -y mysql-connector-odbc unixODBC unixODBC-devel

Проверим odbcinst.ini

# Driver from the mysql-connector-odbc package
# Setup from the unixODBC package
[MySQL]
Description     = ODBC for MySQL
Driver          = /usr/lib/libmyodbc5.so
Setup           = /usr/lib/libodbcmyS.so
Driver64        = /usr/lib64/libmyodbc5.so
Setup64         = /usr/lib64/libodbcmyS.so
FileUsage       = 1

Заполним odbc.ini

[freeswitch]
Driver=MySQL
SERVER=localhost
PORT=3306
DATABASE=freeswitchcdr
USER=DB_USER
PASSWORD=DB_PASSWORD
Проверим подключение к MySQL

Создадим БД MySQL в формате Asterisk CDR

Создайте файл, например:

 touch freeswitchcdr.sql

И скопируйте в него структуру таблицы БД:

CREATE TABLE cdr (
   calldate datetime NOT NULL default '0000-00-00 00:00:00',
   clid varchar(80) NOT NULL default '',
   src varchar(80) NOT NULL default '',
   dst varchar(80) NOT NULL default '',
   dcontext varchar(80) NOT NULL default '',
   channel varchar(80) NOT NULL default '',
   dstchannel varchar(80) NOT NULL default '',
   lastapp varchar(80) NOT NULL default '',
   lastdata varchar(80) NOT NULL default '',
   duration int(11) NOT NULL default '0',
   billsec int(11) NOT NULL default '0',
   disposition varchar(45) NOT NULL default '',
   amaflags int(11) NOT NULL default '0',
   accountcode varchar(20) NOT NULL default '',
   uniqueid varchar(32) NOT NULL default '',
   userfield varchar(255) NOT NULL default '',
   did varchar(50) NOT NULL default '',
   recordingfile varchar(255) NOT NULL default '',
   KEY `calldate` (`calldate`),
   KEY `dst` (`dst`),
   KEY `accountcode` (`accountcode`),
   KEY `uniqueid` (`uniqueid`)
);
Создаем БД:freeswitchcdr
 mysqladmin create freeswitchcdr
Создаем таблицу:cdr
 mysql asteriskcdrdb < freeswitchcdr.sql
Задаем права на БД с параметрами определенными в odbc.ini

 mysql> GRANT ALL PRIVILEGES ON freeswitchcdr.* TO DB_USER@localhost  IDENTIFIED BY 'DB_PASSWORD';
 flush privileges;
 \q

Подготовим FreeSWITCH

Расскомментируйте строку event_handlers/mod_odbc_cdrв файле исходников FS ../freeswitch/modules.conf

и выполните make && make install.

По окончании компиляции скопируйте файл odbc_cdr.conf.xml из исходников в директорию, где установлен FS.

В моем примере это /usr/local/src/freeswitchи /usr/local/freeswitchсоответственно

cp /usr/local/src/freeswitch/src/mod/event_handlers/mod_odbc_cdr/conf/autoload_configs/odbc_cdr.conf.xml /usr/local/freeswitch/conf/autoload_configs/odbc_cdr.conf.xml

И заполните файл следующим содержанием, где параметры БД (odbc-dsn), данные определенные нами в odbc.ini:

<configuration name="odbc_cdr.conf" description="ODBC CDR Configuration">
  <settings>
    <!-- <param name="odbc-dsn" value="freeswitchcdr:DB_USER:DB_PASSWORD"/> -->
        <param name="odbc-dsn" value="odbc://freeswitch"/>
        <!-- global value can be "a-leg", "b-leg", "both" (default is "both") -->
        <param name="log-leg" value="both"/>
    <!-- value can be "always", "never", "on-db-fail" -->
    <param name="write-csv" value="on-db-fail"/>
        <!-- location to store csv copy of CDR -->
    <param name="csv-path" value="/usr/local/freeswitch/log/odbc_cdr"/>
    <!-- if "csv-path-on-fail" is set, failed INSERTs will be placed here as CSV files otherwise they will be placed in "csv-path" -->
    <param name="csv-path-on-fail" value="/usr/local/freeswitch/log/odbc_cdr/failed"/>
    <!-- dump SQL statement after leg ends -->
        <param name="debug-sql" value="true"/>
  </settings>
  <tables>
        <!-- only a-legs will be inserted into this table -->
    <table name="cdr" log-leg="a-leg">
      <field name="calldate" chan-var-name="start_stamp"/>
          <field name="clid" chan-var-name="caller_id_name"/>
          <field name="src" chan-var-name="caller_id_number"/>
          <field name="dst" chan-var-name="destination_number"/>
          <field name="dcontext" chan-var-name=""/>
          <field name="channel" chan-var-name="channel_name"/>
      <field name="dstchannel" chan-var-name="bridge_channel"/>
          <field name="lastapp" chan-var-name="hangup_cause"/>
          <field name="lastdata" chan-var-name="sip_hangup_disposition"/>
          <field name="duration" chan-var-name="duration"/>
          <field name="billsec" chan-var-name="billsec"/>
      <field name="disposition" chan-var-name="hangup_cause"/>
          <field name="lastapp" chan-var-name="current_application"/>
          <field name="amaflags" chan-var-name="amaflags"/>
          <field name="uniqueid" chan-var-name="uuid"/>
          <field name="recordingfile" chan-var-name="recordingfile"/>
          <field name="userfield" chan-var-name=""/>
    </table>
  </tables>
</configuration>
Загрузим модуль mod_odbc_cdr
 fs_cli
 load mod_odbc_cdr

Если в дальнейшем вы будете вносить изменения в файл odbc_cdr.conf.xmlих можно применить командой:

 reload mod_odbc_cdr
Spoiler

Подготовим Asterisk CDR Viewer

 cd /var/www/html
 git clone https://github.com/g613/asterisk-cdr-viewer.git
 
 cd asterisk-cdr-viewer/include

Отредактируем файл config.inc.php

$db_type = 'mysql';
$db_host = 'localhost';
$db_port = '3306';
$db_user = 'DB_USER';
$db_pass = 'DB_PASSWORD';
$db_name = 'freeswitchcdrdb';
$db_table_name = 'cdr';
$db_options = array();

Если все сделано правильно в Asterisk-CDR-Viewer будут отображаться свежие данные о вызовах:

Для того, чтобы работала сортировка по статусу вызова надо отредактировать файл ../asterisk-cdr-viewer/templates/form.tpl.phpзаменив секцию:

<td nowrap=""nowrap>
<input <?php if ( isset($_REQUEST['disposition_neg'] ) && $_REQUEST['disposition_neg'] == 'true' ) { echo 'checked="checked"'; } ?> type="checkbox" name="disposition_neg" value="true" /> not
<select name="disposition" id="disposition">
<option <?php if (empty($_REQUEST['disposition']) || $_REQUEST['disposition'] == 'all') { echo 'selected="selected"'; } ?> value="all">All Dispositions</option>
<option <?php if (isset($_REQUEST['disposition']) && $_REQUEST['disposition'] == 'ANSWERED') { echo 'selected="selected"'; } ?> value="ANSWERED">Answered</option>
<option <?php if (isset($_REQUEST['disposition']) && $_REQUEST['disposition'] == 'BUSY') { echo 'selected="selected"'; } ?> value="BUSY">Busy</option>
<option <?php if (isset($_REQUEST['disposition']) && $_REQUEST['disposition'] == 'FAILED') { echo 'selected="selected"'; } ?> value="FAILED">Failed</option>
<option <?php if (isset($_REQUEST['disposition']) && $_REQUEST['disposition'] == 'NO ANSWER') { echo 'selected="selected"'; } ?> value="NO ANSWER">No Answer</option>
</select>
</td>

на следующий код:

<td nowrap=""nowrap>
<input <?php if ( isset($_REQUEST['disposition_neg'] ) && $_REQUEST['disposition_neg'] == 'true' ) { echo 'checked="checked"'; } ?> type="checkbox" name="disposition_neg" value="true" /> not
<select name="disposition" id="disposition">
<option <?php if (empty($_REQUEST['disposition']) || $_REQUEST['disposition'] == 'all') { echo 'selected="selected"'; } ?> value="all">All Dispositions</option>
<option <?php if (isset($_REQUEST['disposition']) && $_REQUEST['disposition'] == 'NORMAL_CLEARING') { echo 'selected="selected"'; } ?> value="NORMAL_CLEARING">Answer</option>
<option <?php if (isset($_REQUEST['disposition']) && $_REQUEST['disposition'] == 'USER_BUSY') { echo 'selected="selected"'; } ?> value="USER_BUSY">Busy</option>
<option <?php if (isset($_REQUEST['disposition']) && $_REQUEST['disposition'] == 'UNALLOCATED_NUMBER') { echo 'selected="selected"'; } ?> value="UNALLOCATED_NUMBER">No Number</option>
<option <?php if (isset($_REQUEST['disposition']) && $_REQUEST['disposition'] == 'NO_ROUTE_DESTINATION') { echo 'selected="selected"'; } ?> value="NO_ROUTE_DESTINATION">No Route</option>
<option <?php if (isset($_REQUEST['disposition']) && $_REQUEST['disposition'] == 'ORIGINATOR_CANCEL') { echo 'selected="selected"'; } ?> value="ORIGINATOR_CANCEL">No Answer</option>
</select>
</td>

FreeSWITCH

Asterisk Call Center Stats

$
0
0

Asterisk Call Center Stats

Статистика очередей колл центра Asterisk PBX.
Мод основанный на Asternic Call Center Stats lite.

Ключевые изменения:
Вместо парсинга текстового лога очереди /var/log/asterisk/queueu_log в MySQL
используется нативная БД,
формируемая, непосредственно, приложением app_queue - Asterisk PBX.

Отчеты в Asterisk Call Center Stats:

Сортировка

  • Выбор данных по:
    • очередям
    • агентам
    • дате

Реалтайм

  • Состояние агентов в реальном времени.
  • Информация о очереди:
    • Свободные агенты.
    • В разговоре.
    • Количество вызовов в очереди.
  • Вызовы ожидающие в очереди.

asterisk queue stats realtime

Отвеченные вызовы

  • Отвеченные вызовы по очередям и агентам.
  • Среднее время ожидания для очередей и агентов.
  • Среднее время разговора для очередей и агентов.
  • Количество отвеченных вызовов по агентам.
  • Процент отвеченных вызовов для очередей и агентов.

asterisk queue stats answered calls

asterisk queue stats answered calls

Неотвеченные вызовы

  • Количество неотвеченных вызовов по очередям.
  • Средняя позиция в очереди при выходе.
  • Причина разъединения: повесили трубку или отключены по таймауту.

asterisk queue stats unanswered calls

Распределение вызовов

  • Распределение вызовов по дате, по часам и дням недели

asterisk queue stats distribution calls

asterisk queue stats distribution calls

Установка Asterisk Call Center Stats

Установка приложения статистики очередей колл-центра Asterisk PBX.

Укажем Asterisk сохранять лог очереди в БД

Создайте таблицу в БД asterisk.

CREATE TABLE IF NOT EXISTS `queuelog` (
`time` varchar(32) DEFAULT NULL,
`callid` char(64) DEFAULT NULL,
`queuename` char(64) DEFAULT NULL,
`agent` char(64) DEFAULT NULL,
`event` char(32) DEFAULT NULL,
`data` char(64) DEFAULT NULL,
`data1` char(64) DEFAULT NULL,
`data2` char(64) DEFAULT NULL,
`data3` char(64) DEFAULT NULL,
`data4` char(64) DEFAULT NULL,
`data5` char(64) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

в файле /etc/asterisk/logger.confвыключите лог в файл:

 queue_log_to_file = no

в файле /etc/asterisk/asterisk.conf

 [options]
 queue_adaptive_realtime = yes

в файле /etc/asterisk/extconfig.conf

 queue_log => odbc,asterisk,queuelog

где asterisk ваше db конфиг, например в /etc/asterisk/res_odbc_custom.conf

[asterisk]
enabled => yes
dsn => asterisk
username => dbuser
password => dbpass
pre-connect => yes

Примените конфигурацию

 asterisk -rx 'core reload'

Установка и настройка Asterisk Call Center Stats

Скачайте приложение в директорию веб сервера (в примере /var/www/html):

 wget http://asterisk-pbx.ru/downloads/cdr/asterisk-queue-stats.tar.gz

Распакуйте:

 cd /var/www/html
 tar zxvf asterisk-queue-stats-001.tar.gz
 cd queue-stats

Отредактируйте файл config.phpв соответствии в вашими данными, где

  • $dbname - БД в которой вы создали таблицу queuelog (в примере - asterisk)
  • $dbname - Пользователь ДБ
  • $dbpass - Пароль БД (см. /etc/asterisk/res_odbc.conf или /etc/asterisk/res_odbc_custom.conf)

// Credentials for MYSQL database
$dbhost = 'localhost';
$dbname = 'asterisk';
$dbuser = 'root';
$dbpass = '';

// Credentials for AMI (for the realtime tab to work)
// See /etc/asterisk/manager.conf

$manager_host   = "127.0.0.1";
$manager_user   = "admin";
$manager_secret = "amp111";

Задайте права на директорию queue-stats:

 chown -R asterisk. /var/www/html/queue-stats
 

Откройте статистику в вашем любимом веб браузере:

http://ip.add.res.s/queue-stats
Spoiler

Настроим Asterisk, FreeSWITCH, OpenSIPs.

$
0
0

Настроим Asterisk, FreeSWITCH, OpenSIPs.

Интегратор облачных систем телефонных коммуникаций.

Реализуем сложные ТЗ.

Удаленно, в любой точке мира.

Установка IP АТС на открытом программном обеспечении включает в себя следующие этапы:

  1. Разработка технического задания с учетом требований заказчика и возможностей IP АТС.
  2. Подготовка договора на установку и настройку и, если требуется, поставку оборудования.
  3. Подготовка счета на оплату с учетом технического задания, согласование сроков и порядка оплаты.
  4. Удаленная установка IP АТС в любой точке мира.
  5. Установка IP АТС с выездом на объект (Санкт Петербург).
  6. Предварительная настройка оборудования в нашем сервисном центре.
  7. Сдача проекта. Проверка работоспособности всех компонентов и алгоритмов работы IP АТС.
  8. Обучение для дальнейшей эксплуатации IP АТС сотрудниками заказчика.
  9. Бесплатная техническая поддержка в течении месяца с момента запуска в эксплуатацию.

Мы находимся в Санкт-Петербурге, но работаем по всему миру!

Решения

VoIPАТС

  • Неограниченное количество VoIPабонентов и транков.
  • Запись разговоров и детализированный отчет о звонках.
  • Факс на e-mail.
  • Русскоязычный интерфейс.
  • CTI - Интеграция со сторонними приложениями.

Колл Центр

Дополнительно

  • Аудит и обслуживание уже установленных систем Asterisk, FreeSWITCH и др.
  • Написание кастомизированного диаплана под любые нужды.
  • Интеграция с устаревшими TDMАТС (Avaya, NEC, Nortel, Samsung, Panasonic, LG).
  • Аудит и настройки безопасности VoIPсистем.
  • Биллинг. Многопользовательские системы.
  • SIP proxy, SBC.

Напишите нам!

Свяжитесь с нами для получения подробной информации!
Офисная АТС

Only edit this fieldset if “Функционал” is set to “Офисная АТС”.

Колл Центр

Only edit this fieldset if “Функционал” is set to “Колл Центр”.

Кастомные решения

Only edit this fieldset if “Функционал” is set to “Все сложно”.

Asterisk: StopMixMonitor

$
0
0

Asterisk: StopMixMonitor

Приложение Asterisk для остановки MixMonitor.

Описание

Остановить запись разговора приложением MixMonitor() в текущем канале и освободить записываемый файл, чтобы им можно было оперировать до завершения шагов диалплана.

Синтаксис

StopMixMonitor([MixMonitorID])

Аргументы

MixMonitorID - если валидный ID задан, будет остановлена запись только для данного процесса.

См. также Asterisk: MixMonitor()

Команды диалплана Asterisk в алфавитном порядке

Asterisk: ChangeMonitor

$
0
0

Asterisk: ChangeMonitor

Приложение Asterisk: переименовать файл записи разговора приложения Monitor

Синтаксис

ChangeMonitor(filename_base)

Аргументы
  • filename_base - новое имя файлы.
См также

function 'QUEUE_EXISTS'

$
0
0

function 'QUEUE_EXISTS'

Функция Asterisk: проверяет существует ли очередь с указанным именем

Описание

Возвращает '1', если очередь существует и '0' если нет.

Синтаксис

QUEUE_EXISTS([queuename])

см. также

Asterisk: QueueLog

$
0
0

Asterisk: QueueLog

Команда диалплана Asterisk: QueueLog

Запись в файл или БД лога очереди.

Описание

Позволяет записать в лог очереди ваше собственное событие.

Пример: QueueLog(101,${UNIQUEID},${AGENT},WENTONBREAK,600)

Синтаксис

Asterisk: RemoveQueueMember

$
0
0

Asterisk: RemoveQueueMember

Приложение Asterisk: Удаление динамического агента очереди

Описание

Пытается удалить интерфейс из обслуживание очереди. Если не существует- возвращает код ошибки. Устанавливает следующие значения переменной ${RQMSTATUS}по выполнению:

  • REMOVED - интерфейс удален
  • NOTINQUEUE - не обслуживает эту очередь
  • NOSUCHQUEUE - нет очереди
  • NOTDYNAMIC - интерфейс не динамический
пример:
 RemoveQueueMember(techsupport,SIP/3000)
Синтаксис

RemoveQueueMember(queuename[,interface])

См. также

Asterisk: PauseQueueMember

$
0
0

Asterisk: PauseQueueMember

Приложение Asterisk: Поставить агента очереди на паузу (временно вывести из обслуживания очереди).

Описание

Не направлять вызовы из очереди статическому или динамическому агенту. Устанавливает паузу на указаном интерфейсе, в указанной очереди.
Если очередь не определена, устанавливает паузу для указанного интерфейса во всех очередях, которые он обслуживает.
Приложение не выполняется, если интерфейс агента не найден.
Следующие текстовын значения возвращаются в переменную ${PQMSTATUS} по выполнению:

  • PAUSED
  • NOTFOUND
пример:
 PauseQueueMember(,SIP/3000)
Синтаксис

PauseQueueMember([queuename],interface[,options[,reason]])

Аргументы
  • queuename - имя очереди
  • queuename - интерфейс агента
  • options - ?
  • reason - если назначено, дополнительная информация добавляется в лог очередии в события AMI.
См. также

Asterisk: UnpauseQueueMember

$
0
0

Asterisk: UnpauseQueueMember

Приложение Asterisk: Снять интерфейс агента очереди с паузы.

Описание

Снять с паузы, вернуть в обслуживание очереди агента. Данное приложение отменяет действие PauseQueueMember. Возвращает переменную ${UPQMSTATUS}с одним из перечисленных значений:

  • UNPAUSED
  • NOTFOUND
Пример:
 UnpauseQueueMember(,SIP/3000)
Синтаксис

UnpauseQueueMember([queuename],interface[,options[,reason]])

Аргументы
  • reason - если назначено, дополнительная информация добавляется в лог очередии в события AMI.
См. также

Настройка очереди в Asterisk - queues.conf

$
0
0

Настройка очереди в Asterisk - queues.conf

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

В Asterisk поддерживается несколько очередей вызовов. Их определения находятся в файле queues.conf, имена очередей вызовов используются в качестве аргумента команды Queue в файле конфигурации плана набора extensions.conf. Агенты, которые обрабатывают вызовы, поступающие в очередь, описываются в файле agents.conf.

Новая возможность (начиная с 31 июля, 2005 CVS HEAD) Сообщения с периодическим напоминанием вызывающему абоненту, что о нем еще не забыли, можно включить, используя новые опции: periodic-announce и periodic-announce-frequency. С их помощью, через, определенные параметром periodic-announce-frequency промежутки времени ожидания, абоненту будет проигрываться определенное голосовое сообщение, например: «Спасибо за Ваше терпение, Ваш звонок очень важен для нас….» . Например:

periodic-announce = thank-you-message
periodic-announce-frequency = 60 ; проигрывать каждые 60 секунд ожидания
Новая возможность (начиная с 06 января, 2005): Теперь для очередей можно использовать параметр 'weight' (который подразумевает приоритет вызова), для гарантии того, что вызов, ожидающий в очереди с более высоким приоритетом, будет обработан одним из первых. Будет задерживаться обработка вызовов только для менее приоритетных очередей, если участник, который обрабатывает очередь, уже занимается вызовом из более высокоприоритетной очереди.
weight =

weight = целое число
Новые возможности (начиная с 28 сентября, 2004): Полностью и правильно поддерживается, начиная с релиза v1.0 . Если у Вас возникло желание удалять все вызовы, поступившие в очередь, у которой нет участников или агентов, для ее обработки, добавьте в файл queues.conf следующую строку:
leavewhenempty = yes
; При использовании CVS-HEAD версии, используйте:
; leavewhenempty=strict
; joinempty=strict
Новая возможность: Анонс позиции в очереди Появилась в Asterisk, начиная с версии v0.7.2 (см. багрепорт #214 в Mantis bugtracker). Рассмотрим пример файла конфигурации queues.conf.sample, на предмет параметров, которые можно в нем использовать:
;
; Вызовы могут быть записаны, с использованием системы мониторинга Asterisk
; Эта возможность можно включить для команды Queue, запись начнется,
; когда вызов из очереди начнет обрабатываться оператором. Будут записаны
; только состоявшиеся вызовы, в запись не будет включен тот промежуток времени,
; пока вызывающий абонент слушает музыку в процессе ожидания, т.е. пока его
; вызов не будет обработан оператором (MOH).
; Для включения записи вызовов, просто определите параметр "monitor-format",
; иначе, эта возможность будет отключена.
;
; monitor-format = gsm|wav|wav49

; Как часто абоненту, ожидающему в очереди вызовов, сообщать его позицию и/или
; приблизительное время ожидания обработки его вызова (0=выключено)
;
;announce-frequency = 90
;
; Нужно ли нам включать в периодический анонс приблизительное время ожидания
; обработки вызова абонента?
; Возможные значения: yes, no, или once (только один раз); время ожидания будет
; сообщаться только в том случае, если абонент ожидает своей очереди более 1 минуты.
;
;announce-holdtime = yes|no|once
;
; Далее идут описания звуковых файлов, для анонса абоненту эго позиции в очереди и/или
; приблизительного времени ожидания обработки его вызова.
; Файлы, используемые по умолчанию, приведены ниже,
; Вы можете изменить их имена на другие, если Вам это реально нужно.
;
;queue-youarenext = "queue-youarenext" ; ("You are now first in line.")
;queue-thereare = "queue-thereare" ; ("There are")
;queue-callswaiting = "queue-callswaiting" ; ("calls waiting.")
;queue-holdtime = "queue-holdtime" ; ("The current est. holdtime is")
;queue-minutes = "queue-minutes" ; ("minutes.")
;queue-thankyou = "queue-thankyou" ; ("Thank you for your patience.")
;Обратите внимание: что не нужно использовать точку с запятой, описывайте файлы без этого символа, например:
;queue-thankyou=yoursoundfile
;
; Обратите внимание, что значение timeout'а, по достижении которого, происходит выход из очереди
; вызовов, можно определить в самой команде queue в файле extensions.conf:
; Queue(queuename|options|optionalurl|announceoverride|timeout)
; пример: Queue(dave|t|||45)

Wrapuptime

Этот параметр может быть использован как для агентов, так и для самой очереди вызовов. Необходимость использования этой настройки в файле queue.conf, обусловлено тем, что в этом файле для очереди могут быть описаны агенты, в качестве участников, которые обрабатывают эту очередь.

;
; Параметр wrapuptime - это значение минимального промежутка времени,
; с момента, когда работа с абонентом завершена и до того,
; как участник обработки может принять новый вызов из очереди.
; Значение в миллисекундах. (0 - задержка отсутствует)
;
;wrapuptime=15

Memberdelay

Параметр устанавливает время задержки между моментом, когда агент отвечает на вызов и соединения его с вызывающим абонентом.

;memberdelay = 5

timeoutrestartЕсли параметр «timeoutrestart» установлен в значение yes, тогда значение таймаута для агента будет сбрасываться, если от него будет получен сигнал BUSY или CONGESTION. Это бывает полезно, когда агент имеет возможность отметить вызов, отвергая его или, производя некоторые действия, которые имеют подобный эффект. (Обнаружено, что если вызов агента завершился со статусом NOANSWER (ring, no-answer), это так же заставляет вызов отправить к следующему агенту в очереди по алгоритму roundrobin). ;timeoutreset = yes

Замечания

  • Параметр penalty: Очередь вызовов могут обрабатывать люди с разными обязанностями и, следовательно, у одних это обязанность основная , а у других - второстепенная, и основную нагрузку по приему вызовов нам надо возложить на одних людей, а для подстраховки - других (к примеру, если у нас есть очередь, куда поступают вызовы от клиентов, которые хотят что-то купить, то основная обязанность ее обработки ложиться на менеджеров, следовательно, их определяем без пенальти. Еще некоторые люди могут принимать звонки, если у менеджеров полный завал, с пенальти 1, и, с пенальти 2, мы можем определить агентов совсем уж не относящихся к продажам, например, телефон в службе технической поддержки).
  • Если вы включите группу участников в определение Вашей очереди вызовов, тогда вызовы будут распределяться между агентами в группе, в заданном для нее порядке, вне зависимости от заданной стратегии. Теперь, определим каждого агента при помощи директивы member=.

member=Agent/@1 ; группа агентов
member=Agent/501 ; одиночный агент

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

Некоторые пояснения работы режимов распределения вызовов между агентами: roundrobin и rrmemory Режим roundrobin не сбивает алгоритм режима «циклического распределения входящих вызовов между агентами», Фактически, использование режима roundrobin без запоминания того, кто обработал последний вызов, приводит к тому, что вызовы циклически распределяются между агентами. Ниже приводятся пояснения по работе этих режимов от kpfleming.

При использовании режима roundrobin, запоминается последний агент, с которого начался поиск свободного участника для передачи ему поступившего вызова. Поиск агента для следующего вызова начнется со следующего агента из списка. В том случае, если у нас есть свободный агент, то для первого вызова, поиск свободного агента будет осуществляться в последовательности: 1→2→3, для второго - в последовательности: 2→3→1, для следующего: 3→2→1, и т.д.

При использовании режима rrmemory, запоминается последний агент, которого пытались вызвать (у которого звонил телефон), вне зависимости от того, с кого из них начался поиск свободного агента. Тогда, поиск свободного агента для следующего вызова начнется с агента, который по списку следующий за тем, который ответил на первый вызов. Если у нас есть свободные агенты, то поиск свободного агента для обработки первого поступившего вызова будет произведен в следующем порядке 1→2 (предположим, что агент номер 2, отвечает на него), далее, при поступлении следующего вызова, порядок поиска агента для направления ему вызова будет такой: 3→1 (предположим, что агент номер 1 отвечает на него), тогда порядок поиска для следующего вызова будет таким: 2→3→1, и т.д. Если же использовать режим roundrobin, то для первого поступившего вызова, в том случае, если агент номер 2 принимает вызов, тогда, он снова первый в списке поиска свободного агента, при поступлении следующего вызова. Если же используется режим rrmemory, тогда он будет перемещен в конец списка, при поиске свободного агента для второго вызова.

Однако, Вы можете добиться циклического распределения вызовов между агентами, используя режим roundrobin, и задав различные значения параметра penalty для каждого агента, для обеспечения порядка выбора свободного агента в том порядке, который Вам необходим. Приложение app_queue будет всегда сначала искать свободного агента у которого нет пенальти, далее среди тех, у кого значение пенальти - 1, и т.д.

queues example

[sales]
announce-frequency=45
announce-holdtime=yes
announce-position=yes
autofill=no
autopause=no
autopausebusy=no
autopausedelay=0
autopauseunavail=no
eventmemberstatus=yes
eventwhencalled=yes
joinempty=yes
leavewhenempty=no
maxlen=0
memberdelay=0
monitor-type=mixmonitor
penaltymemberslimit=0
periodic-announce-frequency=0
queue-callswaiting=queue-callswaiting
queue-thankyou=queue-thankyou
queue-thereare=queue-thereare
queue-youarenext=queue-youarenext
reportholdtime=no
retry=5
ringinuse=yes
servicelevel=60
setinterfacevar=yes
strategy=ringall
timeout=15
timeoutpriority=app
timeoutrestart=no
weight=0
wrapuptime=0
member=Local/100@from-queue/n,0,100,hint:100@ext-local
member=Local/101@from-queue/n,0
member=Local/102@from-queue/n,0
member=Local/103@from-queue/n,0
member=Local/104@from-queue/n,0
member=Local/105@from-queue/n,0

Настройка Asterisk

function 'ARRAY'

$
0
0

function 'ARRAY'

Функция Asterisk ARRAY, позволяет назначить множество переменных за раз.

Описание

Списку разделенных запятыми переменных присваиваются значения в порядке перечиления.

Пример:

 Set(ARRAY(var1,var2)=1,2) 

назначит var1 = 1 и var2 = 2

СинтаксисARRAY(var1[,var2[,…][,varN]])

См. пример в описании QUEUE_VARIABLES

Функции Asterisk


function 'QUEUE_MEMBER_COUNT'

function 'QUEUE_MEMBER_PENALTY'

Команды, функции и конфигурационные файлы Asterisk ...

$
0
0

function 'QUEUE_WAITING_COUNT'

$
0
0

function 'QUEUE_MEMBER_LIST'

$
0
0

function 'QUEUE_MEMBER_LIST'

Функция Asterisk QUEUE_MEMBER_LISTвозвращает список интерфейсов обслуживающих очередь.

Описание

Возвращает, разделенный запятой список интерфейсов очереди <queuename>.

синтаксис

QUEUE_MEMBER_LIST(queuename)

См. также
Viewing all 1052 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>