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

в 14:10, , рубрики: php, 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('https://'.$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).'&notCallback=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 и бот, который будет реагировать на команды, отправленные с доверенных номеров и принимать определенные решения.

Автор: PavelBelyaev

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js