Дмитрий Кайдаш
14.10.2019
7428

Использование библиотеки PAMI для работы с AMI серверов asterisk.

Описание: в этой статье будет описано как установить, подключить к проекту и использовать библиотеку PAMI. Назначение PAMI заключается в предоставлении готового класса и методов работы с ami в asterisk. Что позволит из скриптов на PHP осуществлять обширный спектр манипуляций. Сюда включается как получение информации, так и отправка команд для осуществления звонков, смены статусов агентов очередей […]

Описание: в этой статье будет описано как установить, подключить к проекту и использовать библиотеку PAMI.

Назначение PAMI заключается в предоставлении готового класса и методов работы с ami в asterisk. Что позволит из скриптов на PHP осуществлять обширный спектр манипуляций. Сюда включается как получение информации, так и отправка команд для осуществления звонков, смены статусов агентов очередей и многое другое.

Приступим к установке. А проводить мы её будем через установщик пакетов и зависимостей PHP –composer.

Если на вашем сервере его нет, можно установить по следующей инструкции: https://www.vultr.com/docs/setup-composer-for-php-dependencies-on-centos-6

Следующим шагом выкачаем саму библиотеку PAMI из репозитория github. Буквально в первых ссылках поиска:

Поиск библиотеки PAMI
Поиск библиотеки PAMI

Переходим. В открывшейся странице находим ссылку на клонирование и копируем её в буфер обмена

Ссылка на библиотеку
Ссылка на библиотеку

Далее открываем доступ к нашему целевому серверу по ssh, переходим в рабочую директорию и осуществляем скачивание командой:

# git clone https://github.com/marcelog/PAMI.git
Директория библиотеки после скачивания
Директория библиотеки после скачивания

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

# nano PAMI/composer.json

И заменяем кучу лишнего текста на необходимый в наших эксперементах код:

{
       "require": {
              "marcelog/pami": "2.*"
       }
}
Указание зависимостей для composer
Указание зависимостей для composer

Возвращаемся в основную директорию и отдаём команду на установку\скачивание\обновление:

# ./composer.phar install
 Процесс установки зависимостей и пакетов
Процесс установки зависимостей и пакетов

Теперь нам необходимо убедиться в наличии директории «vendor».

# ls –l
Наличии директории vendor
Наличии директории vendor

Теперь нам понадобятся учётные данные для подключения к AMI. Создадим их. Открываем на редактирование файл:

# nano /etc/asterisk/manager_custom.conf

И добавляем в него свои учётные данные по следующему образцу:

[user]
secret = pass
deny=0.0.0.0/0.0.0.0
permit=127.0.0.1/255.255.255.0
read = system,call,log,verbose,command,agent,user,config,command,dtmf,reporting,cdr,dialplan,originate,message
write = system,call,log,verbose,command,agent,user,config,command,dtmf,reporting,cdr,dialplan,originate,message
writetimeout = 5000
Учётные данные для AMI
Учётные данные для AMI

Предварительные работы завершены, библиотека установлена и обновлена – переходим к испытаниям и демонстрации.

Напишем простейший скрипт в задачи которого будет вменяться:

  1. Подключение к сокету
  2. Чтение всех событий
  3. Вывод в консоль
  4. Простой в несколько сотых секунды
  5. Отключение от сокета

Он примет следующий вид:

<?php
require __DIR__ . '/vendor/autoload.php';

Самое важное: подключаем к проекту библиотеку PAMI.

$options = [
    'host' => '127.0.0.1',
    'scheme' => 'tcp://',
    'port' => 5038,
    'username' => '******manager',
    'secret' => '8D******************zy',
    'connect_timeout' => 10000,
    'read_timeout' => 10000
];

Заполняем массив данными для подключения. В большинстве случаев достаточно изменить только логин и пароль.

use PAMI\Client\Impl\ClientImpl as PamiClient;
use PAMI\Message\Event\EventMessage;
use PAMI\Listener\IEventListener;
use PAMI\Message\Event\DialEvent;

Перечисляем нужные методы класса для работы с прослушиванием.

$pamiClient = new PamiClient($options);

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

$pamiClient->open();

Объявляем открытие соединения

miClient->registerEventListener(
    function (EventMessage $event) {
        print_r($event);
    }
);
while(true) {
    $pamiClient->process();
    usleep(1000);
}

Устанавливаем прослушку и вывод событий в консоль с небольшой задержкой.

$pamiClient->close();
?>

Разрываем соединение и завершаем скрипт.

Полный скипт
Полный скипт

Пробуем выполнить. Если все действия произведены корректно вы увидите следующее:

Демо работы скрипта слушателя
Демо работы скрипта слушателя

Если всё успешно можем переходить к следующей стадии: показу возможностей самой библиотеки. Для этого по ссылке.

Есть очень крупный скрипт-пример. На его основе мы и рассмотрим некоторые примеры.

Давайте сперва повторим скрипт выше? Для этого приведём example.php к следующему виду:

1. Комментируем или удаляем фрагмент (строки 30-34)

if ($argc != 7) {
    echo "Use: $argv[0] <host> <port> <user> <pass> <connect timeout> <read timeout>";
    exit (254);
}

2. Указываем наши доступы (строки 142-150):

    $options = array(
              'host' => '127.0.0.1',
              'scheme' => 'tcp://',
              'port' => 5038,
              'username' => 'fr******_manager',
              'secret' => '8DM**************8Ghzy',
              'connect_timeout' => 10000,
              'read_timeout' => 10000
    );

3. Удаляем или комментируем все строки образцы, оставляем лишь:

try{
       $options = array(
              'host' => '127.0.0.1',
              'scheme' => 'tcp://',
              'port' => 5038,
              'username' => 'fr******_manager',
              'secret' => '8DM**************8Ghzy',
              'connect_timeout' => 10000,
              'read_timeout' => 10000
    );
       $a = new ClientImpl($options);
    // Register an IEventListener:
       $a->registerEventListener(new A());
       $a->open();   
$a->close(); // send logoff and close the connection.
} 
catch(Exception $e){
       echo $e->getMessage() . "\n";
}

И запускаем подобно предыдущему. Если всё корректно результат будет аналогичным.

Для примера, давайте ещё посмотрим на регистрацию транков, проверим каналы и отправим originate.

  1. Регистрация транков

Комментируем или удаляем всё за искоючением строки (171):

var_dump($a->send(new SIPShowRegistryAction()));

После выполнения в консоли мы получим примерно следующий результат:

object(PAMI\Message\Event\UnknownEvent)#10 (6) {       ["rawContent":protected]=>
              string(211) " Event: RegistryEntry
                                  ActionID: 1566974263.5811
                                  Host: 1016.voxlink.ru
                                  Port: 5060
                                  Username: 74993809039
                                  Domain: 1016.voxlink.ru
                                  DomainPort: 5060
                                  Refresh: 105
                                  State: Registered
                                  RegistrationTime: 1566974251"
       ["channelVariables":protected]=>
              array(1) {
                    ["default"]=> array(0){}
              }
       ["lines":protected]=> array(0) {}
       ["variables":protected]=> array(0) {}
       ["keys":protected]=>
              array(10) {
                    ["event"]=> string(13) "RegistryEntry"
                    ["actionid"]=> string(15) "1566974263.5811"
                    ["host"]=> string(15) "1016.voxlink.ru"
                    ["port"]=> string(4) "5060"
                    ["username"]=> string(11) "74993809039"
                    ["domain"]=> string(15) "1016.voxlink.ru"
                    ["domainport"]=> string(4) "5060"
                    ["refresh"]=> string(3) "105"
                    ["state"]=> string(10) "Registered"
                    ["registrationtime"]=> string(10) "1566974251"
              }
       ["createdDate":protected]=> int(1566974263)
}

Это описывает состояние одного из транков на стендовом asterisk.

2. Текущие каналы

Удаляем или комментируем всё кроме строки (167):

var_dump($a->send(new CoreShowChannelsAction()));

Совершаем звонок и запускаем наш скрипт-монитор. Должно получиться следующее: это звонок между внутренними номерами 712 и 0712.

object(PAMI\Message\Event\CoreShowChannelEvent)#9 (6) {       ["rawContent":protected]=>
              string(452) "Event: CoreShowChannel
              ActionID: 1566975057.0976
              Channel: SIP/712-00000064
              ChannelState: 6
              ChannelStateDesc: Up
              CallerIDNum: 712
              CallerIDName: 712
              ConnectedLineNum: 0712
              ConnectedLineName: 0712
              Language: ru
              AccountCode:
              Context: from-internal
              Exten:
              Priority: 1
              Uniqueid: 1566975051.136
              Linkedid: 1566975051.135
              Application: AppDial
              ApplicationData: (Outgoing Line)
              Duration: 00:00:05
              BridgeId: c45de1ca-9846-4ff3-9941-89261893fbc5"
       ["channelVariables":protected]=> array(1) {
              ["sip/712-00000064"]=> array(0) {}
       }
       ["lines":protected]=> array(0) {}
       ["variables":protected]=> array(0) {}
       ["keys":protected]=> 
              array(20) {
                    ["event"]=> string(15) "CoreShowChannel"
                    ["actionid"]=> string(15) "1566975057.0976"
                    ["channel"]=> string(16) "SIP/712-00000064"
                    ["channelstate"]=> string(1) "6"
                    ["channelstatedesc"]=> string(2) "Up"
                    ["calleridnum"]=> string(3) "712"
                    ["calleridname"]=> string(3) "712"
                    ["connectedlinenum"]=> string(4) "0712"
                    ["connectedlinename"]=> string(4) "0712"
                    ["language"]=> string(2) "ru"
                    ["accountcode"]=> string(0) ""
                    ["context"]=> string(13) "from-internal"
                    ["exten"]=> string(0) ""
                    ["priority"]=> string(1) "1"
                    ["uniqueid"]=> string(14) "1566975051.136"
                    ["linkedid"]=> string(14) "1566975051.135"
                    ["application"]=> string(7) "AppDial"
                    ["applicationdata"]=> string(15) "(Outgoing Line)"
                    ["duration"]=> string(8) "00:00:05"
                    ["bridgeid"]=> string(36) "c45de1ca-9846-4ff3-9941-89261893fbc5"
              }
       ["createdDate":protected]=> int(1566975057)
}

Ну и напоследок выполнение Originate. Здесь нам нужно будет отредактировать блок строк, поэтому приведём их здесь (237-241):

$originateMsg = new OriginateAction('SIP/0712');
$originateMsg->setContext('from-internal');
$originateMsg->setPriority('1');
$originateMsg->setExtension('712');
var_dump($a->send($originateMsg));

Остальное, как уже можете догадаться – удаляем или комментируем и выполняем скрипт. Если всё верно произойдёт следующее:

Выполнение originate
Выполнение originate
Подписаться
Уведомление о
guest
0 Комментарий
Inline Feedbacks
View all comments

Остались вопросы?

Я - Виталий Шелест, менеджер компании Voxlink. Хотите уточнить детали или готовы оставить заявку? Укажите номер телефона, я перезвоню в течение 3-х секунд.

VoIP оборудование

ближайшие курсы

ближайшие Вебинары

ONLINE

10 доводов в пользу Asterisk

Распространяется бесплатно.

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

Безопасен в использовании.

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

Надежен в эксплуатации.

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

Гибкий в настройке.

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

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

Во многом именно Asterisk показал какой должна быть современная телефонная станция. За многие годы развития функциональность Asterisk расширилась, а все основные возможности по-прежнему доступны бесплатно сразу после установки.

Интегрируется с любыми системами.

То, что Asterisk не умеет сам, он позволяет реализовать за счет интеграции. Это могут быть интеграции с коммерческими телефонными станциями, CRM, ERP системами, биллингом, сервисами колл-трекинга, колл-бэка и модулями статистики и аналитики.

Позволяет телефонизировать офис за считанные часы.

В нашей практике были проекты, реализованные за один рабочий день. Это значит, что утром к нам обращался клиент, а уже через несколько часов он пользовался новой IP-АТС. Безусловно, такая скорость редкость, ведь АТС – инструмент зарабатывания денег для многих компаний и спешка во внедрении не уместна. Но в случае острой необходимости Asterisk готов к быстрому старту.

Отличная масштабируемость.

Очень утомительно постоянно возвращаться к одному и тому же вопросу. Такое часто бывает в случае некачественного исполнения работ или выбора заведомо неподходящего бизнес-решения. С Asterisk точно не будет такой проблемы! Телефонная станция, построенная на Asterisk может быть масштабируема до немыслимых размеров. Главное – правильно подобрать оборудование.

Повышает управляемость бизнеса.

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

Снижает расходы на связь.

Связь между внутренними абонентами IP-АТС бесплатна всегда, независимо от их географического расположения. Также к Asterisk можно подключить любых операторов телефонии, в том числе GSM сим-карты и настроить маршрутизацию вызовов по наиболее выгодному тарифу. Всё это позволяет экономить с первых минут пользования станцией.