Przeglądaj źródła

move: 把顶层目录的demo移到bsp/air640w目录下

Wendal Chen 5 lat temu
rodzic
commit
ba05968a46

+ 0 - 0
script/app/playit/main.lua → bsp/air640w/app/playit/main.lua


+ 0 - 0
script/demo/0.hello_world/main.lua → bsp/air640w/demo/0.hello_world/main.lua


+ 0 - 0
script/demo/10.gpio_irq/main.lua → bsp/air640w/demo/10.gpio_irq/main.lua


+ 52 - 52
script/demo/11.uart_irq/main.lua → bsp/air640w/demo/11.uart_irq/main.lua

@@ -1,52 +1,52 @@
-local sys = require "sys"
-
-log.info("main", "uart demo")
-
-local uartid = 1
-
---初始化
-local result = uart.setup(
-    uartid,--串口id
-    115200,--波特率
-    8,--数据位
-    1--停止位
-)
-
-
---循环发数据
-sys.timerLoopStart(uart.write,1000,uartid,"test")
-uart.on(uartid, "receive", function(id, len)
-    log.info("uart", "receive", id, len, uart.read(uartid, len))
-end)
-uart.on(uartid, "sent", function(id)
-    log.info("uart", "sent", id)
-end)
-
---轮询例子
--- sys.taskInit(function ()
---     while true do
---         local data = uart.read(uartid,maxBuffer)
---         if data:len() > 0 then
---             print(data)
---             uart.write(uartid,"receive:"..data)
---         end
---         sys.wait(100)--不阻塞的延时函数
---     end
--- end)
---[[
-
-    uart.None,--校验位
-    uart.LSB,--高低位顺序
-    maxBuffer,--缓冲区大小
-    function ()--接收回调
-        local str = uart.read(uartid,maxBuffer)
-        print("uart","receive:"..str)
-    end,
-    function ()--发送完成回调
-        print("uart","send ok")
-    end
-
-
-]]
-
-sys.run()
+local sys = require "sys"
+
+log.info("main", "uart demo")
+
+local uartid = 1
+
+--初始化
+local result = uart.setup(
+    uartid,--串口id
+    115200,--波特率
+    8,--数据位
+    1--停止位
+)
+
+
+--循环发数据
+sys.timerLoopStart(uart.write,1000,uartid,"test")
+uart.on(uartid, "receive", function(id, len)
+    log.info("uart", "receive", id, len, uart.read(uartid, len))
+end)
+uart.on(uartid, "sent", function(id)
+    log.info("uart", "sent", id)
+end)
+
+--轮询例子
+-- sys.taskInit(function ()
+--     while true do
+--         local data = uart.read(uartid,maxBuffer)
+--         if data:len() > 0 then
+--             print(data)
+--             uart.write(uartid,"receive:"..data)
+--         end
+--         sys.wait(100)--不阻塞的延时函数
+--     end
+-- end)
+--[[
+
+    uart.None,--校验位
+    uart.LSB,--高低位顺序
+    maxBuffer,--缓冲区大小
+    function ()--接收回调
+        local str = uart.read(uartid,maxBuffer)
+        print("uart","receive:"..str)
+    end,
+    function ()--发送完成回调
+        print("uart","send ok")
+    end
+
+
+]]
+
+sys.run()

+ 0 - 0
script/demo/12.dht12/main.lua → bsp/air640w/demo/12.dht12/main.lua


+ 26 - 26
script/demo/20.json/main.lua → bsp/air640w/demo/20.json/main.lua

@@ -1,26 +1,26 @@
-local sys = require "sys"
-
-log.info("main", "json demo")
-print(json.null)
-
-local t = {
-    a = 1,
-    b = "abc",
-    c = {
-        1,2,3,4
-    },
-    d = {
-        x = false,
-        j = 111111
-    },
-    aaaa = 6666,
-}
-
-local s = json.encode(t)
-
-local st = json.decode(s)
-
-print(s)
-print(st.a,st.b,st.d.x)
-
-sys.run()
+local sys = require "sys"
+
+log.info("main", "json demo")
+print(json.null)
+
+local t = {
+    a = 1,
+    b = "abc",
+    c = {
+        1,2,3,4
+    },
+    d = {
+        x = false,
+        j = 111111
+    },
+    aaaa = 6666,
+}
+
+local s = json.encode(t)
+
+local st = json.decode(s)
+
+print(s)
+print(st.a,st.b,st.d.x)
+
+sys.run()

+ 0 - 0
script/demo/60.disp/main.lua → bsp/air640w/demo/60.disp/main.lua


+ 0 - 0
script/demo/70.http_simple/main.lua → bsp/air640w/demo/70.http_simple/main.lua


+ 0 - 0
script/demo/71.mqtt_simple/main.lua → bsp/air640w/demo/71.mqtt_simple/main.lua


+ 0 - 0
script/demo/72.aliyun_autoreg/main.lua → bsp/air640w/demo/72.aliyun_autoreg/main.lua


+ 0 - 0
script/demo/80.socket/main.lua → bsp/air640w/demo/80.socket/main.lua


+ 0 - 0
script/demo/81.socket/main.lua → bsp/air640w/demo/81.socket/main.lua


+ 0 - 0
script/demo/82.modbus_relay2/main.lua → bsp/air640w/demo/82.modbus_relay2/main.lua


+ 0 - 0
script/demo/83.udp/main.lua → bsp/air640w/demo/83.udp/main.lua


+ 0 - 0
script/demo/84.udp_coap/main.lua → bsp/air640w/demo/84.udp_coap/main.lua


+ 49 - 0
bsp/air640w/demo/88.ota/main.lua

@@ -0,0 +1,49 @@
+
+-- 必须有PROJECT和VERSION这两个信息
+
+-- 这个DEMO需要V0003及以上的固件
+
+PROJECT = "otademo"
+VERSION = "1.0.2"
+PROJECT_KEY = "5aae50f068d9408c92b0fb5911834029"
+
+log.info("version", VERSION) -- 打印版本号,就能知道是否升级成功
+
+local sys = require "sys"
+
+wlan.connect("uiot", "1234567890")
+
+-- 生成OTA的URL
+local iot_url = "http://iot.nutz.cn/api/site/firmware_upgrade"
+local ota_url = string.format("%s?project_key=%s&imei=%s&firmware_name=%s&version=%s", 
+                        iot_url,
+                        PROJECT_KEY, 
+                        wlan.getMac(),
+                        PROJECT .. "_" .. rtos.firmware(),
+                        VERSION
+                    )
+
+log.info("ota", "url", ota_url)
+
+sys.taskInit(function()
+    while 1 do
+        if socket.isReady() then
+            -- 联网后轮询
+            http.get(ota_url, {dw="/update.tlv"}, function(code,headers,body)
+                if code == 200 then
+                    -- 当且仅当服务器返回200时,升级文件下载成功
+                    log.info("ota", "http ota ok!!", "reboot!!")
+                    rtos.reboot()
+                else
+                    log.info("ota", "resp", code)
+                end
+            end)
+            sys.wait(120*1000)
+        else
+            sys.wait(3000)
+        end
+    end
+end)
+
+-- 结尾总是这一句哦
+sys.run()

+ 0 - 0
script/demo/91.airkiss/main.lua → bsp/air640w/demo/91.airkiss/main.lua


+ 0 - 0
script/demo/92.ntp/main.lua → bsp/air640w/demo/92.ntp/main.lua


+ 0 - 0
script/demo/93.wifi_scan/main.lua → bsp/air640w/demo/93.wifi_scan/main.lua


+ 0 - 0
script/demo/99.wifi/main.lua → bsp/air640w/demo/99.wifi/main.lua


+ 0 - 2
script/demo/81_socket_long_connect.lnks

@@ -1,2 +0,0 @@
-D:\github\LuatOS\script\lib\sys.lua
-D:\github\LuatOS\script\demo\81.socket\main.lua

+ 0 - 14
script/demo/my_demo.lua

@@ -1,14 +0,0 @@
---
--- 定义了一个模板,用来设置自己环境诸如 wifi  密码等信息
--- 随便存在什么目录上,制作磁盘镜像时引入它即可
--- 需要它的 demo 脚本会用 require("my_demo") 来引用它
---
--- !!! 这只是个模板,要 copy 到你的私有目录再修改
--- 我不想在 git 库里看到你家的 wifi 密码
---
-local mine = {
-  wifi_ssid= "***",
-  wifi_passwd = "***"
-}
-
-return mine

+ 0 - 269
script/lib/httpv2.lua

@@ -1,269 +0,0 @@
---- 模块功能:HTTP客户端, 本代码从LuaTask 2.3.0适配到LuatOS
--- @module httpv2
--- @author 稀饭放姜
--- @author wendal
--- @license MIT
--- @copyright OpenLuat.com
--- @release 2017.10.23
-
-local httpv2 = {}
-
-local Content_type = {'application/x-www-form-urlencoded', 'application/json', 'application/octet-stream'}
-
-function update_resp(resp, data)
-    if not resp.code then
-        -- 第一波数据,看看是不是header
-        -- 需要预防一下, 头部都没发完整的情况
-        local s = resp.tmpdata or ""
-        s = s .. data
-        if #s < 3 then
-            resp.tmpdata = s
-            return true -- 继续等数据
-        end
-        if not string.find(s, '\r\n\r\n', 1, true) then
-            -- header超过8kb了,还没结束,肯定有妖,拒绝
-            if #s > 8192 then
-                log.info("httpv2", "Header bigger than 8192")
-                resp.tmpdata = nil
-                resp.code = 499
-                resp.msg = "Header bigger than 8192"
-                return false
-            else
-                resp.tmpdata = s
-                return true -- 继续等数据
-            end
-        end
-        resp.tmpdata = nil -- 可以释放了
-        -- 接下来,是解析code和header的过程了
-        local _, idx, response_code = s:find("%s(%d+)%s.-\r\n")
-        local _, offset = s:find('\r\n\r\n')
-        local response_header = {}
-        for k, v in string.gmatch(s:sub(idx + 1, offset), "(.-):%s*(.-)\r\n") do response_header[k] = v end
-        local len = response_header["Content-Range"] and tonumber(response_header["Content-Range"]:match("/(%d+)")) or tonumber(response_header["Content-Length"]) or 2147483648
-        s = s:sub((offset or 0) + 1, -1)
-        
-        resp.code = response_code
-        resp.headers = response_header
-        resp.body = s
-        --resp.ok = resp.code == 200 or resp.code == 206
-        return true
-    end
-    resp.body = resp.body .. data -- 如果数据太长, 应该提前报警!!
-    return true
-end
-
--- 处理表的url编码
-function urlencodeTab(params)
-    local msg = {}
-    for k, v in pairs(params) do
-        table.insert(msg, string.urlEncode(k) .. '=' .. string.urlEncode(v))
-        table.insert(msg, '&')
-    end
-    table.remove(msg)
-    return table.concat(msg)
-end
---- HTTP客户端
--- @string method,提交方式"GET" or "POST"
--- @string url,HTTP请求超链接
--- @number timeout,超时时间
--- @param params,table类型,请求发送的查询字符串,通常为键值对表
--- @param data,table类型,正文提交的body,通常为键值对、json或文件对象类似的表
--- @number ctype,Content-Type的类型(可选1,2,3),默认1:"urlencode",2:"json",3:"octet-stream"
--- @string basic,HTTP客户端的authorization basic验证的"username:password"
--- @param headers,table类型,HTTP headers部分
--- @param cert,table类型,此参数可选,默认值为: nil,ssl连接需要的证书配置,只有ssl参数为true时,才参数才有意义,cert格式如下:
--- {
---  caCert = "ca.crt", --CA证书文件(Base64编码 X.509格式),如果存在此参数,则表示客户端会对服务器的证书进行校验;不存在则不校验
---  clientCert = "client.crt", --客户端证书文件(Base64编码 X.509格式),服务器对客户端的证书进行校验时会用到此参数
---  clientKey = "client.key", --客户端私钥文件(Base64编码 X.509格式) clientPassword = "123456", --客户端证书文件密码[可选]
---  }
--- @return string,table,string,正常返回response_code, response_header, response_body
--- @return string,string,错误返回 response_code, error_message
--- @usage local c, h, b = httpv2.request(url, method, headers, body)
--- @usage local r, e  = httpv2.request("http://wrong.url/ ")
-function httpv2.request(method, url, timeout, params, data, ctype, basic, headers, cert, fnc)
-    local response_header, response_code, response_body = {}
-    local _, idx, offset, ssl, auth, https, host, port, path
-    if type(headers) == "string" then
-        local tmp = {}
-        for k, v in string.gmatch(headers, "(.-):%s*(.-)\r\n") do tmp[k] = v end
-        headers = tmp
-    elseif type(headers) ~= "table" then
-        headers = {
-            ['User-Agent'] = 'Mozilla/4.0',
-            ['Accept'] = '*/*',
-            ['Accept-Language'] = 'zh-CN,zh,cn',
-            ['Content-Type'] = 'application/x-www-form-urlencoded',
-            ['Connection'] = 'close',
-        }
-    end
-    -- 处理url的协议头和鉴权
-    _, offset, https = url:find("^(%a+)://")
-    _, idx, auth = url:find("(.-:.-)@", (offset or 0) + 1)
-    offset = idx or offset
-    -- 对host:port整形
-    if url:match("^[^/]+:(%d+)", (offset or 0) + 1) then
-        _, offset, host, port = url:find("^([^/]+):(%d+)", (offset or 0) + 1)
-    elseif url:find("(.-)/", (offset or 0) + 1) then
-        _, offset, host = url:find("(.-)/", (offset or 0) + 1)
-        offset = offset - 1
-    else
-        offset, host = #url, url:sub((offset or 0) + 1, -1)
-    end
-    if not host then return '105', 'ERR_NAME_NOT_RESOLVED' end
-    if not headers.Host then headers["Host"] = host end
-    port = port or (https == "https" and 443 or 80)
-    path = url:sub(offset + 1, -1)
-    path = path == "" and "/" or path
-    -- 处理查询字符串
-    if params then path = path .. '?' .. (type(params) == 'table' and urlencodeTab(params) or params) end
-    -- 处理HTTP协议body部分的数据
-    ctype = ctype or 2
-    headers['Content-Type'] = Content_type[ctype]
-    if ctype == 1 and type(data) == 'table' then
-        data = urlencodeTab(data)
-        headers['Content-Length'] = #data or 0
-    elseif ctype == 2 and data ~= nil then
-        data = type(data) == 'string' and data or (type(data) == 'table' and json.encode(data)) or ""
-        headers['Content-Length'] = #data or 0
-    elseif ctype == 3 and type(data) == 'string' then
-        headers['Content-Length'] = io.fileSize(data) or 0
-    elseif data and type(data) == "string" then
-        headers['Content-Length'] = #data or 0
-    end
-    -- 处理HTTP Basic Authorization 验证
-    if auth then
-        headers['Authorization'] = 'Basic ' .. crypto.base64_encode(auth, #auth)
-    elseif type(basic) == 'string' then
-        headers['Authorization'] = 'Basic ' .. crypto.base64_encode(basic, #basic)
-    end
-    -- 处理headers部分
-    local str = ""
-    for k, v in pairs(headers) do str = str .. k .. ": " .. v .. "\r\n" end
-    -- @LuatOS, 部分特性未支持,所以先过滤一下
-    if ctype == 3 then return '499', 'CTYPE_NOT_SUPPRT' end
-    log.info("httpv2", "all ready", "do tcp connect")
-    -- 发送请求报文
-    while not socket.isReady() do sys.wait(1000) end
-    local c = socket.tcp(https == "https", cert)
-    c:host(host)
-    c:port(port)
-    local connect_topic = "NETC_CONNECT_" .. tostring(c:id())
-    local connect_re = false
-    local resp = {}
-    c:on("connect", function(id, re)
-        connect_re = re
-        sys.publish(connect_topic, re)
-        if not re then
-            c:clean()
-            c:close()
-        end
-    end)
-    c:on("recv", function(id, data)
-        log.debug("httpv2", "recv", "first 30 bytes", string.sub(data, 1, 30))
-        if not update_resp(resp, data) then
-            log.info("httpv2", "close connect for bad resp")
-            c:clean()
-            c:close()
-        end
-    end)
-    if not c:start() then
-        c:clean()
-        c:close()
-        return "499", "SOCKET_CONN_START_ERROR"
-    end
-    sys.waitUntil(connect_topic, 15000)
-    if not connect_re then
-        c:clean()
-        c:close()
-        return "499", "SOCKET_CONN_CONNECT_ERROR"
-    end
-    if ctype ~= 3 then
-        str = method .. ' ' .. path .. ' HTTP/1.0\r\n' .. str .. '\r\n' .. (data and data .. "\r\n" or "")
-        log.info("send http request:", str)
-        if not c:send(str) then
-            c:clean()
-            c:close()
-            return '426', 'SOCKET_SEND_ERROR'
-        end
-    else
-        str = method .. ' ' .. path .. ' HTTP/1.0\r\n' .. str .. '\r\n'
-        log.info("send http request:", str)
-        if not c:send(str) then
-            c:clean()
-            c:close()
-            return '426', 'SOCKET_SEND_ERROR'
-        end
-        local file = io.open(data, 'r')
-        if file then
-            while true do
-                local dat = file:read(8192)
-                if dat == nil then
-                    io.close(file)
-                    break
-                end
-                if not c:send(dat) then
-                    io.close(file)
-                    c:close()
-                    return '426', 'SOCKET_SEND_ERROR'
-                end
-            end
-        end
-        if not c:send('\r\n') then
-            c:close()
-            return '426', 'SOCKET_SEND_ERROR'
-        end
-    end
-
-    -- 等待结束
-    while c:closed() == 0 do
-        sys.waitUntil("NETC_END_" .. c:id(), timeout)
-    end
-    c:clean()
-    c:close()
-    if resp.code then
-        log.info("httpv2", "resp code", resp.code, "body len", #resp.body)
-        return resp.code, resp.headers, resp.body
-    end
-    return 502, {}, ""
-    ------------------------------------ 接收服务器返回消息部分 ------------------------------------
-    --[[
-    local msg, str = {}, ""
-    local r, s = c:recv(timeout)
-    if not r then
-        c:close()
-        return '503', 'SOCKET_RECV_TIMOUT'
-    end
-    -- 处理状态代码
-    _, idx, response_code = s:find("%s(%d+)%s.-\r\n")
-    _, offset = s:find('\r\n\r\n')
-    if not idx or not offset then return '501', 'SERVER_NOT_RESPONSE' end
-    log.info('httpv2.response code:', response_code)
-    -- 处理headers代码
-    for k, v in string.gmatch(s:sub(idx + 1, offset), "(.-):%s*(.-)\r\n") do response_header[k] = v end
-    local len = response_header["Content-Range"] and tonumber(response_header["Content-Range"]:match("/(%d+)")) or tonumber(response_header["Content-Length"]) or 2147483648
-    
-    s = s:sub((offset or 0) + 1, -1)
-    local cnt = #s
-    if tonumber(response_code) == 200 or tonumber(response_code) == 206 then
-        -- 处理body
-        while true do
-            if type(fnc) == "function" then
-                fnc(s, len)
-            else
-                table.insert(msg, s)
-            end
-            if cnt >= len then break end
-            r, s = c:recv(timeout)
-            if not r then break end
-            cnt = cnt + #s
-        end
-        s = table.concat(msg) or ""
-    end
-    c:close()
-    local gzip = response_header["Content-Encoding"] == "gzip"
-    return response_code, response_header, gzip and ((zlib.inflate(s)):read()) or s
-    ]]
-end
-
-return httpv2

+ 0 - 543
script/lib/mqtt.lua

@@ -1,543 +0,0 @@
-
---- 模块功能:MQTT客户端
--- @module mqtt
--- @author openLuat
--- @license MIT
--- @copyright openLuat
--- @release 2017.10.24
-
-local mqtt = {}
-
--- MQTT 指令id
-local CONNECT, CONNACK, PUBLISH, PUBACK, PUBREC, PUBREL, PUBCOMP, SUBSCRIBE, SUBACK, UNSUBSCRIBE, UNSUBACK, PINGREQ, PINGRESP, DISCONNECT = 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14
-local CLIENT_COMMAND_TIMEOUT = 60000
-
-local sys = require "sys"
-local pack = _G.pack
-local string = _G.string
-local encodeLen = mqttcore.encodeLen
---local encodeUTF8 = mqttcore.encodeUTF8
--- local function encodeLen(len)
---     local s = ""
---     local digit
---     repeat
---         digit = len % 128
---         len = (len - digit) / 128
---         if len > 0 then
---             --digit = bit.bor(digit, 0x80)
---             digit = digit | 0x80
---         end
---         s = s .. string.char(digit)
---     until (len <= 0)
---     return s
--- end
-
-local encodeUTF8 = mqttcore.encodeUTF8
--- local function encodeUTF8(s)
---     if not s or #s == 0 then
---         return ""
---     else
---         return pack.pack(">P", s)
---     end
--- end
-
-local packCONNECT = mqttcore.packCONNECT
-
--- local function packCONNECT(clientId, keepAlive, username, password, cleanSession, will, version)
---     local content = pack.pack(">PbbHPAAAA",
---         version == "3.1" and "MQIsdp" or "MQTT",
---         version == "3.1" and 3 or 4,
---         (#username == 0 and 0 or 1) * 128 + (#password == 0 and 0 or 1) * 64 + will.retain * 32 + will.qos * 8 + will.flag * 4 + cleanSession * 2,
---         keepAlive,
---         clientId,
---         encodeUTF8(will.topic),
---         encodeUTF8(will.payload),
---         encodeUTF8(username),
---         encodeUTF8(password))
---     local mydata = pack.pack(">bAA",
---         CONNECT * 16,
---         encodeLen(string.len(content)),
---         content)
---     local tdata = mqttcore.packCONNECT(clientId, keepAlive, username, password, cleanSession, will, version)
---     log.info("mqtt", "true", mydata:toHex())
---     log.info("mqtt", "false", tdata:toHex())
---     return mydata
--- end
-
-local packSUBSCRIBE = mqttcore.packSUBSCRIBE
-
--- local function packSUBSCRIBE(dup, packetId, topics)
---     local header = SUBSCRIBE * 16 + dup * 8 + 2
---     local data = pack.pack(">H", packetId)
---     for topic, qos in pairs(topics) do
---         data = data .. pack.pack(">Pb", topic, qos)
---     end
---     local mydata = pack.pack(">bAA", header, encodeLen(#data), data)
---     log.info("mqtt", "true", mydata:toHex())
---     local tdata = mqttcore.packSUBSCRIBE(dup, packetId, topics)
---     log.info("mqtt", "false", tdata:toHex())
---     return mydata
--- end
-
-local packUNSUBSCRIBE = mqttcore.packUNSUBSCRIBE
--- local function packUNSUBSCRIBE(dup, packetId, topics)
---     local header = UNSUBSCRIBE * 16 + dup * 8 + 2
---     local data = pack.pack(">H", packetId)
---     for k, topic in pairs(topics) do
---         data = data .. pack.pack(">P", topic)
---     end
---     return pack.pack(">bAA", header, encodeLen(#data), data)
--- end
-
-local packPUBLISH = mqttcore.packPUBLISH
-
--- local function packPUBLISH(dup, qos, retain, packetId, topic, payload)
---     local header = PUBLISH * 16 + dup * 8 + qos * 2 + retain
---     local len = 2 + #topic + #payload
---     local mydata = nil
---     if qos > 0 then
---         mydata = pack.pack(">bAPHA", header, encodeLen(len + 2), topic, packetId, payload)
---     else
---         mydata = pack.pack(">bAPA", header, encodeLen(len), topic, payload)
---     end
---     local tdata = mqttcore.packPUBLISH(dup, qos, retain, packetId, topic, payload)
---     log.info("mqtt", "true", mydata:toHex())
---     log.info("mqtt", "false", tdata:toHex())
---     return mydata
--- end
-
-local packACK = mqttcore.packACK
-
--- local function packACK(id, dup, packetId)
---     return pack.pack(">bbH", id * 16 + dup * 8 + (id == PUBREL and 1 or 0) * 2, 0x02, packetId)
--- end
-
-local packZeroData = mqttcore.packZeroData
-
--- local function packZeroData(id, dup, qos, retain)
---     dup = dup or 0
---     qos = qos or 0
---     retain = retain or 0
---     return pack.pack(">bb", id * 16 + dup * 8 + qos * 2 + retain, 0)
--- end
-
-local function unpack(s)
-    if #s < 2 then return end
-    log.debug("mqtt.unpack", #s, string.toHex(string.sub(s, 1, 50)))
-    
-    -- read remaining length
-    local len = 0
-    local multiplier = 1
-    local pos = 2
-    
-    repeat
-        if pos > #s then return end
-        local digit = string.byte(s, pos)
-        len = len + ((digit % 128) * multiplier)
-        multiplier = multiplier * 128
-        pos = pos + 1
-    until digit < 128
-    
-    if #s < len + pos - 1 then return end
-    
-    local header = string.byte(s, 1)
-    
-    --local packet = {id = (header - (header % 16)) / 16, dup = ((header % 16) - ((header % 16) % 8)) / 8, qos = bit.band(header, 0x06) / 2, retain = bit.band(header, 0x01)}
-    local packet = {id = (header - (header % 16)) / 16, dup = ((header % 16) - ((header % 16) % 8)) / 8, qos = (header & 0x06) / 2, retain = (header & 0x01)}
-    local nextpos
-    
-    if packet.id == CONNACK then
-        nextpos, packet.ackFlag, packet.rc = pack.unpack(s, "bb", pos)
-    elseif packet.id == PUBLISH then
-        nextpos, packet.topic = pack.unpack(s, ">P", pos)
-        if packet.qos > 0 then
-            nextpos, packet.packetId = pack.unpack(s, ">H", nextpos)
-        end
-        packet.payload = string.sub(s, nextpos, pos + len - 1)
-    elseif packet.id ~= PINGRESP then
-        if len >= 2 then
-            nextpos, packet.packetId = pack.unpack(s, ">H", pos)
-        else
-            packet.packetId = 0
-        end
-    end
-    
-    return packet, pos + len
-end
-
-local mqttc = {}
-mqttc.__index = mqttc
-
---- 创建一个mqtt client实例
--- @string clientId
--- @number[opt=300] keepAlive 心跳间隔(单位为秒),默认300秒
--- @string[opt=""] username 用户名,用户名为空配置为""或者nil
--- @string[opt=""] password 密码,密码为空配置为""或者nil
--- @number[opt=1] cleanSession 1/0
--- @table[opt=nil] will 遗嘱参数,格式为{qos=, retain=, topic=, payload=}
--- @string[opt="3.1.1"] version MQTT版本号
--- @return table mqttc client实例
--- @usage
--- mqttc = mqtt.client("clientid-123")
--- mqttc = mqtt.client("clientid-123",200)
--- mqttc = mqtt.client("clientid-123",nil,"user","password")
--- mqttc = mqtt.client("clientid-123",nil,"user","password",nil,nil,"3.1")
-function mqtt.client(clientId, keepAlive, username, password, cleanSession, will, version)
-    local o = {}
-    local packetId = 1
-    
-    if will then
-        will.flag = 1
-    else
-        will = {flag = 0, qos = 0, retain = 0, topic = "", payload = ""}
-    end
-    
-    o.clientId = clientId
-    o.keepAlive = keepAlive or 300
-    o.username = username or ""
-    o.password = password or ""
-    o.cleanSession = cleanSession or 1
-    o.version = version or "3.1.1"
-    o.will = will
-    o.commandTimeout = CLIENT_COMMAND_TIMEOUT
-    o.cache = {}-- 接收到的mqtt数据包缓冲
-    o.inbuf = "" -- 未完成的数据缓冲
-    o.connected = false
-    o.getNextPacketId = function()
-        packetId = packetId == 65535 and 1 or (packetId + 1)
-        return packetId
-    end
-    o.lastOTime = 0
-    
-    setmetatable(o, mqttc)
-    
-    return o
-end
-
--- 检测是否需要发送心跳包
-function mqttc:checkKeepAlive()
-    if self.keepAlive == 0 then return true end
-    if os.time() - self.lastOTime >= self.keepAlive then
-        if not self:write(packZeroData(PINGREQ)) then
-            log.info("mqtt.client:", "pingreq send fail")
-            return false
-        end
-    end
-    return true
-end
-
--- 发送mqtt数据
-function mqttc:write(data)
-    log.debug("mqtt.client:write", string.toHex(string.sub(data, 1, 50)))
-    local r = self.io:send(data)
-    if r then self.lastOTime = os.time() end
-    return r
-end
-
--- 接收mqtt数据包
-function mqttc:read(timeout, msg, msgNoResume)
-    if not self:checkKeepAlive() then
-        log.warn("mqtt.read checkKeepAlive fail")
-        return false
-    end
-
-    local topic = "MQTTC_PKG_" .. tostring(self.io:id())
-    local result, data = sys.waitUntil(topic, timeout)
-    --log.info("mqtt.read", result, data)
-    if result then -- 收到topic消息
-        return true, data
-    else
-        if self.io:closed() == 1 then
-            return false
-        else
-            return false, "timeout"
-        end
-    end
-end
-
-local function update_resp(_self, data)
-    if #data > 0 then
-        if #_self.inbuf > 0 then
-            _self.inbuf = _self.inbuf .. data
-        else
-            _self.inbuf = data
-        end
-    end
-    --log.debug("mqttc", "data recv to unpack", _self.inbuf:toHex())
-    local packet, nextpos = unpack(_self.inbuf)
-    if packet then
-        log.info("mqttc", "msg unpack ok", packet.id)
-        _self.inbuf = string.sub(_self.inbuf, nextpos)
-        sys.publish("MQTTC_PKG_" .. tostring(_self.io:id()), packet)
-        if #_self.inbuf > 0 then
-            update_resp(_self, "")
-        end
-    else
-        log.info("mqttc", "data not full")
-    end
-
-    return true
-end
-
--- 等待接收指定的mqtt消息
-function mqttc:waitfor(id, timeout, msg, msgNoResume)
-    for index, packet in ipairs(self.cache) do
-        if packet.id == id then
-            return true, table.remove(self.cache, index)
-        end
-    end
-    
-    while true do
-        local insertCache = true
-        local r, data, param = self:read(timeout, msg, msgNoResume)
-        if r then
-            if data.id == PUBLISH then
-                if data.qos > 0 then
-                    if not self:write(packACK(data.qos == 1 and PUBACK or PUBREC, 0, data.packetId)) then
-                        log.info("mqtt.client:waitfor", "send publish ack failed", data.qos)
-                        return false
-                    end
-                end
-            elseif data.id == PUBREC or data.id == PUBREL then
-                if not self:write(packACK(data.id == PUBREC and PUBREL or PUBCOMP, 0, data.packetId)) then
-                    log.info("mqtt.client:waitfor", "send ack fail", data.id == PUBREC and "PUBREC" or "PUBCOMP")
-                    return false
-                end
-                insertCache = false
-            end
-            
-            if data.id == id then
-                return true, data
-            end
-            if insertCache then table.insert(self.cache, data) end
-        else
-            return false, data, param
-        end
-    end
-end
-
---- 连接mqtt服务器
--- @string host 服务器地址
--- @param port string或者number类型,服务器端口
--- @string[opt="tcp"] transport "tcp"或者"tcp_ssl"
--- @table[opt=nil] cert,table或者nil类型,ssl证书,当transport为"tcp_ssl"时,此参数才有意义。cert格式如下:
--- {
---     caCert = "ca.crt", --CA证书文件(Base64编码 X.509格式),如果存在此参数,则表示客户端会对服务器的证书进行校验;不存在则不校验
---     clientCert = "client.crt", --客户端证书文件(Base64编码 X.509格式),服务器对客户端的证书进行校验时会用到此参数
---     clientKey = "client.key", --客户端私钥文件(Base64编码 X.509格式)
---     clientPassword = "123456", --客户端证书文件密码[可选]
--- }
--- @number timeout, 链接服务器最长超时时间
--- @return result true表示成功,false或者nil表示失败
--- @usage mqttc = mqtt.client("clientid-123", nil, nil, false); mqttc:connect("mqttserver.com", 1883, "tcp", 5)
-function mqttc:connect(host, port, transport, cert, timeout)
-    if self.connected then
-        log.info("mqtt.client:connect", "has connected")
-        return false
-    end
-    
-    if self.io then
-        self.io:clean()
-        self.io:close()
-        self.io = nil
-    end
-    
-    if transport and transport ~= "tcp" and transport ~= "tcp_ssl" then
-        log.info("mqtt.client:connect", "invalid transport", transport)
-        return false
-    end
-
-    self.io = socket.tcp(transport == "tcp_ssl" or type(cert) == "table", cert)
-    self.io:host(host)
-    self.io:port(port)
-    local connect_topic = "NETC_CONNECT_" .. tostring(self.io:id())
-    self.io:on("connect", function(id, re)
-        log.info("mqtt", "connect result", re, re == 1 and "OK" or "FAIL")
-        sys.publish(connect_topic, re == 1)
-        if re == 0 then
-            self.io:clean()
-            self.io:close()
-        end
-    end)
-    self.io:on("recv", function(id, data)
-        if not update_resp(self, data) then
-            log.info("mqtt", "close connect for bad data")
-            self.io:clean()
-            self.io:close()
-        end
-    end)
-    if not self.io:start() then
-        self.io:clean()
-        self.io:close()
-        log.info("mqtt", "fail to start socket thread")
-        return false
-    end
-    --log.info("mqtt", "wait for connect")
-    local result, linked = sys.waitUntil(connect_topic, self.commandTimeout) -- 原本是15秒,在NBIOT下超时的概率不低,改成用commandTimeout
-    if not result then
-        log.info("mqtt", "connect timeout")
-        self.io:clean()
-        self.io:close()
-        return false
-    end
-    if not linked  or self.io:closed() == 1 then
-        log.info("mqtt", "connect fail", result, linked, self.io:closed() == 1)
-        self.io:clean()
-        self.io:close()
-        return false
-    end
-    --log.info("mqtt", "send packCONNECT")
-    if not self:write(packCONNECT(self.clientId, self.keepAlive, self.username, self.password, self.cleanSession, self.will, self.version)) then
-        log.info("mqtt.client:connect", "send fail")
-        return false
-    end
-    --log.info("mqtt", "waitfor CONNACK")
-    local r, packet = self:waitfor(CONNACK, self.commandTimeout, nil, true)
-    if not r or packet.rc ~= 0 then
-        log.info("mqtt.client:connect", "connack error", r and packet.rc or -1)
-        return false
-    end
-    
-    self.connected = true
-    --log.info("mqtt", "connected!~!")
-    
-    return true
-end
-
---- 订阅主题
--- @param topic,string或者table类型,一个主题时为string类型,多个主题时为table类型,主题内容为UTF8编码
--- @param[opt=0] qos,number或者nil,topic为一个主题时,qos为number类型(0/1/2,默认0);topic为多个主题时,qos为nil
--- @return bool true表示成功,false或者nil表示失败
--- @usage
--- mqttc:subscribe("/abc", 0) -- subscribe topic "/abc" with qos = 0
--- mqttc:subscribe({["/topic1"] = 0, ["/topic2"] = 1, ["/topic3"] = 2}) -- subscribe multi topic
-function mqttc:subscribe(topic, qos)
-    if not self.connected then
-        log.info("mqtt.client:subscribe", "not connected")
-        return false
-    end
-    
-    local topics
-    if type(topic) == "string" then
-        topics = {[topic] = qos and qos or 0}
-    else
-        topics = topic
-    end
-    
-    if not self:write(packSUBSCRIBE(0, self.getNextPacketId(), topics)) then
-        log.info("mqtt.client:subscribe", "send failed")
-        return false
-    end
-    
-    if not self:waitfor(SUBACK, self.commandTimeout, nil, true) then
-        log.info("mqtt.client:subscribe", "wait ack failed")
-        return false
-    end
-    
-    return true
-end
-
---- 取消订阅主题
--- @param topic,string或者table类型,一个主题时为string类型,多个主题时为table类型,主题内容为UTF8编码
--- @return bool true表示成功,false或者nil表示失败
--- @usage
--- mqttc:unsubscribe("/abc") -- unsubscribe topic "/abc"
--- mqttc:unsubscribe({"/topic1", "/topic2", "/topic3"}) -- unsubscribe multi topic
-function mqttc:unsubscribe(topic)
-    if not self.connected then
-        log.info("mqtt.client:unsubscribe", "not connected")
-        return false
-    end
-    
-    local topics
-    if type(topic) == "string" then
-        topics = {topic}
-    else
-        topics = topic
-    end
-    
-    if not self:write(packUNSUBSCRIBE(0, self.getNextPacketId(), topics)) then
-        log.info("mqtt.client:unsubscribe", "send failed")
-        return false
-    end
-    
-    if not self:waitfor(UNSUBACK, self.commandTimeout, nil, true) then
-        log.info("mqtt.client:unsubscribe", "wait ack failed")
-        return false
-    end
-    
-    return true
-end
-
---- 发布一条消息
--- @string topic UTF8编码的字符串
--- @string payload 用户自己控制payload的编码,mqtt.lua不会对payload做任何编码转换
--- @number[opt=0] qos 0/1/2, default 0
--- @number[opt=0] retain 0或者1
--- @return bool 发布成功返回true,失败返回false
--- @usage
--- mqttc = mqtt.client("clientid-123", nil, nil, false)
--- mqttc:connect("mqttserver.com", 1883, "tcp")
--- mqttc:publish("/topic", "publish from luat mqtt client", 0)
-function mqttc:publish(topic, payload, qos, retain)
-    if not self.connected then
-        log.info("mqtt.client:publish", "not connected")
-        return false
-    end
-    
-    qos = qos or 0
-    retain = retain or 0
-    
-    if not self:write(packPUBLISH(0, qos, retain, qos > 0 and self.getNextPacketId() or 0, topic, payload)) then
-        log.info("mqtt.client:publish", "socket send failed")
-        return false
-    end
-    
-    if qos == 0 then return true end
-    
-    if not self:waitfor(qos == 1 and PUBACK or PUBCOMP, self.commandTimeout, nil, true) then
-        log.warn("mqtt.client:publish", "wait ack timeout")
-        return false
-    end
-    
-    return true
-end
-
---- 接收消息
--- @number timeout 接收超时时间,单位毫秒
--- @string[opt=nil] msg 可选参数,控制socket所在的线程退出recv阻塞状态
--- @return result 数据接收结果,true表示成功,false表示失败
--- @return data 如果result为true,表示服务器发过来的包;如果result为false,表示错误信息,超时失败时为"timeout"
--- @return param msg控制退出时,返回msg的字符串
--- @usage
--- true, packet = mqttc:receive(2000)
--- false, error_message = mqttc:receive(2000)
--- false, msg, para = mqttc:receive(2000)
-function mqttc:receive(timeout, msg)
-    if not self.connected then
-        log.info("mqtt.client:receive", "not connected")
-        return false
-    end
-    
-    return self:waitfor(PUBLISH, timeout, msg)
-end
-
---- 断开与服务器的连接
--- @return nil
--- @usage
--- mqttc = mqtt.client("clientid-123", nil, nil, false)
--- mqttc:connect("mqttserver.com", 1883, "tcp")
--- process data
--- mqttc:disconnect()
-function mqttc:disconnect()
-    if self.io then
-        if self.connected then self:write(packZeroData(DISCONNECT)) end
-        self.io:close()
-        self.io = nil
-    end
-    self.cache = {}
-    self.inbuf = ""
-    self.connected = false
-end
-
-return mqtt

+ 0 - 384
script/lib/sys.lua

@@ -1,384 +0,0 @@
---- 模块功能:Luat协程调度框架
---module(..., package.seeall)
-
-local sys = {}
-
-local table = _G.table
-local unpack = table.unpack
-local rtos = _G.rtos
-local coroutine = _G.coroutine
-local log = _G.log
-
--- lib脚本版本号,只要lib中的任何一个脚本做了修改,都需要更新此版本号
-SCRIPT_LIB_VER = "1.0.0"
-
--- TaskID最大值
-local TASK_TIMER_ID_MAX = 0x1FFFFF
--- msgId 最大值(请勿修改否则会发生msgId碰撞的危险)
-local MSG_TIMER_ID_MAX = 0x7FFFFF
-
--- 任务定时器id
-local taskTimerId = 0
--- 消息定时器id
-local msgId = TASK_TIMER_ID_MAX
--- 定时器id表
-local timerPool = {}
-local taskTimerPool = {}
---消息定时器参数表
-local para = {}
---定时器是否循环表
-local loop = {}
---lua脚本运行出错时,是否回退为本地烧写的版本
-local sRollBack = true
-
-_G.COROUTINE_ERROR_ROLL_BACK = true
-_G.COROUTINE_ERROR_RESTART = true
-
--- 对coroutine.resume加一个修饰器用于捕获协程错误
-local rawcoresume = coroutine.resume
-sys.coresume = function(...)
-    function wrapper(co,...)
-        local arg = {...}
-        if not arg[1] then
-            local traceBack = debug.traceback(co)
-            traceBack = (traceBack and traceBack~="") and (arg[2].."\r\n"..traceBack) or arg[2]
-            log.error("coroutine.resume",traceBack)
-            if errDump and type(errDump.appendErr)=="function" then
-                errDump.appendErr(traceBack)
-            end
-            if _G.COROUTINE_ERROR_ROLL_BACK then
-                sys.timerStart(assert,500,false,traceBack)
-            elseif _G.COROUTINE_ERROR_RESTART then
-                rtos.reboot()
-            end
-        end
-        return ...
-    end
-    local arg = {...}
-    return wrapper(arg[1], rawcoresume(...))
-end
-
---- Task任务延时函数,只能用于任务函数中
--- @number ms  整数,最大等待126322567毫秒
--- @return 定时结束返回nil,被其他线程唤起返回调用线程传入的参数
--- @usage sys.wait(30)
-function sys.wait(ms)
-    -- 参数检测,参数不能为负值
-    --assert(ms > 0, "The wait time cannot be negative!")
-    -- 选一个未使用的定时器ID给该任务线程
-    if taskTimerId >= TASK_TIMER_ID_MAX then taskTimerId = 0 end
-    taskTimerId = taskTimerId + 1
-    local timerid = taskTimerId
-    taskTimerPool[coroutine.running()] = timerid
-    timerPool[timerid] = coroutine.running()
-    -- 调用core的rtos定时器
-    if 1 ~= rtos.timer_start(timerid, ms) then log.debug("rtos.timer_start error") return end
-    -- 挂起调用的任务线程
-    local message = {coroutine.yield()}
-    if #message ~= 0 then
-        rtos.timer_stop(timerid)
-        taskTimerPool[coroutine.running()] = nil
-        timerPool[timerid] = nil
-        return unpack(message)
-    end
-end
-
---- Task任务的条件等待函数(包括事件消息和定时器消息等条件),只能用于任务函数中。
--- @param id 消息ID
--- @number ms 等待超时时间,单位ms,最大等待126322567毫秒
--- @return result 接收到消息返回true,超时返回false
--- @return data 接收到消息返回消息参数
--- @usage result, data = sys.waitUntil("SIM_IND", 120000)
-function sys.waitUntil(id, ms)
-    sys.subscribe(id, coroutine.running())
-    local message = ms and {sys.wait(ms)} or {coroutine.yield()}
-    sys.unsubscribe(id, coroutine.running())
-    return message[1] ~= nil, unpack(message, 2, #message)
-end
-
---- Task任务的条件等待函数扩展(包括事件消息和定时器消息等条件),只能用于任务函数中。
--- @param id 消息ID
--- @number ms 等待超时时间,单位ms,最大等待126322567毫秒
--- @return message 接收到消息返回message,超时返回false
--- @return data 接收到消息返回消息参数
--- @usage result, data = sys.waitUntilExt("SIM_IND", 120000)
-function sys.waitUntilExt(id, ms)
-    sys.subscribe(id, coroutine.running())
-    local message = ms and {sys.wait(ms)} or {coroutine.yield()}
-    sys.unsubscribe(id, coroutine.running())
-    if message[1] ~= nil then return unpack(message) end
-    return false
-end
-
---- 创建一个任务线程,在模块最末行调用该函数并注册模块中的任务函数,main.lua导入该模块即可
--- @param fun 任务函数名,用于resume唤醒时调用
--- @param ... 任务函数fun的可变参数
--- @return co  返回该任务的线程号
--- @usage sys.taskInit(task1,'a','b')
-function sys.taskInit(fun, ...)
-    local co = coroutine.create(fun)
-    sys.coresume(co, ...)
-    return co
-end
-
------------------------------------------- rtos消息回调处理部分 ------------------------------------------
---[[
-函数名:cmpTable
-功能  :比较两个table的内容是否相同,注意:table中不能再包含table
-参数  :
-t1:第一个table
-t2:第二个table
-返回值:相同返回true,否则false
-]]
-local function cmpTable(t1, t2)
-    if not t2 then return #t1 == 0 end
-    if #t1 == #t2 then
-        for i = 1, #t1 do
-            if unpack(t1, i, i) ~= unpack(t2, i, i) then
-                return false
-            end
-        end
-        return true
-    end
-    return false
-end
-
---- 关闭定时器
--- @param val 值为number时,识别为定时器ID,值为回调函数时,需要传参数
--- @param ... val值为函数时,函数的可变参数
--- @return 无
--- @usage timerStop(1)
-function sys.timerStop(val, ...)
-    -- val 为定时器ID
-    if type(val) == 'number' then
-        timerPool[val], para[val] = nil
-        rtos.timer_stop(val)
-    else
-        for k, v in pairs(timerPool) do
-            -- 回调函数相同
-            if type(v) == 'table' and v.cb == val or v == val then
-                -- 可变参数相同
-                if cmpTable({...}, para[k]) then
-                    rtos.timer_stop(k)
-                    timerPool[k], para[k] = nil
-                    break
-                end
-            end
-        end
-    end
-end
-
---- 关闭同一回调函数的所有定时器
--- @param fnc 定时器回调函数
--- @return 无
--- @usage timerStopAll(cbFnc)
-function sys.timerStopAll(fnc)
-    for k, v in pairs(timerPool) do
-        if type(v) == "table" and v.cb == fnc or v == fnc then
-            rtos.timer_stop(k)
-            timerPool[k], para[k] = nil
-        end
-    end
-end
-
-function sys.timerAdvStart(fnc, ms, _repeat, ...)
-    --回调函数和时长检测
-    --assert(fnc ~= nil, "sys.timerStart(first param) is nil !")
-    --assert(ms > 0, "sys.timerStart(Second parameter) is <= zero !")
-    -- 关闭完全相同的定时器
-    local arg = {...}
-    if #arg == 0 then
-        sys.timerStop(fnc)
-    else
-        sys.timerStop(fnc, ...)
-    end
-    -- 为定时器申请ID,ID值 1-20 留给任务,20-30留给消息专用定时器
-    while true do
-        if msgId >= MSG_TIMER_ID_MAX then msgId = TASK_TIMER_ID_MAX end
-        msgId = msgId + 1
-        if timerPool[msgId] == nil then
-            timerPool[msgId] = fnc
-            break
-        end
-    end
-    --调用底层接口启动定时器
-    if rtos.timer_start(msgId, ms, _repeat) ~= 1 then return end
-    --如果存在可变参数,在定时器参数表中保存参数
-    if #arg ~= 0 then
-        para[msgId] = arg
-    end
-    --返回定时器id
-    return msgId
-end
-
---- 开启一个定时器
--- @param fnc 定时器回调函数
--- @number ms 整数,最大定时126322567毫秒
--- @param ... 可变参数 fnc的参数
--- @return number 定时器ID,如果失败,返回nil
-function sys.timerStart(fnc, ms, ...)
-    return sys.timerAdvStart(fnc, ms, 0, ...)
-end
-
---- 开启一个循环定时器
--- @param fnc 定时器回调函数
--- @number ms 整数,最大定时126322567毫秒
--- @param ... 可变参数 fnc的参数
--- @return number 定时器ID,如果失败,返回nil
-function sys.timerLoopStart(fnc, ms, ...)
-    return sys.timerAdvStart(fnc, ms, -1, ...)
-end
-
---- 判断某个定时器是否处于开启状态
--- @param val 有两种形式
---一种是开启定时器时返回的定时器id,此形式时不需要再传入可变参数...就能唯一标记一个定时器
---另一种是开启定时器时的回调函数,此形式时必须再传入可变参数...才能唯一标记一个定时器
--- @param ... 可变参数
--- @return number 开启状态返回true,否则nil
-function sys.timerIsActive(val, ...)
-    if type(val) == "number" then
-        return timerPool[val]
-    else
-        for k, v in pairs(timerPool) do
-            if v == val then
-                if cmpTable({...}, para[k]) then return true end
-            end
-        end
-    end
-end
-
-
------------------------------------------- LUA应用消息订阅/发布接口 ------------------------------------------
--- 订阅者列表
-local subscribers = {}
---内部消息队列
-local messageQueue = {}
-
---- 订阅消息
--- @param id 消息id
--- @param callback 消息回调处理
--- @usage subscribe("NET_STATUS_IND", callback)
-function sys.subscribe(id, callback)
-    if not id or type(id) == "boolean" or (type(callback) ~= "function" and type(callback) ~= "thread") then
-        log.warn("warning: sys.subscribe invalid parameter", id, callback)
-        return
-    end
-    if not subscribers[id] then subscribers[id] = {} end
-    subscribers[id][callback] = true
-end
---- 取消订阅消息
--- @param id 消息id
--- @param callback 消息回调处理
--- @usage unsubscribe("NET_STATUS_IND", callback)
-function sys.unsubscribe(id, callback)
-    if not id or type(id) == "boolean" or (type(callback) ~= "function" and type(callback) ~= "thread") then
-        log.warn("warning: sys.unsubscribe invalid parameter", id, callback)
-        return
-    end
-    if subscribers[id] then subscribers[id][callback] = nil end
-    -- 判断消息是否无其他订阅
-    for k, _ in pairs(subscribers[id]) do
-        return
-    end
-    subscribers[id] = nil
-end
-
---- 发布内部消息,存储在内部消息队列中
--- @param ... 可变参数,用户自定义
--- @return 无
--- @usage publish("NET_STATUS_IND")
-function sys.publish(...)
-    table.insert(messageQueue, {...})
-end
-
--- 分发消息
-local function dispatch()
-    while true do
-        if #messageQueue == 0 then
-            break
-        end
-        local message = table.remove(messageQueue, 1)
-        if subscribers[message[1]] then
-            for callback, _ in pairs(subscribers[message[1]]) do
-                if type(callback) == "function" then
-                    callback(unpack(message, 2, #message))
-                elseif type(callback) == "thread" then
-                    sys.coresume(callback, unpack(message))
-                end
-            end
-        end
-    end
-end
-
--- rtos消息回调
---local handlers = {}
---setmetatable(handlers, {__index = function() return function() end end, })
-
---- 注册rtos消息回调处理函数
--- @number id 消息类型id
--- @param handler 消息处理函数
--- @return 无
--- @usage rtos.on(rtos.MSG_KEYPAD, function(param) handle keypad message end)
---function sys.on(id, handler)
---    handlers[id] = handler
---end
-
------------------------------------------- Luat 主调度框架  ------------------------------------------
-local function safeRun()
-    -- 分发内部消息
-    dispatch()
-    -- 阻塞读取外部消息
-    local msg, param, exparam = rtos.receive(rtos.INF_TIMEOUT)
-    --log.info("sys", msg, param, exparam, tableNSize(timerPool), tableNSize(para), tableNSize(taskTimerPool), tableNSize(subscribers))
-    -- 空消息?
-    if not msg or msg == 0 then
-        -- 无任何操作
-    -- 判断是否为定时器消息,并且消息是否注册
-    elseif msg == rtos.MSG_TIMER and timerPool[param] then
-        if param < TASK_TIMER_ID_MAX then
-            local taskId = timerPool[param]
-            timerPool[param] = nil
-            if taskTimerPool[taskId] == param then
-                taskTimerPool[taskId] = nil
-                sys.coresume(taskId)
-            end
-        else
-            local cb = timerPool[param]
-            --如果不是循环定时器,从定时器id表中删除此定时器
-            if exparam == 0 then timerPool[param] = nil end
-            if para[param] ~= nil then
-                cb(unpack(para[param]))
-                if exparam == 0 then para[param] = nil end
-            else
-                cb()
-            end
-            --如果是循环定时器,继续启动此定时器
-            --if loop[param] then rtos.timer_start(param, loop[param]) end
-        end
-    --其他消息(音频消息、充电管理消息、按键消息等)
-    --elseif type(msg) == "number" then
-    --    handlers[msg](param, exparam)
-    --else
-    --    handlers[msg.id](msg)
-    end
-end
-
---- run()从底层获取core消息并及时处理相关消息,查询定时器并调度各注册成功的任务线程运行和挂起
--- @return 无
--- @usage sys.run()
-function sys.run()
-    local result, err
-    while true do
-        --if sRollBack then
-            safeRun()
-        --else
-        --    result, err = pcall(safeRun)
-        --    if not result then rtos.restart(err) end
-        --end
-    end
-end
-
-_G.sys_pub = sys.publish
-
-return sys
-----------------------------