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

30.10.2019

полезные команды для мониторинга нагрузки

Кол-во открытых udp портов
ss -ua | grep -c ”

Скорость входящих+исходящих invite в секунду
tcpdump -n port 5060 | grep ‘SIP: INVITE sip:’ | pv -lar > /dev/null


Tags: ,
| Posted in Asterisk | No Comments »
30.10.2019

Too many open files

лично я натолкнулся на эту проблему, когда у меня не было много вызовов, но команда ” ss -ua | grep -c ” выдавала значение около 1000 и астериск ругался TMOF сообщениями. Как оказалось кол-во открытых портов ограничивалось 1024 и это было связано с параметрами процесса.

По умолчанию unix ограничивает для пользователя кол-во открытых файлов до 1024.
При появлении данного сообщения обычно мы так:

а) проверяем ulimit -a лимиты, и можем задать soft лимит на файлы: ulimit -n 4096 к примеру.
б) добавляем в /etc/security/limits.conf строчки
* hard nofile 65536
* soft nofile 65536
, где * – это “для всех пользователей”, а 65536 само максимальное кол-во открытых файлов

После перезагрузки или входа\выхода пользователя лимиты должны применяться и в целом это работает, но если не сработало, то проверьте еще лимиты которые назначены непосредственно процессу:

cat /proc/XXXXX/limits
,где XXXXX номер родительского процесс (легко узнать через “ps aux | grep process_name”

12.08.2019

Colored Fax with raspberry and hylafax+.

Для работа цветных факсов нужно использовать hylafax+ , не путать с обычным Hylafax. В целом установка проходит по порядку, основные проблемы это как обычно поставить все нужные пакеты аккуратно.

Для работы используются следующие статьи:

Hylafax+ на sourceforge скачать нужно последнюю версию 7+.

hylafax+ installation from svn.

hylafax+ about colored fax – во время ./configure необходимо обратить внимание на то, что нужные библиотеки присутствуют в системе.

для работы понадобится iaxmodem и две библиотеки spandsp и libiax2, которые идут вместе с iaxmodem.

  1. Скачать hylafax+ и скомпилировать, во время компиляции gs программа была не найдена, но я просто создал symlink на то место где hylfax+ её искала. хотя это не обязательно.
  2. скачать iaxmodem и скомпилировать две библиотеки идущие с ним в папке Lib. (кстати вероятно этот шаг можно облегчить, если использовать готовые пакеты с iaxmodem )
  3. Сконнектить iaxmodem с астериском, статьи которые помогут это сделать: статья про обычный hylafax и связке с астериском, у меня в прицнипе получилось всё сделать через web freepbx, единственное, что если Host для iax пользователя установить как 127.0.0.1 то, регистрация не проходила, либо проходила с ошибкой, поэтому я сделал dynamic, но permit выставил для 127.0.0.1/32 . О запуске модема можно также в этой статье почитать, но и описание внутри пакета тоже простое и подробное.
  4. После того как модем появился в системе, можно запустить faxgetty и позвонить на номер модема в примере он указан как iaxmodem0, но я использовал 2000.

Для тестирования факсов использовал кстати, ventafax – Это программа с очень долгой историей, но удивительно робит и сейчас.

3.07.2019

Asterisk as Wholesale. PAMI instead of AGI. Stable AMI connection.

Во время выполнения диалплана необходимо уточнять маршруты для звонка и делать то нужно из базы Mysql. Классический вариант использовать AGI Либо FastAGI, Но здесь я рассмотрю вариант запуска в фоне скрипта который, получая информацию о звонке, будет устанавливать переменную обратно в диалплан.

Asterisk адаптированный для wholesale, кстати, достаточно быстро всё обрабатывает используя минимум модулей и запросы в базу через ODBC. на удивление. Но всё равно с Opensips И Kamailio не сравнится.

Используем: PAMI library при установке пришлось повозиться т.к. не очень знаком с composer, но почитав про него – всё получилось. библиотеки ставятся в текущую директорию agi-bin, тогда будет доступ.

Основная проблема это поддержка коннекта между скриптом и астером, а также отсутствие ошибок между ними. Если вы запустите по умолчанию скрипты с ами, то вы наверняка получите внезапное завершение программы при анализе event от астериска. Есть несколько факторов, которые влияют на стабильность соединения:

  1. read timeout\read error – возникает на стороне скрипта, нужно обрабатывать такие события, в скрипте для этого будет try { } catch {}.
  2. Снизить поток событий из Астериска. В manager.conf Использовать eventfilter=Event: Newchannel тогда пользователю будет прилетать только определенный события.
  3. Не подключаться каждый раз при чтении и записи. В рамках библиотеки PAMI пришлось разбираться с классами в php.
  4. Астериск должен подождать в диалплане пока AMI скрипт установит переменную в канал, вот тут я не нашел ничего лучше чем просто подвесить его на 1500 циклов присвоения переменной – это ужасно я знаю.

Пример pami.php

Пример extensions.conf

Пример manager.conf

28.06.2019

Freepbx – Google Speech API – Directory recognition

Задача: При входящем звонке распознавать Имя или Фамилию сотрудника и переводить на него.

Особенностью является то, что распознавание имён удалось улучшить подключив параметры:

 model:phone,
useEnhanced: true,
phrases: [{"слово1", "Фраза из слов"}],

Используемые статьи:

  1. Приложение на базе node.js и bash скрипта которое позволяет быстро развернуть систему и провести первые тесты: https://github.com/phsultan/asterisk-eagi-google-speech-recognition
  2. процесс подключения телефона есть много разных статей но самая удобная и работающая у меня вот эта: Распознавание речи в Asterisk – Voxlink
  3. Докуметация от гугла

Проблемы: 1. установка окружения Node.js для меня в новинку была поэтому, пришлось сначала понять как устроено приложение Node.js.

отладка:

  1. asterisk -r – покажет исполнение скрипта и распознанные слова, если распознанных слов нет, то пункт 2
  2. в папке /usr/local/node_programs/node_speech/samples выполнить: “node recognize.js listen”.
  3. если выдаст “Error: Could not load the default credentials.” то выполнить команду “export GOOGLE_APPLICATION_CREDENTIALS=/usr/local/node_programs/service_account_file.json” – Она добавит данные по авторизации. и снова выполнить пункт 2.
  4. Если выдаст ошибку “invalid_grant: Invalid JWT Signature” то у вас проблемы с ключем от гугла. Решение создать ключ в JSON формате для вашего проекта через https://console.cloud.google.com

2.05.2019

custom script AGI freepbx per each call

to do any custom dialplan per call (inbound from trunk to extensions) use

macro-dialout-one-predial-hook

to do any custom macro action for outgoing from trunk use:

macro-dialout-trunk-predial-hook

Tags: ,
| Posted in Asterisk | No Comments »
1.05.2019

Черный список ip адресов для voip

sh скрипт который

!/bin/bash
BADIPSFILE="badips.list"
BADIPSFILETEMP="$BADIPSFILE".temp
ADDLISTFILE="$BADIPSFILE".load
# get new list
wget https://www.badips.com/get/list/voip/0 -O $BADIPSFILETEMP
# sort new list
sort $BADIPSFILETEMP -o $BADIPSFILETEMP
# touch to be sure that file exist
touch $BADIPSFILE
# diff old ans new file
diff $BADIPSFILE $BADIPSFILETEMP | grep -Po '\d+.\d+.\d+.\d+' > $ADDLISTFILE
# copy new file to old for next ips going fast
cp -f $BADIPSFILETEMP $BADIPSFILE
cp -f drop_temp.xml drop_temp_.xml
BLOCKED_IP=$ADDLISTFILE
IPTABLES="iptables"
if [ -f $BLOCKED_IP ]; then
while read BLOCKED; do
$IPTABLES -A INPUT_direct -i ens192 -s $BLOCKED -p udp -j DROP
done < $BLOCKED_IP
fi

8.04.2019

troubleshoot. ACK sending to wrong host

picture when ACK sending to wrong dest

solve is add function fix_sdp_contact() into onreply_route .

по-русски: проблема была в том, что опенсипс получая ACK от абонента не пересылал его обратно, через внутренний интерфейс железке. А слал ACK напрямую тому, кто указан был в 200 OK оригинальном. в Итоге помогло добавление функции в onreply_route которая по идее должна заменять поле контакт на адрес источника запроса.