最终提交
This commit is contained in:
713
4G/源代码/lib/sms.lua
Normal file
713
4G/源代码/lib/sms.lua
Normal file
@@ -0,0 +1,713 @@
|
||||
--- 模块功能:短信功能
|
||||
-- @module sms
|
||||
-- @author openLuat
|
||||
-- @license MIT
|
||||
-- @copyright openLuat
|
||||
-- @release 2018.03.25
|
||||
require "sys"
|
||||
require "ril"
|
||||
require "common"
|
||||
require "utils"
|
||||
module(..., package.seeall)
|
||||
|
||||
local publish = sys.publish
|
||||
local req = ril.request
|
||||
|
||||
--ready:底层短信功能是否准备就绪
|
||||
local smsReady, isn, tlongsms, netReady, cpinReady,smsUrcReady = false, 255, {}
|
||||
local ssub, slen, sformat, smatch = string.sub, string.len, string.format, string.match
|
||||
local tsend = {}
|
||||
|
||||
--[[
|
||||
函数名:numtobcdnum
|
||||
功能 :号码ASCII字符串 转化为 BCD编码格式字符串,仅支持数字和+,例如"+8618126324567" -> 91688121364265f7 (表示第1个字节是0x91,第2个字节为0x68,......)
|
||||
参数 :
|
||||
num:待转换字符串
|
||||
返回值:转换后的字符串
|
||||
]]
|
||||
local function numtobcdnum(num)
|
||||
local len, numfix, convnum = slen(num), "81", ""
|
||||
|
||||
if ssub(num, 1, 1) == "+" then
|
||||
numfix = "91"
|
||||
len = len - 1
|
||||
num = ssub(num, 2, -1)
|
||||
end
|
||||
|
||||
if len % 2 ~= 0 then --奇数位
|
||||
for i = 1, (len - (len % 2)) / 2 do
|
||||
convnum = convnum .. ssub(num, i * 2, i * 2) .. ssub(num, i * 2 - 1, i * 2 - 1)
|
||||
end
|
||||
convnum = convnum .. "F" .. ssub(num, len, len)
|
||||
else --偶数位
|
||||
for i = 1, (len - (len % 2)) / 2 do
|
||||
convnum = convnum .. ssub(num, i * 2, i * 2) .. ssub(num, i * 2 - 1, i * 2 - 1)
|
||||
end
|
||||
end
|
||||
|
||||
return numfix .. convnum
|
||||
end
|
||||
|
||||
--[[
|
||||
函数名:bcdnumtonum
|
||||
功能 :BCD编码格式字符串 转化为 号码ASCII字符串,仅支持数字和+,例如91688121364265f7 (表示第1个字节是0x91,第2个字节为0x68,......) -> "+8618126324567"
|
||||
参数 :
|
||||
num:待转换字符串
|
||||
返回值:转换后的字符串
|
||||
]]
|
||||
local function bcdnumtonum(num)
|
||||
local len, numfix, convnum = slen(num), "", ""
|
||||
|
||||
if len % 2 ~= 0 then
|
||||
print("your bcdnum is err " .. num)
|
||||
return
|
||||
end
|
||||
|
||||
if ssub(num, 1, 2) == "91" then
|
||||
numfix = "+"
|
||||
end
|
||||
|
||||
len, num = len - 2, ssub(num, 3, -1)
|
||||
|
||||
for i = 1, (len - (len % 2)) / 2 do
|
||||
convnum = convnum .. ssub(num, i * 2, i * 2) .. ssub(num, i * 2 - 1, i * 2 - 1)
|
||||
end
|
||||
|
||||
if ssub(convnum, len, len) == "f" or ssub(convnum, len, len) == "F" then
|
||||
convnum = ssub(convnum, 1, -2)
|
||||
end
|
||||
|
||||
return numfix .. convnum
|
||||
end
|
||||
|
||||
|
||||
--[[
|
||||
函数名:_send
|
||||
功能 :发送短信(内部接口)
|
||||
参数 :num,号码
|
||||
data:短信内容
|
||||
istp:发送方式选择
|
||||
返回值:true:发送成功,false发送失败
|
||||
]]
|
||||
local function _send(num, data,istp)
|
||||
|
||||
if istp == "TEXT" or istp == "text" then
|
||||
req("AT+CSCS=\"IRA\"")
|
||||
-- req("AT+CSMP?")
|
||||
-- req("AT+CSCS?")
|
||||
req("AT+CMGF=1")
|
||||
table.insert(tsend, {sval = 1, rval = 0, flg = true})--sval发送的包数,rval收到的包数
|
||||
req(string.format("%s%s", "AT+CMGS=",num), string.format("%s",data))
|
||||
req('AT+CSCS="UCS2"')
|
||||
req("AT+CMGF=0")
|
||||
return
|
||||
end
|
||||
|
||||
local numlen, datalen, pducnt, pdu, pdulen, udhi = sformat("%02X", slen(num)), slen(data) / 2, 1, "", "", ""
|
||||
if not smsReady or not netReady then return false end
|
||||
|
||||
--如果发送的数据大于140字节则为长短信
|
||||
if datalen > 140 then
|
||||
--计算出长短信拆分后的总条数,长短信的每包的数据实际只有134个实际要发送的短信内容,数据的前6字节为协议头
|
||||
pducnt = sformat("%d", (datalen + 133) / 134)
|
||||
pducnt = tonumber(pducnt)
|
||||
--分配一个序列号,范围为0-255
|
||||
isn = isn == 255 and 0 or isn + 1
|
||||
end
|
||||
|
||||
table.insert(tsend, {sval = pducnt, rval = 0, flg = true})--sval发送的包数,rval收到的包数
|
||||
|
||||
if ssub(num, 1, 1) == "+" then
|
||||
numlen = sformat("%02X", slen(num) - 1)
|
||||
end
|
||||
|
||||
for i = 1, pducnt do
|
||||
--如果是长短信
|
||||
if pducnt > 1 then
|
||||
local len_mul
|
||||
len_mul = (i == pducnt and sformat("%02X", datalen - (pducnt - 1) * 134 + 6) or "8C")
|
||||
--udhi:6位协议头格式
|
||||
udhi = "050003" .. sformat("%02X", isn) .. sformat("%02X", pducnt) .. sformat("%02X", i)
|
||||
log.info(datalen, udhi)
|
||||
pdu = "005110" .. numlen .. numtobcdnum(num) .. "000800" .. len_mul .. udhi .. ssub(data, (i - 1) * 134 * 2 + 1, i * 134 * 2)
|
||||
--发送短短信
|
||||
else
|
||||
datalen = sformat("%02X", datalen)
|
||||
pdu = "001110" .. numlen .. numtobcdnum(num) .. "000800" .. datalen .. data
|
||||
end
|
||||
pdulen = slen(pdu) / 2 - 1
|
||||
req(sformat("%s%s", "AT+CMGS=", pdulen), pdu)
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
--[[
|
||||
函数名:read
|
||||
功能 :读短信
|
||||
参数 :pos短信位置
|
||||
返回值:true:读成功,false读失败
|
||||
]]
|
||||
function read(pos)
|
||||
if not smsReady or pos == nil or pos == 0 then return false end
|
||||
|
||||
req("AT+CMGR=" .. pos)
|
||||
return true
|
||||
end
|
||||
|
||||
--[[
|
||||
函数名:delete
|
||||
功能 :删除短信
|
||||
参数 :pos短信位置
|
||||
返回值:true:删除成功,false删除失败
|
||||
]]
|
||||
function delete(pos)
|
||||
if not smsReady or pos == nil or pos == 0 then return false end
|
||||
req("AT+CMGD=" .. pos)
|
||||
return true
|
||||
end
|
||||
|
||||
Charmap = {[0] = 0x40, 0xa3, 0x24, 0xa5, 0xe8, 0xE9, 0xF9, 0xEC, 0xF2, 0xC7, 0x0A, 0xD8, 0xF8, 0x0D, 0xC5, 0xE5
|
||||
, 0x0394, 0x5F, 0x03A6, 0x0393, 0x039B, 0x03A9, 0x03A0, 0x03A8, 0x03A3, 0x0398, 0x039E, 0x1B, 0xC6, 0xE5, 0xDF, 0xA9
|
||||
, 0x20, 0x21, 0x22, 0x23, 0xA4, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F
|
||||
, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F
|
||||
, 0xA1, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F
|
||||
, 0X50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0xC4, 0xD6, 0xD1, 0xDC, 0xA7
|
||||
, 0xBF, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F
|
||||
, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0xE4, 0xF6, 0xF1, 0xFC, 0xE0}
|
||||
|
||||
Charmapctl = {[10] = 0x0C, [20] = 0x5E, [40] = 0x7B, [41] = 0x7D, [47] = 0x5C, [60] = 0x5B, [61] = 0x7E
|
||||
, [62] = 0x5D, [64] = 0x7C, [101] = 0xA4}
|
||||
|
||||
--[[
|
||||
函数名:gsm7bitdecode
|
||||
功能 :7位编码, 在PDU模式中,当使用7位编码时,最多可发160个字符
|
||||
参数 :data
|
||||
longsms
|
||||
返回值:
|
||||
]]
|
||||
function gsm7bitdecode(data, longsms)
|
||||
local ucsdata, lpcnt, tmpdata, resdata, nbyte, nleft, ucslen, olddat = "", slen(data) / 2, 0, 0, 0, 0, 0
|
||||
|
||||
if longsms then
|
||||
tmpdata = tonumber("0x" .. ssub(data, 1, 2))
|
||||
resdata = bit.rshift(tmpdata, 1)
|
||||
if olddat == 27 then
|
||||
if Charmapctl[resdata] then --特殊字符
|
||||
olddat, resdata = resdata, Charmapctl[resdata]
|
||||
ucsdata = ssub(ucsdata, 1, -5)
|
||||
else
|
||||
olddat, resdata = resdata, Charmap[resdata]
|
||||
end
|
||||
else
|
||||
olddat, resdata = resdata, Charmap[resdata]
|
||||
end
|
||||
ucsdata = ucsdata .. sformat("%04X", resdata)
|
||||
else
|
||||
tmpdata = tonumber("0x" .. ssub(data, 1, 2))
|
||||
resdata = bit.band(bit.bor(bit.lshift(tmpdata, nbyte), nleft), 0x7f)
|
||||
if olddat == 27 then
|
||||
if Charmapctl[resdata] then --特殊字符
|
||||
olddat, resdata = resdata, Charmapctl[resdata]
|
||||
ucsdata = ssub(ucsdata, 1, -5)
|
||||
else
|
||||
olddat, resdata = resdata, Charmap[resdata]
|
||||
end
|
||||
else
|
||||
olddat, resdata = resdata, Charmap[resdata]
|
||||
end
|
||||
ucsdata = ucsdata .. sformat("%04X", resdata)
|
||||
|
||||
nleft = bit.rshift(tmpdata, 7 - nbyte)
|
||||
nbyte = nbyte + 1
|
||||
ucslen = ucslen + 1
|
||||
end
|
||||
|
||||
for i = 2, lpcnt do
|
||||
tmpdata = tonumber("0x" .. ssub(data, (i - 1) * 2 + 1, i * 2))
|
||||
if tmpdata == nil then break end
|
||||
resdata = bit.band(bit.bor(bit.lshift(tmpdata, nbyte), nleft), 0x7f)
|
||||
if olddat == 27 then
|
||||
if Charmapctl[resdata] then --特殊字符
|
||||
olddat, resdata = resdata, Charmapctl[resdata]
|
||||
ucsdata = ssub(ucsdata, 1, -5)
|
||||
else
|
||||
olddat, resdata = resdata, Charmap[resdata]
|
||||
end
|
||||
else
|
||||
olddat, resdata = resdata, Charmap[resdata]
|
||||
end
|
||||
ucsdata = ucsdata .. sformat("%04X", resdata)
|
||||
|
||||
nleft = bit.rshift(tmpdata, 7 - nbyte)
|
||||
nbyte = nbyte + 1
|
||||
ucslen = ucslen + 1
|
||||
|
||||
if nbyte == 7 then
|
||||
if olddat == 27 then
|
||||
if Charmapctl[nleft] then --特殊字符
|
||||
olddat, nleft = nleft, Charmapctl[nleft]
|
||||
ucsdata = ssub(ucsdata, 1, -5)
|
||||
else
|
||||
olddat, nleft = nleft, Charmap[nleft]
|
||||
end
|
||||
else
|
||||
olddat, nleft = nleft, Charmap[nleft]
|
||||
end
|
||||
ucsdata = ucsdata .. sformat("%04X", nleft)
|
||||
nbyte, nleft = 0, 0
|
||||
ucslen = ucslen + 1
|
||||
end
|
||||
end
|
||||
|
||||
return ucsdata, ucslen
|
||||
end
|
||||
|
||||
--[[
|
||||
函数名:gsm8bitdecode
|
||||
功能 :8位编码
|
||||
参数 :data
|
||||
longsms
|
||||
返回值:
|
||||
]]
|
||||
function gsm8bitdecode(data)
|
||||
local ucsdata, lpcnt = "", slen(data) / 2
|
||||
|
||||
for i = 1, lpcnt do
|
||||
ucsdata = ucsdata .. "00" .. ssub(data, (i - 1) * 2 + 1, i * 2)
|
||||
end
|
||||
|
||||
return ucsdata, lpcnt
|
||||
end
|
||||
|
||||
--[[
|
||||
函数名:rsp
|
||||
功能 :AT应答
|
||||
参数 :cmd,success,response,intermediate
|
||||
返回值:无
|
||||
]]
|
||||
local function rsp(cmd, success, response, intermediate)
|
||||
local prefix = smatch(cmd, "AT(%+%u+)")
|
||||
log.info("lib_sms rsp", prefix, cmd, success, response, intermediate)
|
||||
|
||||
--读短信成功
|
||||
if prefix == "+CMGR" then
|
||||
if not success then publish("SMS_READ_CNF") return end
|
||||
local convnum, t, stat, alpha, len, pdu, data, longsms, total, isn, idx = "", ""
|
||||
if intermediate then
|
||||
stat, alpha, len, pdu = smatch(intermediate, "+CMGR:%s*(%d),(.*),%s*(%d+)\r\n(%x+)")
|
||||
len = tonumber(len)--PDU数据长度,不包括短信息中心号码
|
||||
end
|
||||
|
||||
--收到的PDU包不为空则解析PDU包
|
||||
if pdu and pdu ~= "" then
|
||||
local offset, addlen, addnum, flag, dcs, tz, txtlen, fo = 5
|
||||
pdu = ssub(pdu, (slen(pdu) / 2 - len) * 2 + 1, -1)--PDU数据,不包括短信息中心号码
|
||||
fo = tonumber("0x" .. ssub(pdu, 1, 1))--PDU短信首字节的高4位,第6位为数据报头标志位
|
||||
if bit.band(fo, 0x4) ~= 0 then
|
||||
longsms = true
|
||||
end
|
||||
addlen = tonumber(sformat("%d", "0x" .. ssub(pdu, 3, 4)))--回复地址数字个数
|
||||
|
||||
addlen = addlen % 2 == 0 and addlen + 2 or addlen + 3 --加上号码类型2位(5,6)or 加上号码类型2位(5,6)和1位F
|
||||
|
||||
offset = offset + addlen
|
||||
|
||||
addnum = ssub(pdu, 5, 5 + addlen - 1)
|
||||
convnum = bcdnumtonum(addnum)
|
||||
|
||||
flag = tonumber(sformat("%d", "0x" .. ssub(pdu, offset, offset + 1)))--协议标识 (TP-PID)
|
||||
offset = offset + 2
|
||||
dcs = tonumber(sformat("%d", "0x" .. ssub(pdu, offset, offset + 1)))--用户信息编码方式 Dcs=8,表示短信存放的格式为UCS2编码
|
||||
offset = offset + 2
|
||||
tz = ssub(pdu, offset, offset + 13)--时区7个字节
|
||||
offset = offset + 14
|
||||
txtlen = tonumber(sformat("%d", "0x" .. ssub(pdu, offset, offset + 1)))--短信文本长度
|
||||
offset = offset + 2
|
||||
data = ssub(pdu, offset, offset + txtlen * 2 - 1)--短信文本
|
||||
if longsms then
|
||||
if tonumber("0x" .. ssub(data, 5, 6)) == 3 then
|
||||
isn, total, idx = tonumber("0x" .. ssub(data, 7, 8)), tonumber("0x" .. ssub(data, 9, 10)), tonumber("0x" .. ssub(data, 11, 12))
|
||||
data = ssub(data, 13, -1)--去掉报头6个字节
|
||||
elseif tonumber("0x" .. ssub(data, 5, 6)) == 4 then
|
||||
isn, total, idx = tonumber("0x" .. ssub(data, 7, 10)), tonumber("0x" .. ssub(data, 11, 12)), tonumber("0x" .. ssub(data, 13, 14))
|
||||
data = ssub(data, 15, -1)--去掉报头7个字节
|
||||
end
|
||||
end
|
||||
|
||||
log.info("TP-PID : ", flag, "dcs: ", dcs, "tz: ", tz, "data: ", data, "txtlen", txtlen)
|
||||
|
||||
if dcs == 0x00 then --7bit encode
|
||||
local newlen
|
||||
data, newlen = gsm7bitdecode(data, longsms)
|
||||
if newlen > txtlen then
|
||||
data = ssub(data, 1, txtlen * 4)
|
||||
end
|
||||
log.info("7bit to ucs2 data: ", data, "txtlen", txtlen, "newlen", newlen)
|
||||
elseif dcs == 0x04 then --8bit encode
|
||||
data, txtlen = gsm8bitdecode(data)
|
||||
log.info("8bit to ucs2 data: ", data, "txtlen", txtlen)
|
||||
end
|
||||
|
||||
for i = 1, 7 do
|
||||
t = t .. ssub(tz, i * 2, i * 2) .. ssub(tz, i * 2 - 1, i * 2 - 1)
|
||||
|
||||
if i <= 3 then
|
||||
t = i < 3 and (t .. "/") or (t .. ",")
|
||||
elseif i <= 6 then
|
||||
t = i < 6 and (t .. ":") or (t .. "+")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local pos = smatch(cmd, "AT%+CMGR=(%d+)")
|
||||
data = data or ""
|
||||
alpha = alpha or ""
|
||||
publish("SMS_READ_CNF", success, convnum, data, pos, t, alpha, total, idx, isn)
|
||||
elseif prefix == "+CMGD" then
|
||||
publish("SMS_DELETE_CNF", success)
|
||||
elseif prefix == "+CMGS" then
|
||||
--如果是短短信,直接发送短信确认消息
|
||||
if tsend[1].sval == 1 then --{sval=pducnt,rval=0,flg=true}
|
||||
table.remove(tsend, 1)
|
||||
publish("SMS_SEND_CNF", success)
|
||||
--如果是长短信,所有cmgs之后,才抛出SMS_SEND_CNF,所有cmgs都成功,才true,其余都是false
|
||||
else
|
||||
tsend[1].rval = tsend[1].rval + 1
|
||||
--只要其中有发送失败的短信,则整个长短信将标记为发送失败
|
||||
if not success then tsend[1].flg = false end
|
||||
if tsend[1].sval == tsend[1].rval then
|
||||
publish("SMS_SEND_CNF", tsend[1].flg)
|
||||
table.remove(tsend, 1)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function init()
|
||||
if cpinReady and smsUrcReady and netReady then
|
||||
--使用PDU模式发送
|
||||
req("AT+CMGF=0")
|
||||
--设置短信TEXT 模式参数
|
||||
-- req("AT+CSMP=17,167,0,8")
|
||||
--设置AT命令的字符编码是UCS2
|
||||
req('AT+CSCS="UCS2"')
|
||||
--设置存储区为SM
|
||||
req('AT+CPMS="SM"')
|
||||
-- 上报消息CMTI
|
||||
req("AT+CNMI=2,1,0,0,0")
|
||||
--分发短信准备好消息
|
||||
publish("SMS_READY")
|
||||
--清空已读短信
|
||||
req("AT+CMGD=1,3")
|
||||
end
|
||||
end
|
||||
|
||||
--[[
|
||||
函数名:urc
|
||||
功能 :主动上报消息处理函数
|
||||
参数 :data,prefix
|
||||
返回值:无
|
||||
]]
|
||||
local function urc(data, prefix)
|
||||
--短信准备好
|
||||
if data == "SMS READY" then
|
||||
smsUrcReady = true
|
||||
init()
|
||||
-- 存储短信
|
||||
elseif prefix == "+CMTI" then
|
||||
--分发收到新短信消息
|
||||
publish("SMS_NEW_MSG_IND", smatch(data, "(%d+)", slen(prefix) + 1))
|
||||
end
|
||||
end
|
||||
|
||||
--[[
|
||||
函数名:getsmsstate
|
||||
功能 :获取短消息是否准备好的状态
|
||||
参数 :无
|
||||
返回值:true准备好,其他值:未准备好
|
||||
]]
|
||||
function getsmsstate()
|
||||
return smsReady
|
||||
end
|
||||
|
||||
--[[
|
||||
函数名:mergelongsms
|
||||
功能 :合并长短信
|
||||
参数 :
|
||||
tag:长短信标记(ISN和总条数的拼接字符串)
|
||||
返回值:无
|
||||
]]
|
||||
local function mergelongsms(tag)
|
||||
local data = ""
|
||||
--按表中的顺序,一次拼接短消息内容
|
||||
for i = 1, tlongsms[tag]["total"] do
|
||||
data = data .. (tlongsms[tag]["dat"][i] or "")
|
||||
end
|
||||
--分发长短信合并确认消息
|
||||
publish("LONG_SMS_MERGR_CNF", true, tlongsms[tag]["num"], data, tlongsms[tag]["t"], tlongsms[tag]["nam"])
|
||||
log.info("mergelongsms", "num:", tlongsms[tag]["num"], "data", data)
|
||||
tlongsms[tag]["dat"], tlongsms[tag] = nil
|
||||
end
|
||||
|
||||
--[[
|
||||
函数名:longsmsind
|
||||
功能 :长短信被拆解后的消息包上报
|
||||
参数 :id,num, data,datetime,name,total,idx,isn
|
||||
返回值:无
|
||||
]]
|
||||
local function longsmsind(num, data, datetime, name, total, idx, isn)
|
||||
log.info("longsmsind", "isn", isn, "total:", total, "idx:", idx, "data", data)
|
||||
|
||||
if tlongsms[isn .. total] then
|
||||
if not tlongsms[isn .. total]["dat"] then tlongsms[isn .. total]["dat"] = {} end
|
||||
tlongsms[isn .. total]["dat"][idx] = data
|
||||
else
|
||||
tlongsms[isn .. total] = {}
|
||||
tlongsms[isn .. total]["total"], tlongsms[isn .. total]["num"], tlongsms[isn .. total]["t"], tlongsms[isn .. total]["nam"] = total, num, datetime, name
|
||||
tlongsms[isn .. total]["dat"] = {}
|
||||
tlongsms[isn .. total]["dat"][idx] = data
|
||||
end
|
||||
|
||||
local totalrcv = 0
|
||||
for i = 1, tlongsms[isn .. total]["total"] do
|
||||
if tlongsms[isn .. total]["dat"][i] then totalrcv = totalrcv + 1 end
|
||||
end
|
||||
--长短信接收完整
|
||||
if tlongsms[isn .. total]["total"] == totalrcv then
|
||||
sys.timerStop(mergelongsms, isn .. total)
|
||||
mergelongsms(isn .. total)
|
||||
else
|
||||
--如果2分钟后长短信还没收完整,2分钟后将自动合并已收到的长短信
|
||||
sys.timerStart(mergelongsms, 120000, isn .. total)
|
||||
end
|
||||
end
|
||||
|
||||
--注册长短信合并处理函数
|
||||
sys.subscribe("LONG_SMS_MERGE", longsmsind)
|
||||
|
||||
ril.regUrc("SMS READY", urc)
|
||||
ril.regUrc("+CMT", urc)
|
||||
ril.regUrc("+CMTI", urc)
|
||||
|
||||
ril.regRsp("+CMGR", rsp)
|
||||
ril.regRsp("+CMGD", rsp)
|
||||
ril.regRsp("+CMGS", rsp)
|
||||
|
||||
|
||||
--短信发送缓冲表最大个数
|
||||
local SMS_SEND_BUF_MAX_CNT = 10
|
||||
--短信发送间隔,单位毫秒
|
||||
local SMS_SEND_INTERVAL = 3000
|
||||
--短信发送缓冲表
|
||||
local tsmsnd = {}
|
||||
|
||||
--[[
|
||||
函数名:sndnxt
|
||||
功能 :发送短信发送缓冲表中的第一条短信
|
||||
参数 :无
|
||||
返回值:无
|
||||
]]
|
||||
local function sndnxt()
|
||||
if #tsmsnd > 0 then
|
||||
_send(tsmsnd[1].num, tsmsnd[1].data)
|
||||
end
|
||||
end
|
||||
|
||||
--[[
|
||||
函数名:sendcnf
|
||||
功能 :SMS_SEND_CNF消息的处理函数,异步通知短信发送结果
|
||||
参数 :
|
||||
result:短信发送结果,true为成功,false或者nil为失败
|
||||
返回值:无
|
||||
]]
|
||||
local function sendcnf(result)
|
||||
log.info("sendcnf", result)
|
||||
local num, data, cb = tsmsnd[1].num, tsmsnd[1].data, tsmsnd[1].cb
|
||||
--从短信发送缓冲表中移除当前短信
|
||||
table.remove(tsmsnd, 1)
|
||||
--如果有发送回调函数,执行回调
|
||||
if cb then cb(result, num, data) end
|
||||
--如果短信发送缓冲表中还有短信,则SMS_SEND_INTERVAL毫秒后,继续发送下条短信
|
||||
if #tsmsnd > 0 then sys.timerStart(sndnxt, SMS_SEND_INTERVAL) end
|
||||
end
|
||||
|
||||
--- 发送短信
|
||||
-- @string num 短信接收方号码,ASCII码字符串格式
|
||||
-- @string data 短信内容,GB2312编码的字符串
|
||||
-- 如果短信内容中只有ascii可见字符,则超过160个字符时,会被拆分为几条长级联短信进行发送
|
||||
-- 如果短信内容中包含除ascii可见字符外的其他字符,例如包含汉字,一个汉字算作一个字符,一个ascii可见字符也算作一个字符,超过70个字符时,会被拆分为几条长级联短信进行发送
|
||||
-- @function[opt=nil] cbFnc 短信发送结果异步返回时的用户回调函数,回调函数的调用形式为:
|
||||
-- cbFnc(result,num,data)
|
||||
-- num:短信接收方的号码,ASCII码字符串格式
|
||||
-- data:短信内容,unicode大端编码的HEX字符串
|
||||
-- @number[opt=nil] idx 插入短信发送缓冲表的位置,默认是插入末尾
|
||||
-- @string[opt=nil] istp 表示发送方式选择 "TEXT" or "text" 表示 text文本方式发送,nil或其它参数表示pdu方式发送,补充pdu方式采用 USC2 编码方式发送
|
||||
-- @return result,true表示调用接口成功(并不是短信发送成功,短信发送结果,通过sendcnf返回,如果有cbFnc,会通知cbFnc函数);返回false,表示调用接口失败
|
||||
-- @usage sms.send("10086","test",cbFnc,istp)
|
||||
function send(num, data, cbFnc, idx,istp)
|
||||
--号码或者内容非法
|
||||
if not num or num == "" or not data or data == "" then if cbFnc then cbFnc(false, num, data) end return end
|
||||
--短信发送缓冲表已满
|
||||
if #tsmsnd >= SMS_SEND_BUF_MAX_CNT then if cbFnc then cbFnc(false, num, data) end return end
|
||||
|
||||
if istp == "TEXT" or istp == "text" then
|
||||
|
||||
--如果指定了插入位置
|
||||
if idx then
|
||||
table.insert(tsmsnd, idx, {num = num, data = data, cb = cbFnc})
|
||||
--没有指定插入位置,插入到末尾
|
||||
else
|
||||
table.insert(tsmsnd, {num = num, data = data, cb = cbFnc})
|
||||
end
|
||||
|
||||
--如果短信发送缓冲表中只有一条短信,立即触发短信发送动作
|
||||
if #tsmsnd == 1 then _send(num, data,istp) return true end
|
||||
return
|
||||
end
|
||||
|
||||
local dat = string.toHex(common.gb2312ToUcs2be(data))
|
||||
--如果指定了插入位置
|
||||
if idx then
|
||||
table.insert(tsmsnd, idx, {num = num, data = dat, cb = cbFnc})
|
||||
--没有指定插入位置,插入到末尾
|
||||
else
|
||||
table.insert(tsmsnd, {num = num, data = dat, cb = cbFnc})
|
||||
end
|
||||
--如果短信发送缓冲表中只有一条短信,立即触发短信发送动作
|
||||
if #tsmsnd == 1 then _send(num, dat) return true end
|
||||
|
||||
|
||||
end
|
||||
|
||||
|
||||
--短信接收位置表
|
||||
local tnewsms = {}
|
||||
|
||||
--[[
|
||||
函数名:readsms
|
||||
功能 :读取短信接收位置表中的第一条短信
|
||||
参数 :无
|
||||
返回值:无
|
||||
]]
|
||||
local function readsms()
|
||||
if #tnewsms ~= 0 then
|
||||
read(tnewsms[1])
|
||||
end
|
||||
end
|
||||
|
||||
--[[
|
||||
函数名:newsms
|
||||
功能 :SMS_NEW_MSG_IND(未读短信或者新短信主动上报的消息)消息的处理函数
|
||||
参数 :
|
||||
pos:短信存储位置
|
||||
返回值:无
|
||||
]]
|
||||
local function newsms(pos)
|
||||
--存储位置插入到短信接收位置表中
|
||||
table.insert(tnewsms, pos)
|
||||
--如果只有一条短信,则立即读取
|
||||
if #tnewsms == 1 then
|
||||
readsms()
|
||||
end
|
||||
end
|
||||
|
||||
--新短信的用户处理函数
|
||||
local newsmscb
|
||||
|
||||
--- 设置新短信的用户处理函数
|
||||
-- @function cbFnc 新短信的用户处理函数
|
||||
-- @return nil
|
||||
-- @usage sms.setNewSmsCb(cbFnc)
|
||||
function setNewSmsCb(cbFnc)
|
||||
newsmscb = cbFnc
|
||||
end
|
||||
|
||||
--[[
|
||||
函数名:readcnf
|
||||
功能 :SMS_READ_CNF消息的处理函数,异步返回读取的短信内容
|
||||
参数 :
|
||||
result:短信读取结果,true为成功,false或者nil为失败
|
||||
num:短信号码,ASCII码字符串格式
|
||||
data:短信内容,UCS2大端格式的16进制字符串
|
||||
pos:短信的存储位置,暂时没用
|
||||
datetime:短信日期和时间,ASCII码字符串格式
|
||||
name:短信号码对应的联系人姓名,暂时没用
|
||||
返回值:无
|
||||
]]
|
||||
local function readcnf(result, num, data, pos, datetime, name, total, idx, isn)
|
||||
if result then
|
||||
--过滤号码中的86和+86
|
||||
local d1, d2 = string.find(num, "^([%+]*86)")
|
||||
if d1 and d2 then
|
||||
num = string.sub(num, d2 + 1, -1)
|
||||
end
|
||||
--删除短信
|
||||
delete(tnewsms[1])
|
||||
--从短信接收位置表中删除此短信的位置
|
||||
table.remove(tnewsms, 1)
|
||||
if total and total > 1 then
|
||||
publish("LONG_SMS_MERGE", num, data, datetime, name, total, idx, isn)
|
||||
readsms()--读取下一条新短信
|
||||
return
|
||||
end
|
||||
if data then
|
||||
--短信内容转换为GB2312字符串格式
|
||||
data = common.ucs2beToGb2312(data:fromHex())
|
||||
--用户应用程序处理短信
|
||||
if newsmscb then newsmscb(num, data, datetime) end
|
||||
end
|
||||
--继续读取下一条短信
|
||||
readsms()
|
||||
else
|
||||
--删除短信
|
||||
delete(tnewsms[1])
|
||||
--从短信接收位置表中删除此短信的位置
|
||||
table.remove(tnewsms, 1)
|
||||
--继续读取下一条短信
|
||||
readsms()
|
||||
end
|
||||
end
|
||||
|
||||
local function longsmsmergecnf(res, num, data, datetime)
|
||||
--log.info("longsmsmergecnf",num,data,datetime)
|
||||
if data then
|
||||
--短信内容转换为GB2312字符串格式
|
||||
data = common.ucs2beToGb2312(data:fromHex())
|
||||
--用户应用程序处理短信
|
||||
if newsmscb then newsmscb(num, data, datetime) end
|
||||
end
|
||||
end
|
||||
|
||||
sys.subscribe("SMS_NEW_MSG_IND", newsms)
|
||||
sys.subscribe("SMS_READ_CNF", readcnf)
|
||||
sys.subscribe("SMS_SEND_CNF", sendcnf)
|
||||
sys.subscribe("SMS_READY",
|
||||
function()
|
||||
if not smsReady then
|
||||
smsReady = true
|
||||
if netReady then sndnxt() end
|
||||
end
|
||||
end
|
||||
)
|
||||
sys.subscribe("NET_STATE_REGISTERED",
|
||||
function()
|
||||
if not netReady then
|
||||
netReady = true
|
||||
init()
|
||||
if smsReady then sndnxt() end
|
||||
end
|
||||
end
|
||||
)
|
||||
sys.subscribe("SIM_IND",
|
||||
function(para)
|
||||
if para=="RDY" and not cpinReady then
|
||||
cpinReady = true
|
||||
init()
|
||||
end
|
||||
end
|
||||
)
|
||||
|
||||
sys.subscribe("LONG_SMS_MERGR_CNF", longsmsmergecnf)
|
||||
|
||||
-- 此处为临时AT+CNMI补丁
|
||||
sys.timerStart(req, 30000, "AT+CNMI=2,1,0,0,0")
|
||||
Reference in New Issue
Block a user