gists/php/AMI.php

159 lines
5.1 KiB
PHP
Raw Permalink Normal View History

2022-01-11 00:13:24 +00:00
<?php
/**
* Класс для работы с Asterisk по протоколу AMI через сокет.
* Реализовано: подключение, авторизация, отправка команд, отправка СМС, отключение.
* Успешно работало на проде в связке с Yeastar TG400.
*
* Class to work with Asterisk gateway throuth AMI protocol via socket.
* Features: connection, authorization, send commands, send SMS, disconnect.
* Successfully used in production with Yeastar TG400.
*
* @see https://habr.com/post/253387/
* @see https://gist.github.com/anthonyaxenov/12cff2bea5fae1f1c5b40b886340b2ba
*/
class AMI {
/** string Параметры подключения к Asterisk. Asterisk config. */
private const AMI_HOST = '192.168.1.19';
private const AMI_PORT = 5038;
private const AMI_USER = 'user';
private const AMI_PASS = 'useruser';
/** int Код последней операции. Last action ID. */
public $lastActionID = 0;
/** array Массив строк результата последней операции. Array of strings with result of last action. */
public $lastRead = [];
/** resource Подключение к сокету. Connection socket. */
private $connection;
/** array Описывает данные о последней СМС. Describes last SMS data. */
private $sms_data = [];
/**
* AMI constructor.
*/
function __construct() {
$this->connect();
}
/**
* Соединяет со шлюзом.
* Connects with gateway.
*
* @return bool
*/
public function connect() {
$this->connection = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
if ($this->connection === FALSE) {
echo "Cannot socket_create(): ".socket_strerror(socket_last_error())."\n";
return FALSE;
}
if (socket_connect($this->connection, self::AMI_HOST, self::AMI_PORT) === FALSE) {
echo "Cannot socket_connect(): ".socket_strerror(socket_last_error())."\n";
return FALSE;
}
return TRUE;
}
/**
* Авторизирует на шлюзе.
* Authorizes on gateway.
*
* @return bool
*/
public function auth(): bool {
$command = [
"Action: Login",
"Username: ".self::AMI_USER,
"Secret: ".self::AMI_PASS,
];
$this->command($command);
return $this->lastRead["Response"] === "Success";
}
/**
* Пишет данные в сокет.
* Writes data into socket.
*
* @param array $command
* @return int
*/
public function write(array $command): int {
$this->lastActionID = rand(10000000000000000, 99999999900000000);
$string = implode("\r\n", $command);
socket_write($this->connection, "ActionID: {$this->lastActionID}\r\n{$string}\r\n\r\n");
return $this->lastActionID;
}
/**
* Читает данные из сокета.
* Reads data from socket.
*
* @return array
*/
public function read(): array {
$result = [];
$data = socket_read($this->connection, 1024);
$data = str_replace("Asterisk Call Manager/1.1\r\n", '', $data);
$data = explode("\r\n", trim($data));
foreach ($data as $key => $string) {
$pos = strpos($string, ':');
$key = substr($string, 0, $pos);
$string = substr($string, $pos + 2, strlen($string));
$result[$key] = $string;
}
return $this->lastRead = $result;
}
/**
* Отправляет команду шлюзу и возвращает ответ.
* Sends command throuth socket and returns response.
*
* @param array $command
* @return array
*/
public function command(array $command): array {
$this->write($command);
return $this->read();
}
/**
* Отправляет СМС.
* Sends SMS.
*
* @param string $phone_number
* @param string $sms_text
* @param int $sim_id
* @return int SMS ID
*/
public function sendSMS(int $dispatch_id, string $phone_number, string $sms_text, int $sim_id): int {
$this->sms_data['sim_id'] = $sim_id;
$this->sms_data['phone_number'] = $phone_number;
$this->sms_data['text'] = $sms_text;
$this->sms_data['date_send'] = date('Y-m-d H:i:s');
// $this->sms_data['date_status'] = "NULL";
$this->sms_data['status'] = 0;
$smsid = $this->writeSmsReport();
$command = [
"Action: smscommand",
"command: gsm send sms ".($sim_id + 1)." {$phone_number} \"".urlencode($sms_text)."\" ID{$smsid}",
];
$this->command($command);
return $smsid;
}
/**
* Отключает от шлюза и закрывает сокет.
* Disconnects from gateway and closes socket.
*/
public function disconnect() {
if ($this->connection) {
$this->write(["Action: Logoff"]);
socket_close($this->connection);
}
}
}