Utoljára aktív 1740110017

php
AMI.php Eredeti
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 */
14class 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}