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