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