Остання активність 1740110017

php

Версія 094379db1c184ac53f9354fc18156ee1db0c2f26

AMI.php Неформатований
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 */
12class 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}