--- 模块功能：短信功能
-- @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:短信内容
返回值：true：发送成功，false发送失败
]]
local function _send(num, data)
    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编码的字符串
-- @function[opt=nil] cbFnc，短信发送结果异步返回时的用户回调函数，回调函数的调用形式为：
--              cbFnc(result,num,data)
--              num：短信接收方的号码，ASCII码字符串格式
--              data：短信内容，unicode大端编码的HEX字符串
-- @number[opt=nil] idx，插入短信发送缓冲表的位置，默认是插入末尾
-- @return result，true表示调用接口成功（并不是短信发送成功，短信发送结果，通过sendcnf返回，如果有cbFnc，会通知cbFnc函数）；返回false，表示调用接口失败
-- @usage sms.send("10086","test",cbFnc)
function send(num, data, cbFnc, idx)
    --号码或者内容非法
    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
    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")
