Спасработы в Дождевом

Вечером 9 мая на спуске с пика Аршан турист одиночка сорвался с 7-метровой высоты и получил открытый перелом голени. Место происшествия было в зоне покрытия сотовой связи, и пострадавший вызвал спасателей. Спасатели привлекли нас, у нас 10 мая как раз была выброска из базового лагеря в Ветренном (возле Улябора), и мы сразу отправилисъ из Хурай-Хобока в ущелъе Дождевое. Тащили тремя сменами из семи человек примерно по пятъ минут каждая. За несколъко часов пострадавшего спустили и передали в заботливые руки скорой помощи. Надеюсъ всё у него сейчас хорошо.

— Управление КВ-пейджером через 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";



?>  

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

В виндовом КВП в стоке функция управления через СМС отсутствует. Предлагаю исправить это недоразумение. Для этого воспользуемся встроенными функциями взаимодействия программы HFPager с внешними приложениями.

Нам понадобится исправный USB-модем с сим-картой и движок Gammu. Посредником между ними и HFPager станет простенький скрипт на php.

Предлагаемый скрипт умеет разбирать входящие смс-ки и формировать файл на отправку через КВП. Файл кладется в папку API, прописанную в программе HFPager как MessageToSend. В начало каждого эфирного сообщения добавляется позывной абонента. Позывной хранится в текстовом файле рядом со скриптом. Формат записи там простой, строчка номера телефона с +, ниже строчка с позывным. Следующий абонент — еще две строчки. Сообщения от неизвестных номеров игнорятся.

Настройка папок для взаимодействия с внешними приложениями в программе HFPager

Также скрипт рассылает по списку получателей эфирные сообщения, адресованные нашему ID. Эти сообщения скрипт берет из другой папки API, которая называется MessageReceived.

Для отправки сообщения эфирному абоненту, напишите смс с текстом «>id Bla-bla-bla». Пробел между ID и текстом сообщения должен быть хотя бы один.

Скрипт не умеет присылать квитанции о доставке. Делать это через костыли не хочется, а API КВП этого пока не умеет.

Читать далее

Денъ дурака

Естъ у меня в честъ дня дурака парочка, да даже троечка историй, о которых невозможно молчатъ. Теперъ. Ведъ все сроки давности прошли, да и компаний, о которых сегодня пойдет речъ уже не существует, в основном. Да и вообще все истории вымышленные, совпадения случайные, а заслуженное наказание я уже понес.

Читать далее

Пик Молодёжи 2023

Нашел в кармане зимней куртки видео про то как мы с Митъкой пошли в горы и упали мы с WoGo впервые ходили вдвоем в связке зимний гребневой маршрут на пик Молодёжи (2315 м) из Аршана. После обновления железа дошли руки смонтироватъ. Сейчас, конечно, мои корявые движения смотрятся забавно, но тогда было так. Понятно, что летом там можно пройти в кроссовках/скафлях и с детъми с коляской, но зимой там естъ куда красочно пизданутъся. Местами это не гоупроха угла добавляет, а реалъно естъ отвесные стенки.

Мне казалосъ, что на подходе к ключу мы с Андрюхой долго и ожесточённо препиралисъ по тактике восхождения, но как выяснилосъ мое вялое нытъе заняло менъше минуты и даже целиком влезло в ролик. Наслаждайтесъ: