29.11.2019

AMI FREEPBX NAMI SYSLOG NODEJS

В этом проекте нам нужно сохранять различные события в очередях Астериска через nodejs библиотеку NAMI. Сложности тут на первый взгляд только одна, это создания таблиц для сохранения событий. На самом деле нет, есть еще задача сохранения неудачного запроса, есть задача выполнения асинхронного запроса, чтобы не скрипт не тормозил.

В проект включены файлы:
tables.sql – который создает базу данных asterisk_logs и несколько табличек в ней,
table-ami-events.ods – excel файл с описанием событий по столбцам.

  1. создаем БД и таблички tables.sql,
  2. устанавливаем “npm install nami mysql modern-syslog”
  3. добавляем пользователя monit в manager_custom.conf
  4. прописываем учетные данные для mysql и asterisk manager в массивы db_config и namiConfig.
  5. Запускаем скрипт nami.js и если модули nodejs установлены верно, то скрипт запустится даже если у вас нет астериска и базы данных.

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

фалы проекта можно скачать тут

29.11.2019

certbot ssl certificate for issabel manual installation

  1. install certbot (was installed by issabel)
  2. comment rewrite engine in /etc/httpd/issabel.conf
  3. add virtual host file “issabelmanual.conf” with 80 port into /etc/httpd/conf.d
<VirtualHost *:80>
 <Directory "/var/www/html">

 </Directory>
</VirtualHost>

3. restart httpd: systemctl restart httpd
4. run certbot and answer to questions
5. certbot will add new sertificate to your ssl.conf file and comment old ssl lines in this file
6. uncomment at step 2.
7. restart httpd: systemctl restart httpd.
8. add to cron renew certificate every month by command “crontab -e”
“@monthly certbot renew”

26.11.2019

mysql optimization

Задача отображать данные из таблицы которая превышает 100 млн записей. Опции которые нужно проверить. Для отображения последних данных используется скрипт:

  1. Создание индекса НЕ на всю длину,
  2. Создание индексов для двух колонок,
  3. Для уменьшения места можно использовать компрессию для таблицы, сжимает – будь здоров, но потеря в производительности.
  4. Ограничение времени для выполнения конкретного запроса через /*+ MAX_EXECUTION_TIME($TIMEOUT) */  где $TIMEOUT в микросекундах.
  5. Изменение параметров кешей и прочего значимых изменений не дали.
  6. Создание и управление вторым сервером на компьютере для проведения тестирования при помощи mysqld_multi.
  7. create table new like current > rename current to old_tmp, new to current > select into tmp.csv where time > (2 days) > load data from tmp.csv into current > rm csv.

21.11.2019

Freepbx using any CAllerID display name as callerID(num) when making external calls

В рамках freepbx вы не можете установить callerid name (display) как вы хотите, вы всегда будете видеть тот display name который установили при создании Extension.

Чтобы исправить эту несправедливость, добавляем в extension_custom.conf

[macro-dialout-trunk-predial-hook]
exten => s,1,Noop(Number translation)
exten => s,n,Set(MYFROM=${PJSIP_HEADER(read,From)})
exten => s,n,set(MYFROM=${CUT(MYFROM, ,1)})
exten => s,n,set(MYFROM=${REPLACE(MYFROM,\")})
exten => s,n,Noop(HEADER - ${MYFROM})
exten => s,n,Set(CALLERID(number)=${MYFROM})

после этого при исходящих звонках через транки, вы будете видеть тот АОН который вы выставить в CAller ID name в своем софтфоне.

19.11.2019

Asterisk Click2Call API

  1. Готовый скрипт для вызовов между extension и внешним номером, а также для запуска любого диалплана и передачи ему параметров. Использовалась библиотека https://github.com/chan-sccp/PAMI это форк самой популярной библиотеки от marcelog/PAMI. Используется потому, что в ней исправлена ошибка при использовании CommandAction. в оригинальной библиотеке она будет выдавать read timeout. Скрипт выдает статус оригинации в json формате и unqueid. техническое задание в конце кода.
ini_set('display_errors', 0);
require __DIR__ . '/vendor/autoload.php';

use PAMI\Client\Impl\ClientImpl;
use PAMI\Listener\IEventListener;
use PAMI\Message\Event\EventMessage;
use PAMI\Message\Action\OriginateAction;
use \PAMI\Message\Event\NewchannelEvent;

class A implements IEventListener
{
    public $result;

    public function handle(EventMessage $event)
    {

        if ($event instanceof \PAMI\Message\Event\NewchannelEvent) {

            $this->result = $event->getUniqueID();
            return $this->result;
        }


    }
}

$agent          = $_GET['agent'];
$extension      = $_GET['extension'];
$destination    = $_GET['destination'];

while ($agent && $extension) {
    echo "No agent and extension possible!";
    exit;
}

include "config.php";

        $a = new ClientImpl($options);
        $a->open();
        $ClassA = new A();
        $a->registerEventListener($ClassA);

        while ($agent && $destination) {

            echo "Agent && Destination";
            $result = makecallagent($a,$agent,$destination);
            $arr = array('success' => false, 'errormsg' => $result);

            if ($result === true)
                $arr = array('success' => $result,'errormsg' => NULL, 'uniqueid' =>  $ClassA->result);


            echo json_encode($arr);

            $a->close();
            exit;
        }

        while ($extension && $destination) {

            $result = makecall($a,$extension,$destination);

            $arr = array('success' => false, 'errormsg' => $result);

            if ($result === true)
                $arr = array('success' => $result,'errormsg' => NULL, 'uniqueid' =>  $ClassA->result);


            echo json_encode($arr);

            $a->close();
            exit;
        }

        echo "No extension\agent and destination correctly passed";
        exit;


function makecall($a,$source,$number) {

        $originateMsg = new OriginateAction("PJSIP/$source");
        $originateMsg->setContext('from-internal');
        $originateMsg->setPriority('1');
        $originateMsg->setExtension("$number");
        $res = $a->send($originateMsg);

        if ($res->isSuccess()) return true;   //return tru if originating success
        return $res->getKeys()['message'];    //otherwise return error message

}

function makecallagent($a,$source,$number) {

        $originateMsg = new OriginateAction("Local/28@queuemetrics");
        $originateMsg->setContext('queuemetrics');
        $originateMsg->setPriority('1');
        $originateMsg->setVariable('AGENTCODE',$source);
        $originateMsg->setVariable('QDIALER_QUEUE','outqueue');
        $originateMsg->setVariable('EXTTODIAL',$number);

        $originateMsg->setExtension("28");
        $res = $a->send($originateMsg);

        if ($res->isSuccess()) return true;   //return tru if originating success
        return $res->getKeys()['message'];    //otherwise return error message
}

15.11.2019

Removing plus symbol from CLI (Asterisk)

If CLI coming with +, then remove it, otherwise do nothing.

same = n,Set(CALLERID(num)=${IF($["${CALLERID(num):0:1}"="+"]?${CALLERID(num):1}:${CALLERID(num)})})

11.11.2019

Add simple Ring group (freepbx)

After that go to “inbound route” and change\add destination to created group

11.11.2019

Add queue for few Extensions to make ring them all (freepbx)

then go to “inbound routes”

Choose destination Queue created before

11.11.2019

Add carrier trunk for recieve DID number (Freepbx)

  1. Adding inbound trunk: There are many ways to add carrier , carriers may use IP-IP direct link or carrier may ask you to register on registrar server.

Adding IP-IP trunk:

Adding route to deliver call from DID to Extension:

That’s all for receiving call on stand alone extension

11.11.2019

Freepbx add simple extension