|
| 1 | +-- Copyright 2020-2022 Rafa³ Wabik (IceG) - From eko.one.pl forum |
| 2 | +-- Licensed to the GNU General Public License v3.0. |
| 3 | + |
| 4 | + |
| 5 | + local util = require "luci.util" |
| 6 | + local fs = require "nixio.fs" |
| 7 | + local sys = require "luci.sys" |
| 8 | + local http = require "luci.http" |
| 9 | + local dispatcher = require "luci.dispatcher" |
| 10 | + local http = require "luci.http" |
| 11 | + local sys = require "luci.sys" |
| 12 | + local uci = require "luci.model.uci".cursor() |
| 13 | + |
| 14 | +-- module("luci.controller.modem.sms", package.seeall) |
| 15 | +module("luci.controller.sms", package.seeall) |
| 16 | +-- I18N = require "luci.i18n" |
| 17 | +-- translate = I18N.translate |
| 18 | +function index() |
| 19 | + -- entry({"admin", "modem"}, firstchild(), "蜂窝", 30).dependent=false |
| 20 | + -- entry({"admin", "modem", "sms"}, alias("admin", "modem", "sms", "readsms"), translate("SMS Messages"), 10) |
| 21 | + -- entry({"admin", "modem", "sms", "readsms"},template("modem/readsms"),translate("Received Messages"), 10) |
| 22 | + -- entry({"admin", "modem", "sms", "sendsms"},template("modem/sendsms"),translate("Send Messages"), 20) |
| 23 | + entry({"admin", "modem", "readsms"},template("modem/readsms"),translate("Received Messages"), 20) |
| 24 | + entry({"admin", "modem", "sendsms"},template("modem/sendsms"),translate("Send Messages"), 30) |
| 25 | + -- entry({"admin", "modem", "sms", "ussd"},template("modem/ussd"),translate("USSD Codes"), 30) |
| 26 | + -- entry({"admin", "modem", "sms", "atcommands"},template("modem/atcommands"),translate("AT Commands"), 40) |
| 27 | + if nixio.fs.access("/etc/config/smsconfig") then |
| 28 | + entry({"admin", "modem", "smsconfig"}, cbi("smsconfig"),translate("Configuration"), 50) |
| 29 | + end |
| 30 | + -- entry({"admin", "modem", "smsconfig"},cbi("smsconfig"),translate("Configuration"), 50) |
| 31 | + entry({"admin", "modem", "delete_one"}, call("delete_sms", smsindex), nil).leaf = true |
| 32 | + entry({"admin", "modem", "delete_all"}, call("delete_all_sms"), nil).leaf = true |
| 33 | + -- entry({"admin", "modem", "sms", "run_ussd"}, call("ussd"), nil).leaf = true |
| 34 | + -- entry({"admin", "modem", "sms", "run_at"}, call("at"), nil).leaf = true |
| 35 | + entry({"admin", "modem", "run_sms"}, call("sms"), nil).leaf = true |
| 36 | + entry({"admin", "modem", "readsim"}, call("slots"), nil).leaf = true |
| 37 | + -- entry({"admin", "modem", "countsms"}, call("count_sms"), nil).leaf = true |
| 38 | + -- entry({"admin", "modem", "sms", "user_ussd"}, call("userussd"), nil).leaf = true |
| 39 | + -- entry({"admin", "modem", "sms", "user_atc"}, call("useratc"), nil).leaf = true |
| 40 | + -- entry({"admin", "modem", "sms", "user_phonebook"}, call("userphb"), nil).leaf = true |
| 41 | +end |
| 42 | + |
| 43 | + |
| 44 | +function delete_sms(smsindex) |
| 45 | +local devv = tostring(uci:get("sms_tool", "general", "readport")) |
| 46 | +local s = smsindex |
| 47 | +for d in s:gmatch("%d+") do |
| 48 | + os.execute("sms_tool -d " .. devv .. " delete " .. d .. "") |
| 49 | +end |
| 50 | +end |
| 51 | + |
| 52 | +function delete_all_sms() |
| 53 | + local devv = tostring(uci:get("sms_tool", "general", "readport")) |
| 54 | + os.execute("sms_tool -d " .. devv .. " delete all") |
| 55 | +end |
| 56 | + |
| 57 | + |
| 58 | +function sms() |
| 59 | + local devv = tostring(uci:get("sms_tool", "general", "sendport")) |
| 60 | + local sms_code = http.formvalue("scode") |
| 61 | + |
| 62 | + nr = (string.sub(sms_code, 1, 20)) |
| 63 | + msgall = string.sub(sms_code, 21) |
| 64 | + msg = string.gsub(msgall, "\n", " ") |
| 65 | + nr = string.gsub(nr, "%s", "") |
| 66 | + if sms_code then |
| 67 | + -- local odpall = io.popen("sms_tool -d " .. devv .. " send " .. nr .." '".. msg .."'") |
| 68 | + local odpall = encodeToPDU(nr, msg) |
| 69 | + local odp = odpall:read("*a") |
| 70 | + odpall:close() |
| 71 | + http.write(tostring(odp)) |
| 72 | + else |
| 73 | + http.write_json(http.formvalue()) |
| 74 | + end |
| 75 | + |
| 76 | +end |
| 77 | + |
| 78 | +function encodeToPDU(phoneNumber, message) |
| 79 | + local smsc="" |
| 80 | + local function TONGen(input, isPhonenum) |
| 81 | + local TONBegin = "91" |
| 82 | + local orinInput = input |
| 83 | + if #input % 2 == 1 then |
| 84 | + input = input .. 'F' |
| 85 | + end |
| 86 | + -- 交换数位 |
| 87 | + local transformed = {} |
| 88 | + for i = 1, #input, 2 do |
| 89 | + local firstChar = input:sub(i, i) |
| 90 | + local secondChar = input:sub(i + 1, i + 1) |
| 91 | + transformed[#transformed + 1] = secondChar |
| 92 | + transformed[#transformed + 1] = firstChar |
| 93 | + end |
| 94 | + local TONStr = TONBegin .. table.concat(transformed) |
| 95 | + local TONLength = 0 |
| 96 | + if (isPhonenum == false) then |
| 97 | + TONLength = string.len(TONStr) / 2 |
| 98 | + else |
| 99 | + TONLength = string.format("%02X", string.len(orinInput)) |
| 100 | + end |
| 101 | + if (string.len(TONLength) < 2) then --当短信中心号码过短时,最开头需要补0 |
| 102 | + TONLength = "0" .. TONLength |
| 103 | + end |
| 104 | + return TONLength .. TONStr |
| 105 | + end |
| 106 | + |
| 107 | + local function splitMessage(msg,subLen) |
| 108 | + local segments = {} |
| 109 | + local len = string.len(msg) |
| 110 | + local i = 1 |
| 111 | + while i <= len do |
| 112 | + local segment = msg:sub(i,i+subLen-1) |
| 113 | + segments[#segments + 1] = segment |
| 114 | + i = i + subLen |
| 115 | + end |
| 116 | + return segments |
| 117 | + end |
| 118 | + |
| 119 | + local function generateRandomInt8() |
| 120 | + math.randomseed(os.time()) |
| 121 | + local randomInt8 = math.random(0, 255) |
| 122 | + return randomInt8 |
| 123 | + end |
| 124 | + |
| 125 | + |
| 126 | + local SCA=TONGen(smsc, false) |
| 127 | + local MTI0='1' |
| 128 | + local MTI1='0' |
| 129 | + local RD='0' |
| 130 | + local VPF0='0' |
| 131 | + local VPF1='0' |
| 132 | + local SR='0' |
| 133 | + local UDHI='0' |
| 134 | + local RP='0' |
| 135 | + local pdu |
| 136 | + local TPMR = "00" -- TP-MR 消息基准 |
| 137 | + local phoneNumEncode = TONGen(phoneNumber, true) --DA |
| 138 | + local TPPID = "00" -- TP-PID |
| 139 | + local TPDCS = "08" -- TP-DCS |
| 140 | + local MSG = encodeToUCS2(message) |
| 141 | + local sendLimit=60*4 ---单条短信字符限制 |
| 142 | + |
| 143 | + if string.len(MSG) >= sendLimit then |
| 144 | + UDHI='1' |
| 145 | + end |
| 146 | + local PDUType = RP .. UDHI .. SR .. VPF1 .. VPF0 .. RD .. MTI1 .. MTI0 -- PDU-Type |
| 147 | + |
| 148 | + local decimalValue = tonumber(PDUType, 2) -- 将二进制字符串转换为十进制数 |
| 149 | + PDUType = string.format("%02X", decimalValue) -- 将十进制数转换为十六进制字符串 |
| 150 | + if (string.len(smsc) == 0) then |
| 151 | + pdu = "00" .. PDUType .. TPMR .. phoneNumEncode |
| 152 | + else |
| 153 | + pdu = SCA .. PDUType .. TPMR .. phoneNumEncode |
| 154 | + end |
| 155 | + |
| 156 | + local sendList={} |
| 157 | + if string.len(MSG) <= sendLimit then |
| 158 | + local MSGLen = string.format("%02X", string.len(MSG) / 2) |
| 159 | + local AllMsgLen = 7 + string.len(phoneNumEncode) / 2 + string.len(MSG) / 2 - 2 |
| 160 | + pdu = AllMsgLen .. " " .. pdu .. TPPID .. TPDCS .. MSGLen .. MSG |
| 161 | + sendList[#sendList + 1]=pdu |
| 162 | + else |
| 163 | + local RefSeq=generateRandomInt8() |
| 164 | + local segments = splitMessage(MSG,sendLimit) |
| 165 | + for i, segment in ipairs(segments) do |
| 166 | + local UDHIHeader = string.format("05%02X%02X%02X%02X%02X", 0,3,RefSeq,#segments,i) -- 长短信的UDHI头 --05 00 03 85 03 02. |
| 167 | + local MSGLen = string.format("%02X", string.len(segment) / 2 + 6) |
| 168 | + segment=UDHIHeader .. segment |
| 169 | + local AllMsgLen = 7 + string.len(phoneNumEncode) / 2 + string.len(segment) / 2 - 2 |
| 170 | + local currentPdu = AllMsgLen .. " " .. pdu .. TPPID .. TPDCS .. MSGLen .. segment |
| 171 | + sendList[#sendList + 1]=currentPdu |
| 172 | + end |
| 173 | + end |
| 174 | + local file = io.open("/tmp/sms.log", "a") -- 打开文件以追加内容 |
| 175 | + if file then |
| 176 | + file:write(table.concat(sendList),"\n") -- 写入内容到文件,以空格分隔并在结尾加入换行符 |
| 177 | + file:close() -- 关闭文件 |
| 178 | + end |
| 179 | + |
| 180 | + for i, segment in ipairs(sendList) do |
| 181 | + local odpall = io.popen("/usr/share/modem/mopdu " .. segment) |
| 182 | + os.execute("sleep " .. 2) --需要一点等待的时间 |
| 183 | + |
| 184 | + end |
| 185 | + return odpall |
| 186 | + |
| 187 | +end |
| 188 | + |
| 189 | +function encodeToUCS2(text) |
| 190 | + local ucs2 = {} |
| 191 | + local index = 1 |
| 192 | + local length = string.len(text) |
| 193 | + |
| 194 | + while index <= length do |
| 195 | + local byte1 = string.byte(text, index) |
| 196 | + |
| 197 | + if byte1 < 128 then |
| 198 | + ucs2[#ucs2 + 1] = string.format("%04X", byte1) |
| 199 | + index = index + 1 |
| 200 | + elseif byte1 >= 192 and byte1 < 224 then |
| 201 | + local byte2 = string.byte(text, index + 1) |
| 202 | + ucs2[#ucs2 + 1] = string.format("%04X", (byte1 - 192) * 64 + (byte2 - 128)) |
| 203 | + index = index + 2 |
| 204 | + elseif byte1 >= 224 then |
| 205 | + local byte2 = string.byte(text, index + 1) |
| 206 | + local byte3 = string.byte(text, index + 2) |
| 207 | + ucs2[#ucs2 + 1] = string.format("%04X", (byte1 - 224) * 4096 + (byte2 - 128) * 64 + (byte3 - 128)) |
| 208 | + index = index + 3 |
| 209 | + else |
| 210 | + return nil |
| 211 | + end |
| 212 | + end |
| 213 | + |
| 214 | + return table.concat(ucs2) |
| 215 | +end |
| 216 | + |
| 217 | + |
| 218 | +function slots() |
| 219 | + local sim = { } |
| 220 | + local devv = tostring(uci:get("sms_tool", "general", "readport")) |
| 221 | + -- local led = tostring(uci:get("sms_tool", "general", "smsled")) |
| 222 | + -- local dsled = tostring(uci:get("sms_tool", "general", "ledtype")) |
| 223 | + -- local ln = tostring(uci:get("sms_tool", "general", "lednotify")) |
| 224 | + |
| 225 | + local smsmem = tostring(uci:get("sms_tool", "general", "storage")) |
| 226 | + |
| 227 | + local statusb = luci.util.exec("sms_tool -s" .. smsmem .. " -d ".. devv .. " status") |
| 228 | + local usex = string.sub (statusb, 23, 27) |
| 229 | + local max = statusb:match('[^: ]+$') |
| 230 | + sim["use"] = string.match(usex, '%d+') |
| 231 | + local smscount = string.match(usex, '%d+') |
| 232 | + -- if ln == "1" then |
| 233 | + -- luci.sys.call("echo " .. smscount .. " > /etc/config/sms_count") |
| 234 | + -- if dsled == "S" then |
| 235 | + -- luci.util.exec("/etc/init.d/led restart") |
| 236 | + -- end |
| 237 | + -- if dsled == "D" then |
| 238 | + -- luci.sys.call("echo 0 > '/sys/class/leds/" .. led .. "/brightness'") |
| 239 | + -- end |
| 240 | + -- end |
| 241 | + sim["all"] = string.match(max, '%d+') |
| 242 | + luci.http.prepare_content("application/json") |
| 243 | + luci.http.write_json(sim) |
| 244 | +end |
| 245 | + |
0 commit comments