— Управление КВ-пейджером через E-mail

В виндовой версии программы HFPager есть режим управления через электронную почту. Он позволяет отправлять эфирные сообщения на электронную почту и наоборот. Режим этот называется «Персональный e-mail шлюз» и полноценно работать умеет только с одним адресатом. К тому же требует соблюдения особых условий при формировании письма. Цитата из документации: «Кроме того, поле «Subject:» принятого письма должно включать в себя текст вида hfpager idFrom > idTo».

Чтобы сделать число почтовых юзеров больше чем один, а также для упрощения поля Subject, разработан промежуточный коннектор. Он с одной стороны получает письма от HFPager и пересылает их по списку юзеров. С другой стороны, письма юзеров пересылает на адрес пейджера. При этом в поле Subject можно просто написать id адресата. Или оставить его пустым, но в самом сообщении указать id в самом начале после символа правой скобки: вот такого >.

В каждое письмо, адресованное в сторону HFPager, скрипт добавляет позывной юзера, который прописан в файле maillist.txt. Письма с незнакомых адресов игнорятся.

Схема взаимодействия юзеров с пейджером

Коннектор выполнен в виде скрипта на языке php. Запускается Планировщиком заданий прямо на компьютере с HFPager. Но можно вынести вообще на любой комп, имеющий доступ к используемым почтовым серверам.

Проверена работа с почтовыми клиентами K9 и Delta-Chat. С другими клиентами, возможно, придется допиливать обработку различных кодировок. Удачи вам в этом нелегком деле, не забудьте поделиться своими успехами.

Дополнительные материалы:

https://github.com/RA0UEK/HFP-Email-Connector — Материалы проекта на GitHub;

https://teletype.in/@shpagin/phpmailer — Вменяемая инструкция к PHPMailer. Отправка писем и файлов на почту.

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

Отложенные сообщения хранятся в папке C:\USERNAME\<id адресата сообщений>

Сообщения представляют собой простые текстовые файлы с произвольным названием. Например. 1.txt, 2.txt, 3.txt и так далее. В файлах пишите все в одну строку без переносов каретки, скрипт не умеет читать более одной строки.

Скрипт написан на языке PHP и запускается Планировщиком заданий через пакетный файл .bat. В планировщике нужно указать период выполнения скрипта, например, «раз в минуту».

В программе КВП настроим взаимодействие с внешними программами.

Разложим проект где удобно на диске.

Положим в папку с ID эфирного абонента (которому предназначаются сообщения) текстовые файлы.

Не забудьте в скрипте PHP поправить ID вашего КВП. В моем случае это 2104, замените его на свой. В тексте программы есть комментарии в местах, где нужно его поменять.

Далее в Планировщике заданий создаем простое задание с запуском файла .bat раз в минуту.

Проверяем. Из эфира на номер вашего КВП направляем сообщение с текстом qru? Если все принято и настроено правильно, в ответ прилетит сначала сообщение о числе отложенных сообщений, а затем сами сообщения.

Код прилагается:

<?php  

header('Content-Type: text/html; charset=utf-8');

$msgreceived = 'C:\LEV\RECEIVED'; // HFPager API config
$msgtosend = 'C:\LEV\SEND'; // HFPager API config
$dirqru = 'C:\LEV\QRU'; // Тут хранятся папки с отложенными сообщениями




echo "\n\n";


$msgarray = array_diff(scandir($msgreceived), ['.', '..']);
$count = array_key_last($msgarray);


foreach ($msgarray as $row) {
    $row = $msgarray[$count];
	$count = $count - 1;
		
If (strlen($row)>10) { 
	
	$stop_f = strpos($row,'.');
	$start_f = 21;

	
	// Error message files > dev/null

	If (strpos($msgreceived.'/'.$row,'REC-ER')) {
	echo "Error  --  \033[31m[Ignore]\033[0m \n";
	unlink($msgreceived.'/'.$row);
	}		


	
	// Beacons files > dev/null

	If (strpos($msgreceived.'/'.$row,'BEA')) {
	echo "Beacon  --  \033[31m[Ignore]\033[0m \n";
	unlink($msgreceived.'/'.$row);
	}		



	// GPS files > dev/null

	If (strpos($msgreceived.'/'.$row,'GPS')) {
	echo "GPS  --  \033[31m[Ignore]\033[0m \n";
	unlink($msgreceived.'/'.$row);
	}		



	// Bad headers files > dev/null

	If (strpos($msgreceived.'/'.$row,'REC-BD')) {
	echo "Bad title   --  \033[31m[Ignore]\033[0m \n";
	unlink($msgreceived.'/'.$row);
	}



	// SNT-R-containing files

	If (strpos($msgreceived.'/'.$row,'SNT-R')) {
	echo "Sent message   --  \033[31m[Ignore]\033[0m \n";
	unlink($msgreceived.'/'.$row);
	}





	// REC-containing files

	If (strpos($msgreceived.'/'.$row,'REC-OK')) {
	echo "\033[32mMessage received correct\033[0m   --   ";
	
	$fd = fopen($msgreceived.'/'.$row, 'r') or die("ERR_OPEN_FILE");
	
	$header='';
	$message='';

	
	$header = trim(fgets($fd,4096));
	$header = str_replace("\r\n","",$header);

	while(!feof($fd))
	{
    $sw = fgets($fd,4096);
	$sw = str_replace("\n",'',$sw);
	$sw = str_replace("\r",'',$sw);

		
	If (($message!='') AND ($sw!='')) {
	$message = $message.' '.$sw;	
	}

	If (($message=='') AND ($sw!='')) {
	$message = $sw;	
	}	
		
	}
	fclose($fd);
	
	$message = str_replace("\r\n","",$message);
	
	
	// Message not for our ID
	
	If (strpos($header,'> 2104') === false) { // Укажите тут ID своего КВП
	echo "Not for us   --  \033[31m[Ignore]\033[0m\n";
	unlink($msgreceived.'/'.$row);
	}
	
	
	
	// If message for our ID
	
	If (strpos($header,'> 2104')) { // Укажите здесь ID своего КВП
	
	$serial = 0;
	
	$er = substr($header,strpos($header,'Error Rate')+11);
	$er = str_replace(' :','',$er);
	$qru_id = trim(substr($header,0,strpos($header,' ')));	
	$header = substr($header,0,strpos($header,' '));
	$text_for_terminal = iconv("Windows-1251", "UTF-8", $message);
	$text_for_terminal = $header . ' ('. $er . ') > ' . $text_for_terminal;

	echo "\033[32m" . $text_for_terminal . "\033[0m \n";
	unlink($msgreceived.'/'.$row);

	
	
	
	
	// START If message conteins 'QRU?'
	
	
	If (stripos($message,'QRU?') !== false) {
	
	echo "\033[32mRequest <QRU?>\033[0m   --   \033[32m[SEND ANSVER]\033[0m";
	
	$dirqru = $dirqru . '\\\\' . $qru_id; 
	
	If (file_exists($dirqru)) { // Если директория существует
	
	$qru_count = 0;
	$qru_array = array_diff(scandir($dirqru), array('.', '..'));
	$qru_count = array_key_last($qru_array);	
	
	
	If ($qru_count > 0) { // Если в директории что-то есть
	
	
	
	$qru_text = iconv("UTF-8","Windows-1251",'Msg: ' . $qru_count - 1 . '.');
	$uta = date('YmdHis');
	$filehfp = $msgtosend.'/1.dat';
	$filehfpnew = $msgtosend.'/1.msg';
	$hfptext = 'to=' . $qru_id . ',speed=0,askreq=1,resend=3' . "\n" . $qru_text . "\n";
	file_put_contents($filehfp, $hfptext);
	rename($filehfp, $filehfpnew);
		
	
	sleep(10);
		
	
	$smsarray = array_diff(scandir($dirqru), array('.', '..'));
	$smscount = array_key_last($smsarray);
		
	foreach ($smsarray as $srow) {
    $srow = $smsarray[$smscount];
	$smscount = $smscount - 1;
	
	$smsfile = fopen($dirqru.'/'.$srow, 'r') or die("ERR_OPEN_FILE");
	$smstext = trim(fgets($smsfile,4096));
	$smstext = iconv("UTF-8","Windows-1251",$smstext);
	fclose($smsfile);
	
	
	
	$uta = date('YmdHis');
	$filehfp = $msgtosend.'/'.$uta.$smscount.'.dat';
	$filehfpnew = $msgtosend.'/'.$uta.$smscount.'.msg';
	$hfptext = 'to=' . $qru_id . ',speed=0,askreq=1,resend=3' . "\n" . $smstext . "\n";
	file_put_contents($filehfp, $hfptext);
	rename($filehfp, $filehfpnew);
	
	
	unlink($dirqru.'/'.$srow);
	}
	

	
	} else { // Если в директории ничего нет
	$qru_text = iconv("UTF-8","Windows-1251",'No msg!');
	$uta = date('YmdHis');
	$filehfp = $msgtosend.'/'.$uta.'.dat';
	$filehfpnew = $msgtosend.'/'.$uta.'.msg';
	$hfptext = 'to=' . $qru_id . ',speed=0,askreq=1,resend=3' . "\n" . $qru_text . "\n";
	file_put_contents($filehfp, $hfptext);
	rename($filehfp, $filehfpnew);
			}
	
			
	} else { // Если директория не существует
	$qru_text = iconv("UTF-8","Windows-1251",'No msg!');
	$uta = date('YmdHis');
	$filehfp = $msgtosend.'/'.$uta.'.dat';
	$filehfpnew = $msgtosend.'/'.$uta.'.msg';
	$hfptext = 'to=' . $qru_id . ',speed=0,askreq=1,resend=3' . "\n" . $qru_text . "\n";
	file_put_contents($filehfp, $hfptext);
	rename($filehfp, $filehfpnew);	
			}
	
	
	
	}

	// STOP If message conteins 'QRU?'
	
	
	

	
} 	// STOP If message for our ID
	
} 	// STOP REC-containing files

} 

}



echo "\n\n";



?>