Автоматическая работа с SMS на модеме ZTE-MF823

от автора

Данный модем не является модемом, как таковым. Это роутер с процессором arm v7 на базе Linux, в системе отображается в виде сетевой карты, без проблем заводится в Линуксе (сетевой интерфейс usb0, подсеть 192.168.0.0).

К устройству можно подключаться по telnet (ip: 192.168.0.1, login: root, password: zte9x15), дальше внедрять свои iptables, вешать скрипты в crontab и многое другое, даже устанавливать собственное по, но сегодня речь не об этом.

Для выполнения операций с модемом необходимо выполнять CGI запросы к веб-интерфейсу, подойдет wget или curl. В модеме от мегафон нет веб-морды, а вот в билайновском есть. Web-морда представляет из себя браузерное JavaScript-приложение, которое отправляет аяксом эти самые CGI запросы, ни каких годных документаций по работе с sms на просторах интернета я найти не смог, поэтому решил залить веб-морду и отловить запросы.

Для работы с SMS нужно отправлять POST-запросы на адрес 192.168.0.1/goform/goform_set_cmd_process

Отправка SMS

goformId=SEND_SMS
notCallback=true
Number=номер абонента
sms_time= дата в формате y;m;d;h;i;s
MessageBody=текст сообщения
ID=-1
encode_type=UNICODE

Удаление SMS

goformId=DELETE_SMS
msg_id=список id сообщений, разделенный точкой с запятой
notCallback=true

Получение SMS
Для получения всех сообщений в формате json, нужно обратиться по адресу
192.168.0.1/goform/goform_get_cmd_process?cmd=sms_data_total&page=0&data_per_page=5000&mem_store=1&tags=10&order_by=order+by+id+desc
в ответ мы получим массив всех SMS в формате JSON.

C удалением sms всё просто, а вот с получением и отправкой следующая беда — каждый символ кодируется HEX-кодом UTF, получаем код символа функцией ord(), переводим то что получилось в 16-ричную систему счисления и добиваем нулями до 4х сиволов, для обратной раскодировки сообщений делим текст по 4 символа, переводим в 10-ричную систему счисления и получаем символ по его номеру функцией chr(). Казалось бы, всё так просто, да вот только php не особо то хорошо работает с юникодов, поэтому пришлось изобретать какие то велосипеды и быдлокодить, в итоге 3х часовых опытов получился PHP класс для работы с sms на данном модеме.

<?php mb_internal_encoding("UTF-8");  class ZTE_WEB { 	public $ip="192.168.0.1",$tz="+5";  	public function url($url,$post="") 	{ 			$ch = curl_init($url); 			curl_setopt($ch,CURLOPT_RETURNTRANSFER,true); 			curl_setopt($ch,CURLOPT_BINARYTRANSFER,false); 			curl_setopt($ch,CURLOPT_HEADER,false); 			curl_setopt($ch,CURLOPT_TIMEOUT, 90); 			$header = array(); 			$header[] = 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8'; 			$header[] = 'Accept-Charset: Windows-1251,utf-8;q=0.7,*;q=0.7'; 			$header[] = 'Accept-Language: ru-ru,ru;q=0.8,en-us;q=0.5,en;q=0.3'; 			$header[] = 'Pragma: '; 			curl_setopt($ch, CURLOPT_HTTPHEADER, $header); 			unset ($header); 			if(!empty($post)) {curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, $post);} 	        $content = curl_exec($ch); 			curl_close($ch); 	        return $content; 	}  	public function utf2hex($str) 	{ 		$l=mb_strlen($str); 		$res=''; 		for ($i=0;$i<$l;$i++) 		{	 			$s = mb_substr($str,$i,1); 			$s = mb_convert_encoding($s, 'UCS-2LE', 'UTF-8'); 	    	$s = dechex(ord(substr($s, 1, 1))*256+ord(substr($s, 0, 1))); 	    	if (mb_strlen($s)<4) $s = str_repeat("0",(4-mb_strlen($s))).$s; 	    	$res.=$s;     	}     	return $res;  	}  	public function hex2utf($str) 	{ 		$l=mb_strlen($str)/4; 		$res=''; 		for ($i=0;$i<$l;$i++) $res.=html_entity_decode('&#'.hexdec(mb_substr($str,$i*4,4)).';',ENT_NOQUOTES,'UTF-8');     	return $res;  	}  	//отправляет смску 	public function send($number,$text) 	{ 		$url = 'http://'.$this->ip.'/goform/goform_set_cmd_process'; 		$post='isTest=false&'; 		$post.= 'goformId=SEND_SMS&'; 		$post.= 'notCallback=true&'; 		$post.= 'Number='.urlencode($number).'&'; 		$date = gmdate('y;m;d;h;i;s;'.$this->tz,time()+($this->tz*3600)); 		$post.= 'sms_time='.urlencode($date).'&'; 		$post.= 'MessageBody='.($this->utf2hex($text)).'&'; 		$post.= 'ID=-1&'; 		$post.= 'encode_type=UNICODE'; 		return $this->url($url,$post); 	}  	//возвращает массив всех смсок 	public function get_sms() 	{ 		$cont=$this->url('http://'.$this->ip.'/goform/goform_get_cmd_process?cmd=sms_data_total&page=0&data_per_page=5000&mem_store=1&tags=10&order_by=order+by+id+desc'); 		$cont = json_decode($cont,true); 		$cont = $cont['messages']; 		foreach ($cont as $id => $arr) $cont[$id]['content']=$this->hex2utf(($cont[$id]['content'])); 		return $cont; 	}  	//удаляет все смс 	public function clear_sms($cont=0) 	{ 		if ($cont===0) $cont=$this->get_sms(); 		$list_id=''; 		$url = 'http://'.$this->ip.'/goform/goform_set_cmd_process'; 		foreach ($cont as $id => $arr) $list_id.=$cont[$id]['id'].';'; 		$post='isTest=false&goformId=DELETE_SMS&msg_id='.urlencode($list_id).'¬Callback=true'; 		return $this->url($url,$post); 	}  }  $zte = new ZTE_WEB; //отправка $zte->send("+79220000000","проверка"); //чистка $zte->clear_sms($zte->get_sms()); //получение $zte->get_sms(); ?> 

Предполагается, что скрипты на php будут получать все сообщения, а потом делать зачистку памяти модема.
Данный модем подключен к Raspberry Pi, в кронтабе будут висеть различные обработчики sms и бот, который будет реагировать на команды, отправленные с доверенных номеров и принимать определенные решения.

ссылка на оригинал статьи https://habrahabr.ru/post/277637/