AMI.php
· 5.1 KiB · 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/
*/
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);
}
}
}
| 1 | /** |
| 2 | * Класс для работы с Asterisk по протоколу AMI через сокет. |
| 3 | * Реализовано: подключение, авторизация, отправка команд, отправка СМС, отключение. |
| 4 | * Успешно работало на проде в связке с Yeastar TG400. |
| 5 | * |
| 6 | * Class to work with Asterisk gateway throuth AMI protocol via socket. |
| 7 | * Features: connection, authorization, send commands, send SMS, disconnect. |
| 8 | * Successfully used in production with Yeastar TG400. |
| 9 | * |
| 10 | * @see https://habr.com/post/253387/ |
| 11 | */ |
| 12 | class AMI { |
| 13 | |
| 14 | /** string Параметры подключения к Asterisk. Asterisk config. */ |
| 15 | private const AMI_HOST = '192.168.1.19'; |
| 16 | private const AMI_PORT = 5038; |
| 17 | private const AMI_USER = 'user'; |
| 18 | private const AMI_PASS = 'useruser'; |
| 19 | |
| 20 | /** int Код последней операции. Last action ID. */ |
| 21 | public $lastActionID = 0; |
| 22 | |
| 23 | /** array Массив строк результата последней операции. Array of strings with result of last action. */ |
| 24 | public $lastRead = []; |
| 25 | |
| 26 | /** resource Подключение к сокету. Connection socket. */ |
| 27 | private $connection; |
| 28 | |
| 29 | /** array Описывает данные о последней СМС. Describes last SMS data. */ |
| 30 | private $sms_data = []; |
| 31 | |
| 32 | /** |
| 33 | * AMI constructor. |
| 34 | */ |
| 35 | function __construct() { |
| 36 | $this->connect(); |
| 37 | } |
| 38 | |
| 39 | /** |
| 40 | * Соединяет со шлюзом. |
| 41 | * Connects with gateway. |
| 42 | * |
| 43 | * @return bool |
| 44 | */ |
| 45 | public function connect() { |
| 46 | $this->connection = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); |
| 47 | if ($this->connection === FALSE) { |
| 48 | echo "Cannot socket_create(): ".socket_strerror(socket_last_error())."\n"; |
| 49 | return FALSE; |
| 50 | } |
| 51 | if (socket_connect($this->connection, self::AMI_HOST, self::AMI_PORT) === FALSE) { |
| 52 | echo "Cannot socket_connect(): ".socket_strerror(socket_last_error())."\n"; |
| 53 | return FALSE; |
| 54 | } |
| 55 | return TRUE; |
| 56 | } |
| 57 | |
| 58 | /** |
| 59 | * Авторизирует на шлюзе. |
| 60 | * Authorizes on gateway. |
| 61 | * |
| 62 | * @return bool |
| 63 | */ |
| 64 | public function auth(): bool { |
| 65 | $command = [ |
| 66 | "Action: Login", |
| 67 | "Username: ".self::AMI_USER, |
| 68 | "Secret: ".self::AMI_PASS, |
| 69 | ]; |
| 70 | $this->command($command); |
| 71 | return $this->lastRead["Response"] === "Success"; |
| 72 | } |
| 73 | |
| 74 | /** |
| 75 | * Пишет данные в сокет. |
| 76 | * Writes data into socket. |
| 77 | * |
| 78 | * @param array $command |
| 79 | * @return int |
| 80 | */ |
| 81 | public function write(array $command): int { |
| 82 | $this->lastActionID = rand(10000000000000000, 99999999900000000); |
| 83 | $string = implode("\r\n", $command); |
| 84 | socket_write($this->connection, "ActionID: {$this->lastActionID}\r\n{$string}\r\n\r\n"); |
| 85 | return $this->lastActionID; |
| 86 | } |
| 87 | |
| 88 | /** |
| 89 | * Читает данные из сокета. |
| 90 | * Reads data from socket. |
| 91 | * |
| 92 | * @return array |
| 93 | */ |
| 94 | public function read(): array { |
| 95 | $result = []; |
| 96 | $data = socket_read($this->connection, 1024); |
| 97 | $data = str_replace("Asterisk Call Manager/1.1\r\n", '', $data); |
| 98 | $data = explode("\r\n", trim($data)); |
| 99 | foreach ($data as $key => $string) { |
| 100 | $pos = strpos($string, ':'); |
| 101 | $key = substr($string, 0, $pos); |
| 102 | $string = substr($string, $pos + 2, strlen($string)); |
| 103 | $result[$key] = $string; |
| 104 | } |
| 105 | return $this->lastRead = $result; |
| 106 | } |
| 107 | |
| 108 | /** |
| 109 | * Отправляет команду шлюзу и возвращает ответ. |
| 110 | * Sends command throuth socket and returns response. |
| 111 | * |
| 112 | * @param array $command |
| 113 | * @return array |
| 114 | */ |
| 115 | public function command(array $command): array { |
| 116 | $this->write($command); |
| 117 | return $this->read(); |
| 118 | } |
| 119 | |
| 120 | /** |
| 121 | * Отправляет СМС. |
| 122 | * Sends SMS. |
| 123 | * |
| 124 | * @param string $phone_number |
| 125 | * @param string $sms_text |
| 126 | * @param int $sim_id |
| 127 | * @return int SMS ID |
| 128 | */ |
| 129 | public function sendSMS(int $dispatch_id, string $phone_number, string $sms_text, int $sim_id): int { |
| 130 | $this->sms_data['sim_id'] = $sim_id; |
| 131 | $this->sms_data['phone_number'] = $phone_number; |
| 132 | $this->sms_data['text'] = $sms_text; |
| 133 | $this->sms_data['date_send'] = date('Y-m-d H:i:s'); |
| 134 | // $this->sms_data['date_status'] = "NULL"; |
| 135 | $this->sms_data['status'] = 0; |
| 136 | $smsid = $this->writeSmsReport(); |
| 137 | $command = [ |
| 138 | "Action: smscommand", |
| 139 | "command: gsm send sms ".($sim_id + 1)." {$phone_number} \"".urlencode($sms_text)."\" ID{$smsid}", |
| 140 | ]; |
| 141 | $this->command($command); |
| 142 | return $smsid; |
| 143 | } |
| 144 | |
| 145 | /** |
| 146 | * Отключает от шлюза и закрывает сокет. |
| 147 | * Disconnects from gateway and closes socket. |
| 148 | */ |
| 149 | public function disconnect() { |
| 150 | if ($this->connection) { |
| 151 | $this->write(["Action: Logoff"]); |
| 152 | socket_close($this->connection); |
| 153 | } |
| 154 | } |
| 155 | } |