RouterOS и кодировка SMS UCS-2

Обсуждение ПО и его настройки
Sertik
Сообщения: 1598
Зарегистрирован: 15 сен 2017, 09:03

По последнему сообщению ...

Да ..... Вот уж человек действительно не пожалел времени - такой скриптец наваял ... Даже у такого извращенца как я терпения бы не хватило .... Хотя, конечно, по конструкциям многим там перебор ..., можно было бы оптимизировать код на 1/4 как минимум ...

А всё от того, что Микротик не хочет (или руки не доходят, или не нужно им это) нормально поддержать русскую кодировку ...

Но доброму человеку (имея ввиду автора скрипта), конечно, огромное спасибо в любом случае ! Во-первых за то, что не жлобился, а выложил сюда скрипт. Во-вторых за ряд приемов скриптописания и конструкций ... Всё пригождается, как показывает опыт, т.к. скриптовый язык очень мощная на самом деле вещь, но синтаксис его применительно к Рос весьма не дружелюбен ...


фрагменты скриптов, готовые работы, статьи, полезные приемы, ссылки
viewtopic.php?f=14&t=13947
Аватара пользователя
podarok66
Модератор
Сообщения: 4355
Зарегистрирован: 11 фев 2012, 18:49
Откуда: МО

Блин, я ради этого скрипта скопировал тему в Готовые скрипты. Пусть будет, на случай поиска...


Мануалы изучил и нигде не ошибся? Фаервол отключил? Очереди погасил? Витая пара проверена? ... Тогда Netinstal'ом железку прошей и настрой ее заново. Что, все равно не фурычит? Тогда к нам. Если не подскажем, хоть посочувствуем...
nikolay.hmarin
Сообщения: 15
Зарегистрирован: 18 мар 2019, 23:43

отличный скрип, правда работает через раз... и последний символ не дешифрует.


Erik_U
Сообщения: 1755
Зарегистрирован: 09 июл 2014, 12:33

Кирилица в СМС. Ну и запросы.

Попробуйте кирилицу в строке коментарий!! :)


pepelxl
Сообщения: 161
Зарегистрирован: 23 июл 2013, 18:47

Ооо, крутой скрипт для понимания работы mikrotika и pdu. Буду сидеть изучать его, может накаледую версию для своих нужд(преправка всех входящих на email).
Сразу вопрос - у меня та-же беда: Huawei не отдаёт длину SCA. Есть понимание почему это происходит? Во всех даташитах на модем в примерах указана отдача sc_len. Есть у меня предположение, что он не отдаёт длину, если номер имеет международный формат или поиграться с AT+CSCA.
В любом случае, что бы скрипт был более универсальным можно ввести простую проверку: sca может быть до двенадцати байт, а в следующим за ним байтом(первый байт SCA(type_addr)) седьмой бит зарезервирован единицей. То-есть, если первый бит сообщения 0, то первый байт SC_len. А если 1, то sc_len отброшен и принимать длину международного стандарта.


pepelxl
Сообщения: 161
Зарегистрирован: 23 июл 2013, 18:47

В общем и смех и грех. По поводу потери байт вопрос оказался очень прозаичным, косяк OS. Потеря наблюдалась, только, в at-chat. В обычном режиме терминала, модем отдаёт без потери байтов. Написал на оф-форум, в саппорт писать не стал. Судя по обилию тем на форуме, в OS присутствуют куча болячек более серьёзного плана, да и отвечает саппорт через 10 месяцев. НО, произошло странное стечение обстоятельств: в актуальной версии(6.45.1) баг исправили.


pepelxl
Сообщения: 161
Зарегистрирован: 23 июл 2013, 18:47

Накалякал себе, может кому пригодится:

Код: Выделить всё

#Скрипт пересылки SMS на email. 
# Автор: pepelxl, 07.2019.
# Немного памятки:
# из модема sms можно извлечь в двух режимах – PDU и text
# Текст передаётся в трёх кодировках :
# 7bit – 160 символов
# 8bit – 140 символов
# UCS2 – 70 символов
# в режиме text,  модем сам распарсит sms из 7bit и 8bit, но не сможет распасить ucs2.
# Мой скрип работает с режимом  text, из минусов: 
# - нет возможности сортировать и склеивать сообщения.
# - 7bit базируется на кодировке alphabet, не известно как передаст модем символы отличные от ANSII
# - 8bit может содержать кодировки на национальных языках, опять же проблема поведения и передачи символов.
# Обработчик ошибок так и не осилил, возможно сделаю позже.
# UCS2 по байтно совместим с UTF-16(базис план, 2byte), можно слать его сразу на почту,
# но тогда придётся разбивать шапку и тело, а поскольку национальное sms
# как правило состоит из нескольких  штук, - будет не удобно.
# Кроме того, не все почтовые клиенты правильно обрабатывают ucs2.
# скрипт конвертирует UCS2 в UTF-8 и отсылает собранные sms в один email.
# текст будет в том же виде, как и пришел.
# cкрипт проверялся на оборудовании: Huawei me909, basebox2, routerOS  6.45.1(на более
# ранних версиях присутствует баг извлечения sms из модема).




#:log info "Running...";
# Переводим модем в режим чтения TEXT
/interface lte at-chat lte1 input="AT+CMGF=1";
# Читаем все сообщения
:local content [/interface lte at-chat lte1 input="AT+CMGL=\"all\"" as-value];
# Извлекаем элемент массива output в переменную
:set content ($content->"output");
# Проверяем, что сообщение есть
:if ([:len $content]>2) do={

:local lineEnd;
:local lineStart;
:local line "";
:local smsTo "";
:local smsDate "";
:local smsBody "";
:local ucs2text true;
:local outUtf "";
:local emailBody "";
:local flagEnd true;

:while ($flagEnd) do={
#ищем начало SMS
:set lineStart [ find $content "+CMGL:" $lineStart ] ;
# Проверяем что поиск завершился успешно
:if ([ typeof $lineStart ]="num") do={
	# Ищем конец SMS
	:set $lineEnd [ find $content "+CMGL:" $lineStart ];
	:if ([ typeof $lineEnd ] = "nil") do={
	:set $lineEnd [ find $content "OK" $lineStart ];
	};
	# вынимаем сообщение
	:set line [ pick $content $lineStart ($lineEnd - 1) ];
	# вынимаем телефон отправителя
	:set $smsTo [ pick $line ([:find $line "\",\""] + 3) ([:find $line ",,"] - 1)];
	# вынимаем дату
	:set $smsDate [ pick $line ([:find $line ",,"] + 3) ([:find $line "\n"] - 2)];
	# вынимаем тело
	:set smsBody [:pick $line ([:find $line "\n"]+1) ([:len $line]-1)];
	
	
	# проверяем в каком формате находится тело
	:local iter [:len $smsBody];
	:local hexCap "0123456789ABCDEF";
	:while ($iter > 0) do={
		:if ([:typeof [:find $hexCap [:pick $smsBody ($iter - 1) $iter]]] != "num") do={
			:set $ucs2text false;
			:set $iter 0;};
		:set $iter ($iter - 1);
	};
	
	# Следующий блок конвертирует usc2 в utf-8
	:if ($ucs2text) do={
		:set $outUtf;
		:local symbolsHex {"\00";"\01";"\02";"\03";"\04";"\05";"\06";"\07";"\08";"\09";"\0A";"\0B";"\0C";"\0D";"\0E";"\0F";"\10";"\11";"\12";"\13";"\14";"\15";"\16";"\17";"\18";"\19";"\1A";"\1B";"\1C";"\1D";"\1E";"\1F";"\20";"\21";"\22";"\23";"\24";"\25";"\26";"\27";"\28";"\29";"\2A";"\2B";"\2C";"\2D";"\2E";"\2F";"\30";"\31";"\32";"\33";"\34";"\35";"\36";"\37";"\38";"\39";"\3A";"\3B";"\3C";"\3D";"\3E";"\3F";"\40";"\41";"\42";"\43";"\44";"\45";"\46";"\47";"\48";"\49";"\4A";"\4B";"\4C";"\4D";"\4E";"\4F";"\50";"\51";"\52";"\53";"\54";"\55";"\56";"\57";"\58";"\59";"\5A";"\5B";"\5C";"\5D";"\5E";"\5F";"\60";"\61";"\62";"\63";"\64";"\65";"\66";"\67";"\68";"\69";"\6A";"\6B";"\6C";"\6D";"\6E";"\6F";"\70";"\71";"\72";"\73";"\74";"\75";"\76";"\77";"\78";"\79";"\7A";"\7B";"\7C";"\7D";"\7E";"\7F";"\80";"\81";"\82";"\83";"\84";"\85";"\86";"\87";"\88";"\89";"\8A";"\8B";"\8C";"\8D";"\8E";"\8F";"\90";"\91";"\92";"\93";"\94";"\95";"\96";"\97";"\98";"\99";"\9A";"\9B";"\9C";"\9D";"\9E";"\9F";"\A0";"\A1";"\A2";"\A3";"\A4";"\A5";"\A6";"\A7";"\A8";"\A9";"\AA";"\AB";"\AC";"\AD";"\AE";"\AF";"\B0";"\B1";"\B2";"\B3";"\B4";"\B5";"\B6";"\B7";"\B8";"\B9";"\BA";"\BB";"\BC";"\BD";"\BE";"\BF";"\C0";"\C1";"\C2";"\C3";"\C4";"\C5";"\C6";"\C7";"\C8";"\C9";"\CA";"\CB";"\CC";"\CD";"\CE";"\CF";"\D0";"\D1";"\D2";"\D3";"\D4";"\D5";"\D6";"\D7";"\D8";"\D9";"\DA";"\DB";"\DC";"\DD";"\DE";"\DF";"\E0";"\E1";"\E2";"\E3";"\E4";"\E5";"\E6";"\E7";"\E8";"\E9";"\EA";"\EB";"\EC";"\ED";"\EE";"\EF";"\F0";"\F1";"\F2";"\F3";"\F4";"\F5";"\F6";"\F7";"\F8";"\F9";"\FA";"\FB";"\FC";"\FD";"\FE";"\FF"};
		:for curposition from=0 to=[:len $smsBody] step=4 do={
		:local i [:tonum ("0x".[:pick $smsBody $curposition ($curposition +4)])];
		:if ($i < 0x80) do={
		:set $outUtf ($outUtf.($symbolsHex->$i));
		};
		:if (($i >= 0x80) and ($i < 0x800)) do={
		:local byteA (($i >> 6) | 192);
		:local byteB (($i & 63) | 128);
		:set $outUtf ($outUtf.($symbolsHex->$byteA).($symbolsHex->$byteB));
		};
		:if ($i >= 0x800) do={
		:local byteA (($i >> 12) | 224);
		:local byteB ((($i >> 6) & 63) | 128);
		:local byteC (($i & 63) | 128);
		:set $outUtf ($outUtf.($symbolsHex->$byteA).($symbolsHex->$byteB).($symbolsHex->$byteC));
		};
		};
	} else={:set $outUtf $smsBody;};
	
	########## Здесь собираем тело письма в нужной последовательности ######
	:set $emailBody ($emailBody."from: ".$smsTo."\r\nDate: ".$smsDate."\r\nMessage: ".$outUtf."\r\n\r\n");
	
	#######################################################################
	
	# Возвращаем флаг формата sms для следующего сообщения.
	:set $ucs2text true;
	# Останавливаем цикл, если прочитано последнее сообщение
	} else={ :set $flagEnd false;};
	};
	#Отправляем письмо
	:if ( [:len $emailBody] > 0 ) do={/tool e-mail send to=example@mail.ru subject="Mikrotik\r\nMIME-Version: 1.0\r\nContent-Type: text/plain; charset=utf-8" body=$emailBody;
		:delay 10s;
		#Удаляем все прочитанные sms
		:if ( [ /tool e-mail get last-status ] = "succeeded") do={/interface lte at-chat lte1 input="at+cmgd=1,2";};
	};
};
#:log info "END";
Последний раз редактировалось pepelxl 26 июл 2019, 12:36, всего редактировалось 3 раза.


Sertik
Сообщения: 1598
Зарегистрирован: 15 сен 2017, 09:03

Спасибо ! Очень даже пригодится, проверим.


фрагменты скриптов, готовые работы, статьи, полезные приемы, ссылки
viewtopic.php?f=14&t=13947
pepelxl
Сообщения: 161
Зарегистрирован: 23 июл 2013, 18:47

Если с чем столкнётесь , то сообщайте. Есть желание на свежие дрожжи написать обработчик исключений, но имея в наличии один модем, это крайне сложно.


pepelxl
Сообщения: 161
Зарегистрирован: 23 июл 2013, 18:47

добавил в скрипт проверку отосланного e-mail, что бы не терялись sms при недоступности сети.


Ответить