Разборка SMS и отправка на e-mail

Здесь выкладываем скрипты
Правила форума
Уважаемые Пользователи форума, обратите внимание!
Ни при каких обстоятельствах, Администрация форума, не несёт ответственности за какой-либо, прямой или косвенный, ущерб причиненный в результате использования материалов, взятых на этом Сайте или на любом другом сайте, на который имеется гиперссылка с данного Сайта. Возникновение неисправностей, потерю программ или данных в Ваших устройствах, даже если Администрация будет явно поставлена в известность о возможности такого ущерба.
Просим Вас быть предельно осторожными и внимательными, в использовании материалов раздела. Учитывать не только Ваши пожелания, но и границы возможностей вашего оборудования.
Ответить
pepelxl
Сообщения: 161
Зарегистрирован: 23 июл 2013, 18:47

Без Wait в буфер считывается от 0 до 3-4 PDU из 10 в Inbox в ответ на команду "AT+CMGL=4"
Тут думал как поступить дальше, ведь проблеме будут следовать многие железки.
Сначала пришла простое гениальное решение - указывать везде wait=yes, а ответ обрезать от "+<команда>" до "OK"
И в конце "NO clear SMS"

такое обрезание надо делать для любой посылаемой команды.
Потому что даже после at+cmgd в терминале приходит много мусора.
Потом мне прислали образец того, что приходит после AT+CMGL=4 и у меня произошёл взрыв мозга. Чем думали разрабы модема создавая этот код. :ps_ih:
Внутри ответа идёт выхлоп другой команды +MMSG
Это надо было так бредово сделать.
Придётся писать код так, что бы парсить ответ построчно, а это тот ещё гемор, так-как по спецификации каждое сообщение с новой строки и конец удачной пересылки всегда подтверждается "OK" с новой строки


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

EagleNN пришлите пожалуйста выхлоп от этих команд, пока остаётся не ясно, как удалять смс в модемах mikrotik


EagleNN
Сообщения: 13
Зарегистрирован: 09 авг 2017, 19:45

pepelxl писал(а): 05 июл 2020, 10:46 EagleNN пришлите пожалуйста выхлоп от этих команд, пока остаётся не ясно, как удалять смс в модемах mikrotik
Выхлоп ниже:

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

[admin@MikroTik] > :put [/interface lte at-chat lte1 input="AT+CMGF\?" as-value wait=yes]
output=+CMGF: 0
OK
+CSQ: 11,99
+CESQ: 99,99,31,36,255,255
*CESQ: 99,99,31,36,255,255,0
+CSQ: 12,99
+CESQ: 99,99,32,35,255,255
*CESQ: 99,99,32,35,255,255,0
+CSQ: 11,99
+CESQ: 99,99,31,34,255,255
*CESQ: 99,99,31,34,255,255,0

[admin@MikroTik] > :put [/interface lte at-chat lte1 input="at+cmgd\?" as-value wait=yes]
output=+CMS ERROR: operation not allowed
+CSQ: 11,99
+CESQ: 99,99,31,32,255,255
*CESQ: 99,99,31,32,255,255,0
+CSQ: 12,99
+CESQ: 99,99,32,31,255,255
*CESQ: 99,99,32,31,255,255,0

[admin@MikroTik] > :put [/interface lte at-chat lte1 input="at+cmgd=\?" as-value wait=yes]
output=+MMSG: 1, 1
+MMSG: 1, 1
+MMSG: 1, 1
+MMSG: 1, 1
+MMSG: 1, 1
+MMSG: 1, 1
+MMSG: 1, 1
+MMSG: 1, 1
+MMSG: 1, 1
+CMGD: (1,2,3,4,5,6,7,8,9,10),(0-4)
OK
+MMSG: 1, 1
+CSQ: 12,99
+CESQ: 99,99,32,39,255,255
*CESQ: 99,99,32,39,255,255,0
+CSQ: 12,99
+CESQ: 99,99,33,35,255,255
*CESQ: 99,99,33,35,255,255,0

[admin@MikroTik] > :put [/interface lte at-chat lte1 input="at+cmgd=0,1" as-value wait=yes]
output=+CMS ERROR: invalid memory index
+CSQ: 12,99
+CESQ: 99,99,32,31,255,255
*CESQ: 99,99,32,31,255,255,0

[admin@MikroTik] > :put [/interface lte at-chat lte1 input="at+cmgd=1" as-value wait=yes] 
output=+MMSG: 1, 0
OK
+MMSG: 1, 0



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

прекрасный кусок дебилизма разрабов mikrotik-a

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

[admin@MikroTik] > :put [/interface lte at-chat lte1 input="at+cmgd=1" as-value wait=yes] 
output=+MMSG: 1, 0
OK
+MMSG: 1, 0
Хоть стой, хоть падай.
На кой мне этот отчёт "+MMSG" по десять раз в секунду.
Как я должен поймать отсюда "OK" на свою команду, если "OK" может быть в любом месте, а поскольку at-chat подразумевает - "подсмотреть в терминал за общением чужих", то понять, что "OK" пришло на мою команду вообще не возможно.
Хоть сейчас создавать тикет и долбить поддержку.


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

Не удивительно, что все с родными модемами видят NO clear SMS
Для отладки закоментируйте в основном скрипте следующие строки

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

:local flagSend [$extractSmsModem action="clear"]
:if ($flagSend != true) do={:set $flagSend [$extractSmsModem action="clear"]}
:if ($flagSend != true) do={:log warning "NO clear SMS"; $exitFunctionPDU; :error}


EagleNN
Сообщения: 13
Зарегистрирован: 09 авг 2017, 19:45

pepelxl писал(а): 05 июл 2020, 22:31 Не удивительно, что все с родными модемами видят NO clear SMS
Для отладки закоментируйте в основном скрипте следующие строки

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

:local flagSend [$extractSmsModem action="clear"]
:if ($flagSend != true) do={:set $flagSend [$extractSmsModem action="clear"]}
:if ($flagSend != true) do={:log warning "NO clear SMS"; $exitFunctionPDU; :error}
Может кто еще сможет протестить?
У меня доступ к тушке только по выходным, и то не факт...

Если не пришлют ранее, попробую в районе 25-го июля прислать.


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

в общем времени так и не смог найти, на скорую руку переписал функцию извлечения

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

:global extractSmsModem do={
# Функция принимает один аргумент со значениями “read” или “clear”.
# При “read” возвращать должна один из трёх вариантов:
# 1 - Строку “NO SMS” в случаи отсутствия sms
# 2 - Строку с текстом ошибки при сбоях в выполнении функции
# 3 - Массив из строк PDU
# При “clear” должно вернутся булево значение
# true - при удачном стирании sms из памяти
# false - если стереть sms не удалось


:local nameFind [:toarray ""]
# ищем модемы lte
:foreach i in=[/interface lte find] do={
if ([/interface lte get $i value-name=disabled] = false) do={
:local tmp [/interface lte info $i once as-value]
:set $nameFind ($nameFind , {{"name"=[/interface lte get $i value-name=name];"type"="lte";"manufacturer"=($tmp->"manufacturer");"model"=($tmp->"model");"revision"=($tmp->"revision")}})
}}
# ищем модемы ppp-client
:foreach i in=[/interface ppp-client find] do={
if ([/interface ppp-client get $i value-name=disabled] = false) do={
:set $nameFind ($nameFind , {"name"=[/interface ppp-client get $i value-name=name];"type"="ppp-client"})
}}
:if ([:len $nameFind] = 0) do={:return "No found Modem"}

:local output [:toarray ""]
:local errorString
:local flagErrorExtract false
:local nosms false
:local clearSms true
:global storageMessageIndex
:if ($action = "read") do={:set $storageMessageIndex [:toarray ""]}

# опрашиваем все модемы по очереди
:foreach m in=$nameFind do={
:local tmp
:local tmp2
:local stStart
:local stEnd
:local mode
do {
# проверяем режим
:if (($m->"type") = "lte") do={:set $tmp ([/interface lte at-chat ($m->"name") input="AT+CMGF\?" wait=yes as-value]->"output")}
:if (($m->"type") = "ppp-client") do={:set $tmp ([/interface ppp-client at-chat ($m->"name") input="AT+CMGF\?" as-value]->"output")}
:set $stStart [:find $tmp "+CMGF"]
:if ([:typeof $stStart] != "num") do={:set $tmp2 "wrong answer to AT+CMGF\r\n"; throw;}
:set $stEnd [:find $tmp "\r\n" $stStart]
:if ([:typeof $stEnd] != "num") do={:set $tmp2 "wrong answer to AT+CMGF\r\n"; throw;}
:set $tmp2 [:pick $tmp ($stEnd + 2) ($stEnd + 4)]
:if ($tmp2 != "OK") do={:set $tmp2 "wrong answer to AT+CMGF\r\n"; throw;}
:set $tmp2 [:pick $tmp ($stStart + 7)]
:if ($tmp2 = "0") do={:set $mode false} else={:set $mode true}
:if ($mode) do={
:if (($m->"type") = "lte") do={/interface lte at-chat ($m->"name") input="AT+CMGF=0"}
:if (($m->"type") = "ppp-client") do={/interface ppp-client at-chat ($m->"name") input="AT+CMGF=0"}}
# читаем
:if ($action = "read") do={
# CMGL read sms
# 0 Received unread messages
# 1 Received read messages
# 2 Stored unsent messages
# 3 Stored sent messages
# 4 All messages
:if (($m->"type") = "lte") do={:set $tmp ([/interface lte at-chat ($m->"name") input="AT+CMGL=4" wait=yes as-value]->"output")}
:if (($m->"type") = "ppp-client") do={:set $tmp ([/interface ppp-client at-chat ($m->"name") input="AT+CMGL=4" as-value]->"output")}
:local flagend true
:local curStruct {"pdu"=[:toarray ""];"index"=[:toarray ""]}
:set $stStart [:find $tmp "+CMGL"]
:if ([:typeof $stStart] != "num") do={:if ($tmp~"OK" = true) do={:set $flagend false; set $nosms true} else={:set $tmp2 "wrong answer to AT+CMGL\r\n"; throw;}}
:set $stStart
:if ($flagend) do={[:parse ":global storageMessageIndex; :set \$storageMessageIndex (\$storageMessageIndex , {$($m->"name")=[:toarray \"\"]})"]}
:while ($flagend) do={
:set $stStart [:find $tmp "+CMGL" $stStart]
:if ([:typeof $stStart] != "num") do={:set $tmp2 "wrong answer to AT+CMGL\r\n"; throw;}
:set $stEnd [:find $tmp "\r\n" $stStart]
:if ([:typeof $stEnd] != "num") do={:set $tmp2 "wrong answer to AT+CMGL\r\n"; throw;}
:set $tmp2 [:pick $tmp $stStart $stEnd]
:local stat [:tonum [:pick $tmp2 ([:find $tmp2 ","] + 1)]]
:if (($stat = 0) or ($stat = 1)) do={
:local length [:tonum [ pick $tmp2 ([:find $tmp2 ",,"] + 2) [:len $tmp2]]]
:local index  [:tonum [ pick $tmp2 ([:find $tmp2 " "] + 1) [:find $tmp2 ","]]]
:set $stStart ($stEnd + 2)
:set $stEnd [:find $tmp "\r\n" $stStart]
:if ([:typeof $stEnd] != "num") do={:set $tmp2 "wrong answer to AT+CMGL\r\n"; throw;}
:set $tmp2 [:pick $tmp $stStart $stEnd]
:set $length (($length + 1 + [:tonum ("0x".[ pick $tmp2 0 2])]) * 2)
:if ($length != [:len $tmp2]) do={:set $tmp2 "wrong length in CMGL\r\n"; throw;}
:set ($curStruct->"pdu") (($curStruct->"pdu") , $tmp2)
:set ($curStruct->"index") (($curStruct->"index") , $index)
:if ([:pick $tmp ($stEnd + 2) ($stEnd + 4)] = "OK") do={:set $flagend false}
}
}
:set ($storageMessageIndex->($m->"name")) (($storageMessageIndex->($m->"name")) , ($curStruct->"index"))
:set $output ($output , ($curStruct->"pdu"))
}

# стираем
:if ($action = "clear") do={
:if (($m->"type") = "lte") do={:set $tmp ([/interface lte at-chat ($m->"name") input="AT+CMGD=1,1" wait=yes as-value]->"output")}
:if (($m->"type") = "ppp-client") do={:set $tmp ([/interface ppp-client at-chat ($m->"name") input="AT+CMGD=1,1" as-value]->"output")}
:if ($tmp~"OK" != true) do={
:foreach i in=($storageMessageIndex->($m->"name")) do={
:if (($m->"type") = "lte") do={:set $tmp ([/interface lte at-chat ($m->"name") input="AT+CMGD=$i" wait=yes as-value]->"output")}
:if (($m->"type") = "ppp-client") do={:set $tmp ([/interface ppp-client at-chat ($m->"name") input="AT+CMGD=$i" as-value]->"output")}
:if ($tmp~"OK" != true) do={:set $clearSms false}
}
}
}
} on-error={:set $flagErrorExtract true; :log info $m; :local na $m; :set $errorString ($errorString."Modem: ".[:tostr $m]."\r\nError: ".$tmp2."Returned:\r\n".$tmp."\r\n")}
:if ($mode) do={
:if (($m->"type") = "lte") do={/interface lte at-chat ($m->"name") input="AT+CMGF=1"}
:if (($m->"type") = "ppp-client") do={/interface ppp-client at-chat ($m->"name") input="AT+CMGF=1"}}
}
:if ($flagErrorExtract) do={
:set $storageMessageIndex
:if ([:len $output] > 0) do={:set $output ($errorString."Extracted from other modems:\r\n".[:tostr $output])
} else={:set $output $errorString}}
:if ($action = "clear") do={:set $storageMessageIndex
:if (!$clearSms) do={:set $output false} else={:set $output true}}
:if ($nosms and ([:len $output] = 0)) do={:set $output "NO SMS"; set $storageMessageIndex}
:return $output
}
Тестируйте, добавлено - автоматический поиск модемов, извлечение pdu из каши по присланным образцам, два режима стирания.
Но учтите, что хоть скрипт и обрабатывает все найденные модемы по порядку, но лучше пока не использовать если модемов больше чем один, там всё скорее всего развалится, вплоть до потери sms.
Обязательно отписывайтесь.
Последний раз редактировалось pepelxl 16 июл 2020, 10:51, всего редактировалось 1 раз.


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

скрипт простоял ночь, вышел косяк, -
регулярка вида ~"^OK\$" не отрабатывает на тексте вида:

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

OK
^RSSI: 25
^HCSQ: "LTE",59,52,156,28
я так понимаю, что в синтаксисе регулярок ros нет модификаторов.
немного поправил код выше, кто уже скачал - перекачайте.


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

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

:if (($m->"type") = "lte") do={/interface lte at-chat ($m->"name") input="AT+CMGF=1"}
:if (($m->"type") = "ppp-client") do={/interface ppp-client at-chat ($m->"name") input="AT+CMGF=1"}
А нельзя сразу типа так, для рациональности (вместо двух строк уже одна):

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

:if  (($m->"type") = "lte") or  ($m->"type") = "ppp-client")) do={/interface ($m->"type") at-chat ($m->"name") input="AT+CMGF=1"}
?


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

А нельзя сразу типа так, для рациональности (вместо двух строк уже одна):
оно изначально так и думал, но не работает, разбираться не стал, это черновик, что бы понять, заработает у людей или нет.
тем более там разница в wait=yes
Весь получившийся код я бы слил в унитаз, если мне бы принесли "как решение"


Ответить