Код: Выделить всё
:global extractSmsModem do={
# Функция не принимает аргументов.
# возвращает массив
# строку errorString текст ошибки, если таковая присутствует
# вложенный массив со значениями - pdu-name modem
# поддержка двух симочных моделей не реализована
# концепция скрипта подразумевает возможную потерю pdu при отсутствии поддержки команд модемом
# вложенная функция запросов
:local chat do={
:local t {"r"="";"f"=""}
:if ($1 = "lte") do={:set ($t->"r") ([/interface lte at-chat $2 input=$3 wait=yes as-value]->"output")}
:if ($1 = "ppp-client") do={:set ($t->"r") ([/interface ppp-client at-chat $2 input=$3 as-value]->"output")}
:if (($t->"r")~"(^|\n)OK(\$|\r)" != true) do={:set ($t->"f") true} else={:set ($t->"f") false}
:return $t
}
# массив с найдеными модемами
: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={
:local manufacturer
: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 [[:parse "({\"errorStr\"=[:tostr \"\"];\"arr\"=[:toarray \"\"]})"]]
# опрашиваем все модемы по очереди
:foreach m in=$nameFind do={
:local tmp
:local tmp2
:local stStart
:local stEnd
:local mode
do {
# проверяем режим
:set $tmp [$chat ($m->"type") ($m->"name") "AT+CMGF?"]
:if (($tmp->"f")) do={:set $tmp2 "wrong answer to AT+CMGF\r\n"; throw;}
:set $stStart [:find ($tmp->"r") "+CMGF"]
:if ([:typeof $stStart] != "num") do={:set $tmp2 "wrong answer to AT+CMGF\r\n"; throw;}
:set $stEnd [:find ($tmp->"r") "\r\n" $stStart]
:if ([:typeof $stEnd] != "num") do={:set $tmp2 "wrong answer to AT+CMGF\r\n"; throw;}
:set $tmp2 [:pick ($tmp->"r") ($stStart + 7)]
:if ($tmp2 = "0") do={:set $mode false} else={:set $mode true}
# устанавливаем режим PDU
:if ($mode) do={:set $tmp [$chat ($m->"type") ($m->"name") "AT+CMGF=0"]}
:if (($tmp->"f")) do={:set $tmp2 "wrong answer to AT+CMGF=0\r\n"; throw;}
# временное хранение
:local curStruct {"pdu"=[:toarray ""];"index"=[:toarray ""]}
# читаем
# CMGL read sms
# 0 Received unread messages
# 1 Received read messages
# 2 Stored unsent messages
# 3 Stored sent messages
# 4 All messages
:set $tmp [$chat ($m->"type") ($m->"name") "AT+CMGL=4"]
:if (!($tmp->"f")) do={
:local flagend true
# проверяем что sms есть
:set $stStart [:find ($tmp->"r") "+CMGL"]
:if ([:typeof $stStart] != "num") do={:set $flagend false;}
:set $stStart
# извлекаем строки из текста
:while ($flagend) do={
:set $stStart [:find ($tmp->"r") "+CMGL" $stStart]
:if ([:typeof $stStart] != "num") do={:set $tmp2 "wrong answer to AT+CMGL\r\n"; throw;}
:set $stEnd [:find ($tmp->"r") "\r\n" $stStart]
:if ([:typeof $stEnd] != "num") do={:set $tmp2 "wrong answer to AT+CMGL\r\n"; throw;}
:set $tmp2 [:pick ($tmp->"r") $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)
:local coretka true
:while ($coretka) do={
:if (([:pick ($tmp->"r") $stStart] = "\r") or ([:pick ($tmp->"r") $stStart] = "\n")) do={
:set $stStart ($stStart + 1)} else={:set $coretka false}}
:set $stEnd [:find ($tmp->"r") "\r\n" $stStart]
:if ([:typeof $stEnd] != "num") do={:set $tmp2 "wrong answer to AT+CMGL\r\n"; throw;}
:set $tmp2 [:pick ($tmp->"r") $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") , {{"pdu"=$tmp2;"name"=($m->"name");"mode"="sms"}})
:set ($curStruct->"index") (($curStruct->"index") , $index)
}
:set $tmp2 [:pick ($tmp->"r") $stEnd [:len ($tmp->"r")]]
:if (($tmp2~"\\+CMGL" != true) and ($tmp2~"(^|\n)OK(\$|\r)" = true)) do={:set $flagend false}
}
} else={:local simFill
do {
:set $tmp [$chat ($m->"type") ($m->"name") "AT+CMGD=?"]
:if (($tmp->"f")) do={throw;}
:set $stStart [:find ($tmp->"r") "+CMGD"]
:if ([:typeof $stStart] != "num") do={throw;}
:set $stEnd [:find ($tmp->"r") "\r\n" $stStart]
:if ([:typeof $stEnd] != "num") do={throw;}
:set $tmp2 [:pick ($tmp->"r") $stStart $stEnd]
:set $stStart [:find $tmp2 "("]
:if ([:typeof $stStart] != "num") do={throw;}
:set $stEnd [:find $tmp2 ")"]
:if ([:typeof $stEnd] != "num") do={throw;}
:set $simFill [:toarray [:pick $tmp2 ($stStart + 1) $stEnd]]
} on-error={:set $tmp2 "wrong answer to AT+CMGD=?\r\n"; throw;}
:foreach i in=$simFill do={do {
:set $tmp [$chat ($m->"type") ($m->"name") ("AT+CMGR=".[:tostr $i])]
:if (($tmp->"f")) do={throw;}
:set $stStart [:find ($tmp->"r") "+CMGR"]
:if ([:typeof $stStart] != "num") do={throw;}
:set $stEnd [:find ($tmp->"r") "\r\n" $stStart]
:if ([:typeof $stEnd] != "num") do={throw;}
:set $tmp2 [:pick ($tmp->"r") $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]]]
:set $stStart ($stEnd + 2)
:local coretka true
:while ($coretka) do={
:if (([:pick ($tmp->"r") $stStart] = "\r") or ([:pick ($tmp->"r") $stStart] = "\n")) do={
:set $stStart ($stStart + 1)} else={:set $coretka false}}
:set $stEnd [:find ($tmp->"r") "\r\n" $stStart]
:if ([:typeof $stEnd] != "num") do={throw;}
:set $tmp2 [:pick ($tmp->"r") $stStart $stEnd]
:set $length (($length + 1 + [:tonum ("0x".[ pick $tmp2 0 2])]) * 2)
:if ($length != [:len $tmp2]) do={throw;}
:set ($curStruct->"pdu") (($curStruct->"pdu") , {{"pdu"=$tmp2;"name"=($m->"name");"mode"="sms"}})
:set ($curStruct->"index") (($curStruct->"index") , $i)
}} on-error={:set $tmp2 ("wrong answer to AT+CMGR=$i; simfill=".[:tostr $simFill]."\r\n"); throw;}}
}
# стираем
:if ([:len ($curStruct->"index")] > 0) do={
:set $tmp [$chat ($m->"type") ($m->"name") "AT+CMGD=1,1"]
:if (($tmp->"f")) do={
:foreach i in=($curStruct->"index") do={
:local iterError 20
:while ($iterError > 0) do={
:set $tmp [$chat ($m->"type") ($m->"name") ("AT+CMGD=".[:tostr $i])]
:set $iterError ($iterError - 1)
:if (!($tmp->"f")) do={:set $iterError 0}}
:if (($tmp->"f")) do={:set $tmp2 "wrong answer in CMGD\r\n"; throw;}
}}}
# возвращаем режим обратно
:if ($mode) do={:set $tmp [$chat ($m->"type") ($m->"name") "AT+CMGF=1"]}
:if (($tmp->"f")) do={:set $tmp2 "wrong answer to AT+CMGF=1\r\n"; throw;}
# добавляем извлечённые pdu в возврат функции
:if ([:len ($curStruct->"index")] > 0) do={
:set ($output->"arr") (($output->"arr") , ($curStruct->"pdu"))}
} on-error={
# сохраняем значение в переменную, т.к. tmp является указателем
:local es ($tmp->"r")
# опрашиваем идентификаторы модема
:if (($m->"type") = "ppp-client") do={
:local man [$chat ($m->"type") ($m->"name") "AT+GMI"]
:if (($man->"f")) do={:set $man [$chat ($m->"type") ($m->"name") "AT+CGMI"]}
:if (($man->"f")) do={:set $man "no information"} else={:set $man ($man->"r")}
:local mod [$chat ($m->"type") ($m->"name") "AT+GMM"]
:if (($mod->"f")) do={:set $mod [$chat ($m->"type") ($m->"name") "AT+CGMM"]}
:if (($mod->"f")) do={:set $mod "no information"} else={:set $mod ($mod->"r")}
:local rev [$chat ($m->"type") ($m->"name") "AT+GMR"]
:if (($rev->"f")) do={:set $rev [$chat ($m->"type") ($m->"name") "AT+CGMR"]}
:if (($rev->"f")) do={:set $rev "no information"} else={:set $rev ($rev->"r")}
:set $m ($m , {"manufacturer"=$man;"model"=$mod;"revision"=$rev})
}
:set ($output->"errorStr") (($output->"errorStr")."Modem: ".[:tostr $m]."\r\nError: ".$tmp2."Returned:\r\n$es\r\n")}
}
:return $output
}