Adatum
Сен
11
2014

Отправка СМС спомощю php, модуль mod-sms.php Умного Дома

3gphp
Добрый день, сегодня я завел Github для проекта Adatum+ «Умный дом».
— Github SmartHomeAdatum
Но статья не об этом. Я расскажу как в моей системе происходит отправка СМС с помощью 3G модема.
Думаю это пригодится многим и в их проектах. Работать будем под Linux с помощью библиотечки PHP-Serial — PHP-Serial.
Наш модем подключённый в Ubuntu определиться как несколько устройств
-ttyUSB0
-ttyUSB1
-ttyUSB2
-ttyUSB3
Может больше может меньше нам нужно предпоследнее, в моем случае ttyUSB2.

Библиотеку PHP-Serial можно скачать у автора PHP-Serial, а библиотеку
ucs2cp1251.class.php здесь ucs2cp1251.class.php .

Сначала подключаем библиотеки PHP-Serial и Библиотеку работы с СМСucs2cp1251.class.php

<?php
include "ucs2cp1251.class.php";
include "PhpSerial.php";

// подключение адаптера
$serial = new phpSerial;
$serial->deviceSet("/dev/ttyUSB2");
$serial->confBaudRate(9600);
$serial->confParity("none");
$serial->confCharacterLength(8);
$serial->confStopBits(1);
$serial->confFlowControl("none");
$serial->deviceOpen();
// подключение адаптера
?>

Далее отключаем эхо на COM — порте

<?php
// отключаем режим эхо на ком порте
exec("stty  -F /dev/ttyUSB2 -echo");
// отключаем режим эхо на ком порте
?>

Теперь можно работать с модемом

Для начала включим модем, затем переведём его в цифровой режим (необходимо для работы с русскими буквами), указываем с какой памятью работать для СМС.
И включаем Автоматический определитель номера.

<?php
$serial->sendMessage("AT+CFUN=1\n");                           //Включить модем
$serial->sendMessage("AT+CMGF=0\n"); 			       //Цифровой режим
$serial->sendMessage("AT+CPMS=\"ME\",\"SM\",\"MT\""); 	      // От куда читаем смс
$serial->sendMessage("AT+CLIP=1\n");                          //Включение АОН
?>

Теперь можно прочесть СМС из модема

на команду AT+CMGL=4 модем ответит примерно следующие

+ CMGL: 1,1,, 26 
07913366003000F3040B913366920547F40013001190412530400741AA8E5A9C5201
OK

где 1 — номер сообщения, 1-статус сообщения, 26 — длина сообщения.
Статус сообщений в памяти:
0 — «REC UNREAD» Полученные непрочитанные сообщения.
1 — «REC READ» Полученные прочитанные сообщения.
2 — «STO UNSENT» Сохраненные не отправленные сообщения.
3 — «STO SENT» Сохраненные отправленные сообщения.

<?php
$serial->sendMessage("AT+CMGL=4\n\r");  // отправляем модему команду
 чтение СМС.

$read = $serial->readPort();
if ($read) 
	{
if(strpos($read, "+CMGL")){       
     
// Ищем в принятой строке команду +CMGL означающую что последующий 
// текст это СМС.
$colstr = substr_count($read,"+CMGL"); 	echo "KOL: ".$colstr."\n\r";	
$lensrt = strlen($read); echo "LEN: ".$lensrt."\n\r";
$dlina =0;
$num = 0;	
$dlinacode=0;
while ($num <= $colstr-1) {
echo "NUM: ".$num."; "; 
$begin = strpos($read, "+CMGL",$dlina);
$end = strpos($read, "0791",$dlina);
$dlina=$end+5;
$string = substr($read, $begin+7, ($end-$begin-7));
$ends = strrpos($string, ",");
$colsimcod = floatval(substr($string, $ends+1,  ($ends+ $end-1)))*2+16;
echo "Colsimcod: ".$colsimcod."; "; 
$begincode = strpos($read, "0791",$dlinacode);
$dlinacode=$begincode+$colsimcod;
$codepdu = substr($read, $begincode, $colsimcod );
echo "CODE: ".$codepdu."; \n"; 

//Перекодируем полученное сообщение из PDU в читабельный вид 
// функции sms_decode() из библиотеки ucs2cp1251.class.php
list ($telnumber, $smsdec) = sms_decode($codepdu); 

//Перекодируем полученное сообщение из CP1251 в UTF8 с помощью
// функции CP1251toUTF8() из библиотеки ucs2cp1251.class.php
//(если у вас текст и так в UTF8 этого делать не нужно)
$smsdec=CP1251toUTF8($smsdec);

//Выводим номер абонента и СМС сообщение на экран.
echo " -> Telephone: ".$telnumber." SMS: ".$smsdec."\n"; 

//далее удаляем про читаное сообщение
$serial->sendMessage("AT+CMGD=".$num."\n"); 
$num++;
 }
  }
        }

?>

с приемом СМС вроде разобрались.

Теперь отправим СМС в русской кодировке в PDU формате.

Для отправки SMS нужно ввести команду:
AT+CMGS=«7923XXXXXXX» номер указывается в формате 11 знаков начиная с 7.
При отправке после ввода команды появится символ «>» означающий что можно вводить текст сообщения.
После ввода сообщения для отправки СМС сообщения нужно нажать сочетание CTRL+Z, а в нашем случае отправить в порт символ chr(26).

<?php

	$numb_in="7923XXXXXXX";	   //номер телефона
	$dat_in="HEllo Привет";	  // текст сообщения

// перекодируем текст из UTF8 в CP1251 
// функции utf8_to_win() из библиотеки ucs2cp1251.class.php
//(если у вас текст и так в CP1251 этого делать не нужно)
	$textsms = utf8_to_win($dat_in); 

//Определяем длин СМС сообщения 
// функции ATSMS() из библиотеки ucs2cp1251.class.php
	$lengthsms = ATSMS($numb_in, $textsms);	

//Кодируем текст сообщения в формат PDU 
//функции sendSMS() из библиотеки ucs2cp1251.class.php
	$encodesms = sendSMS($smsc_numb, $numb_in, $textsms);	

//Теперь отправляем наше СМС сообщение
	$serial->sendMessage("AT+CMGS=".$lengthsms."\n");
	$serial->sendMessage($encodesms);
	$serial->sendMessage(chr(26));

?>	

Теперь проверим уровень сигнала сотовой связи на модеме.

На команду AT+CSQ модем вернет два числа +CSQ: 17,0
где 17 — уровень сигнала. Может быть в диапазоне 0..31 или 99. Чем больше тем лучше, 99 значит его отсутствие.
0 — коэффициент ошибок связи. Может быть от 0 до 7, чем число меньше тем качество связи лучше.

<?php

$serial->sendMessage("AT+CSQ\n");   //отправляем модему команду
//проверки уровня сигнала.

$read = $serial->readPort();
if ($read) 
	{

// ищем в принятой строке команду +CSQ означающую что последующий 
// текст это уровень сигнала
if(strpos($read, "+CSQ")){
$begin = strpos($read, "+CSQ");
$string = substr($read, $begin+6, 2);

//Уровень сигнала показывается от 0 до 31 и 99(означает отсутствие
// сигнала), выведем его в % от 0 до 100%.
$string = floor(($string/31)*100);
if($string ==99){$string="0";}

// Уровень сигнала от 0 до 100%.
echo $string;
}
        }

?>	

Приём входящих звонков

Команда AT+CLIP=1 включает режим CLI (Calling Line Identification) или по русски АОН.
После его включения при входящем звонке будет отображаться
+CLIP: «+7XXXXXXXXXX»,145,»»,,»»,0 или
+CLIP: «+7XXXXXXXXXX»,145,»»,,«main»,0
Где
«+7XXXXXXXXXX», номер абонента
далее формат номера в сообщении:
145 — интернациональный формат.
129 — неизвестный.
Далее верность данных:
0 — данные верны.
1 — данные не дает оператор .
2 — данные недоступны из за ограничений сети.
и «main» — имя записи в записной книжке.

<?php
$serial->sendMessage("AT+CLIP=1\n");          //Включение АОН
// ищем в принятой строке команду +CLIP означающую что последующий 
// текст это входящий звонок.
 if(strpos($read, "+CLIP")){
$CALQ=$CALQ+1;
$begin = strpos($read, "+CLIP");
$end = strpos($read, ",145");
$string = substr($read, $begin+9, $end-$begin-10);

//Выводим номер телефона входящего звонка.
echo "RING: ".$string."\n ";

//После 2 входящий сбрасываем трубку командой <strong>ATH0</strong> чтобы не занимать модем.
if($CALQ>2){
  $serial->sendMessage("ATH0\n"); 
  $CALQ=0;
          }
}

?>	

Осуществление исходящих звонков

Звонок осуществляется командой ATD+7ХХХХХХХХХХ где 7ХХХХХХХХХХ номер телефона (11 знаков), обращаю ваше внимание что не все 3G модемы умеют звонить.

<?php
$serial->sendMessage("ATD+7ХХХХХХХХХХ;\n"); 
?>	

А теперь приведу полный код модуля

<?php
error_reporting(E_ALL); 
ini_set("display_errors", 1); 
include 's-head.php';
include "ucs2cp1251.class.php";
include "PhpSerial.php";


// проверка запущенной копии
$process = shell_exec('ps ax | grep mod-sms.php');if (substr_count($process,"/html/mod-sms.php")>1){echo "-> ".$date_today." ".$time_today." .......... Process is already running.\n";}else {
// проверка запущенной копии

//Проверка подключения устройства и установка COM порта
$result= mysqli_query($con, "SELECT * FROM data WHERE id='17'"); $row=mysqli_fetch_array($result); $namedev = $row['state'];
list ($nameport, $numport) = dev_detect($namedev); 
echo "-> ".$date_today." ".$time_today." -> Name: ".$nameport." Port: ".$numport."\n"; 
if($nameport) {
//Проверка подключения устройства и установка COM порта

//префикс ком порта
$resulttty= mysqli_query($con, "SELECT * FROM data WHERE id='19'"); $rowtty=mysqli_fetch_array($resulttty); $nametty = $rowtty['state'];
//префикс ком порта

// подключение адаптера
$serial = new phpSerial;
$serial->deviceSet("/dev/".$nametty.($numport-1)."");
$serial->confBaudRate(9600);
$serial->confParity("none");
$serial->confCharacterLength(8);
$serial->confStopBits(1);
$serial->confFlowControl("none");
$serial->deviceOpen();
// подключение адаптера

// отключаем режим эхо на ком порте
exec("stty  -F /dev/".$nametty.($numport-1)." -echo");
// отключаем режим эхо на ком порте

$serial->sendMessage("AT+CFUN=1\n");                           //Включить модем
$serial->sendMessage("AT+CMGF=0\n"); 							//Цифровой режим
$serial->sendMessage("AT+CPMS=\"ME\",\"SM\",\"MT\""); 				// от куда читаем смс
$serial->sendMessage("AT+CLIP=1\n");                    			//Включение АОН

$CALQ=0;
$previousMillis = 0;  

while (true)  //бесконечный цикл
{
//назначаем переменные даты и времени
$timereal = time()+$timezone;   //в формате Unixtime + часовой пояс
$date_today = date("Y.m.d",$timereal); 
$time_today = date("H:i:s",$timereal); 
//echo " -> Timereal: ".$timereal."; "; echo "Date_today: ".$date_today."; "; echo "Time_today: ".$time_today."\n\r; "; 
//назначаем переменные даты и времени

//пишем в базу если адаптер подключен
mysqli_query($con,"UPDATE data SET state='$timereal' WHERE id='13'");  
//пишем в базу если адаптер  подключен

$serial->sendMessage("AT+CMGL=4\n\r"); // чтение смс.

$read = $serial->readPort();
if ($read) 
	{
	
	
$currentMillis = round(microtime(1)*1000);
if($currentMillis - $previousMillis > 10000 ) //10 секунд
{                                                            
$previousMillis = $currentMillis; 


//отправка СМСс задержкой 500 миллисекунд

$res = mysqli_query($con,"SELECT * FROM `run` WHERE run ='0' AND mode ='SMS'  ORDER BY id DESC LIMIT 1");
if($res) {   while($row = mysqli_fetch_assoc($res)) 
   {	
	$numb_in=$row['vale1'];	   //номер телефона
	$dat_in=$row['vale2'];	 // текст сообщения
	$resultsmsc_numb= mysqli_query($con, "SELECT * FROM data WHERE id='18'"); $rowsmsc_numb=mysqli_fetch_array($resultsmsc_numb); $smsc_numb = $rowsmsc_numb['state']; //номер смс центра
	echo "-> ".$date_today." ".$time_today." Send SMS to number ".$numb_in." SMS center ".$smsc_numb." text ".$dat_in."\n ";
	$textsms = utf8_to_win($dat_in);
	$lengthsms = ATSMS($numb_in, $textsms);	
	$encodesms = sendSMS($smsc_numb, $numb_in, $textsms);		
	$serial->sendMessage("AT+CMGS=".$lengthsms."\n");
	$serial->sendMessage($encodesms);
	$serial->sendMessage(chr(26));
	$vale_id=$row['id'];		
	mysqli_query($con,"DELETE FROM run WHERE id='$vale_id'");			// удаляем отправленную смс
	echo "-> ".$date_today." ".$time_today." Removal from the database of used commands.\n\r";
	
   }
mysqli_free_result($res); } 

//отправка смс с задержкой 300 миллисекунд



$serial->sendMessage("AT+CSQ\n");			//Уровень сигнала
}
	


//echo $read;

//-----------------------чтение смс----------------------------------------------------------------------------
if(strpos($read, "+CMGL")){
echo "\n\r--------------------===============================-----------------------\n\r";				
$colstr = substr_count($read,"+CMGL"); 	echo "KOL: ".$colstr."\n\r";	
$lensrt = strlen($read); echo "LEN: ".$lensrt."\n\r";
echo "\n\r--------------------===============================-----------------------\n\r";	
$dlina =0;
$num = 0;	
$dlinacode=0;
while ($num <= $colstr-1) {
echo "NUM: ".$num."; "; 
$begin = strpos($read, "+CMGL",$dlina);
$end = strpos($read, "0791",$dlina);
$dlina=$end+5;
$string = substr($read, $begin+7, ($end-$begin-7));
//echo $string."\n"; 
$ends = strrpos($string, ",");
$colsimcod = floatval(substr($string, $ends+1,  ($ends+ $end-1)))*2+16;
echo "Colsimcod: ".$colsimcod."; "; 
$begincode = strpos($read, "0791",$dlinacode);
$dlinacode=$begincode+$colsimcod;
//echo "begincode: ".$begincode."; \n"; 
$codepdu = substr($read, $begincode, $colsimcod );
echo "CODE: ".$codepdu."; \n"; 
list ($telnumber, $smsdec) = sms_decode($codepdu); 
$smsdec=CP1251toUTF8($smsdec);
echo " -> Telephone: ".$telnumber." SMS: ".$smsdec."\n"; 
mysqli_query($con,"INSERT INTO developments (mode, address, vale1, vale2, vale3, vale4, date, time,unixtime) VALUES ('SMS', '00000000', '$telnumber', '$smsdec', '', '', '$date_today', '$time_today', '$timereal')");
  $serial->sendMessage("AT+CMGD=".$num."\n"); 
$num++;
 }
  }
 //-----------------------чтение смс----------------------------------------------------------------------------
 
 
 //-----------------------Обработка звонков----------------------------------------------------------------------------
 if(strpos($read, "+CLIP")){
$CALQ=$CALQ+1;
$begin = strpos($read, "+CLIP");
$end = strpos($read, ",145");
$string = substr($read, $begin+9, $end-$begin-10);
echo "RING: ".$string."\n ";
if($CALQ>2){
mysqli_query($con,"INSERT INTO developments (mode, address, vale1, vale2, vale3, vale4, date, time,unixtime) VALUES ('RING', '00000000', '$string', '', '', '', '$date_today', '$time_today', '$timereal')");
  $serial->sendMessage("ATH0\n"); 
  $CALQ=0;
  }
 }
 //-----------------------Обработка звонков----------------------------------------------------------------------------
 
 //-----------------------Качество связи----------------------------------------------------------------------------
  if(strpos($read, "+CSQ")){

$begin = strpos($read, "+CSQ");

$string = substr($read, $begin+6, 2);
$string = floor(($string/31)*100);
if($string ==99){$string="0";}
echo "-> ".$date_today." ".$time_today." Definition quality of communication: ".$string."\n ";
mysqli_query($con,"UPDATE data SET state='$string' WHERE id='15'"); 

 }
 //-----------------------Качество связи----------------------------------------------------------------------------
 

}
	
//Проверка на доступность устройства если не доступно выключаем программу и ждем перезапуск
list ($nameport2, $numport2) = dev_detect($namedev); 
if($numport!=$numport2){break;}
//Проверка на доступность устройства если не доступно выключаем программу и ждем перезапуск	

usleep(100);

} //конец цикла
}

//сообщаем о недоступности устройства
else {echo "-> ".$date_today." ".$time_today." "." No connected devices.\n";}; 
}

Обращаю ваше внимание что со временем модуль может устареть, а последний модуль можно скачать с — Github SmartHomeAdatum

Похожие статьи

Оставить комментарий

  • Прошу подсказать, как исправить ошибку: при чтении СМС получаю -> Telephone: D4AE0100801 SMS: Invalid Format NUM: 1; Colsimcod: 328; CODE:

  • Всем привет

  • Доброе утро завсегдатае сайта, если вас не затруднит, научите уму разуму — 2 дня назад вместе с парнем собираемся заказать большой телевизор,
    оказалось , нам недостает 8500 рублей. Где порекомендуйте оформить кредитную карту ?

  • Киносериалы — это сегодня обязательная часть нашего досуга, один из способов полезно и не очень заполнить вечер, расслабиться от повседневных и рабочих трудностей, а также полностью погрузится в прекрасный мир выдуманных героев.

    На этом веб-сайте вы можете узнать о выпуске разных заманчивых свежих релизов, просмотреть занятные промо ролики или трейлеры, выяснить много информации об будущих премьерах и чего нужно ожидать от них, ближе познакомитесь с первостепенными персонажами и их особенностями.

    новые сериалы 2016