Просмотр исходного кода

Merge branch 'master' of https://gitee.com/openLuat/LuatOS

chenxuuu 1 год назад
Родитель
Сommit
df9920e563

+ 1 - 1
components/network/libemqtt/luat_mqtt.h

@@ -15,7 +15,7 @@
 
 #ifndef MQTT_RECV_BUF_LEN_MAX
 #if defined(CHIP_EC618) || defined(CHIP_EC718)|| defined(CHIP_EC716)
-#define MQTT_RECV_BUF_LEN_MAX (80*1024) ///< MQTT 接收BUFF大小
+#define MQTT_RECV_BUF_LEN_MAX (32*1024) ///< MQTT 接收BUFF大小
 #else
 #define MQTT_RECV_BUF_LEN_MAX 4096 ///< MQTT 接收BUFF大小
 #endif

+ 14 - 338
demo/air780eg_gnsstest/main.lua

@@ -1,357 +1,33 @@
 -- LuaTools需要PROJECT和VERSION这两个信息
 PROJECT = "gnsstest"
 VERSION = "1.0.1"
+PRODUCT_KEY = "" -- 基站定位需要用到
 
 --[[
 本demo需要很多流量!!!
 注意: 室内无信号!! 无法定位!!!
-
-本demo对应的网页是 https://iot.openluat.com/iot/device-gnss
 ]]
 
 -- sys库是标配
-local sys = require("sys")
+_G.sys = require("sys")
 require("sysplus")
 
--- Air780E的AT固件默认会为开机键防抖, 导致部分用户刷机很麻烦
-if rtos.bsp() == "EC618" and pm and pm.PWK_MODE then
-    pm.power(pm.PWK_MODE, false)
-end
-
-local gps_uart_id = 2
-local mqttc = nil
-
--- libgnss库初始化
-libgnss.clear() -- 清空数据,兼初始化
-
--- LED和ADC初始化
-LED_GNSS = 24
-LED_VBAT = 26
-gpio.setup(LED_GNSS, 0) -- GNSS定位成功灯
-gpio.setup(LED_VBAT, 0) -- 低电压警告灯
-adc.open(adc.CH_VBAT)
-adc.open(adc.CH_CPU)
-
--- 串口初始化
-uart.setup(gps_uart_id, 115200)
-
--- TODO 做成agnss.lua
-function exec_agnss()
-    local url = "http://download.openluat.com/9501-xingli/HXXT_GPS_BDS_AGNSS_DATA.dat"
-    local dat_done = false
-    sys.waitUntil("NTP_UPDATE", 1000)
-    if io.fileSize("/6228.bin") > 1024 then
-        local date = os.date("!*t")
-        log.info("当前系统时间", os.date())
-        if date.year < 2023 then
-            date = os.date("!*t")
-        end
-        if date.year > 2022 then
-            local tm = io.readFile("/6226_tm")
-            if tm then
-                local t = tonumber(tm)
-                if t and (os.time() - t < 3600*2) then
-                    log.info("agnss", "重用星历文件")
-                    local body = io.readFile("/6228.bin")
-                    for offset = 1, #body, 512 do
-                        uart.write(gps_uart_id, body:sub(offset, offset + 511))
-                        sys.wait(100)
-                    end
-                    dat_done = true
-                else
-                    log.info("星历过期了")
-                end
-            else
-                log.info("星历时间有问题")
-            end
-        else
-            log.info("时间有问题")
-        end
-    end
-    if http and not dat_done then
-        -- AGNSS 已调通
-        while 1 do
-            local code, headers, body = http.request("GET", url).wait()
-            log.info("gnss", "AGNSS", code, body and #body or 0)
-            if code == 200 and body and #body > 1024 then
-                for offset = 1, #body, 512 do
-                    log.info("gnss", "AGNSS", "write >>>", #body:sub(offset, offset + 511))
-                    uart.write(gps_uart_id, body:sub(offset, offset + 511))
-                    -- sys.waitUntil("UART2_SEND", 100)
-                    sys.wait(100) -- 等100ms反而更成功
-                end
-                -- sys.waitUntil("UART2_SEND", 1000)
-                io.writeFile("/6228.bin", body)
-                local date = os.date("!*t")
-                if date.year > 2022 then
-                    io.writeFile("/6226_tm", tostring(os.time()))
-                end
-                break
-            end
-            sys.wait(60 * 1000)
-        end
-    end
-    sys.wait(20)
-    -- "$AIDTIME,year,month,day,hour,minute,second,millisecond"
-    local date = os.date("!*t")
-    if date.year > 2022 then
-        local str = string.format("$AIDTIME,%d,%d,%d,%d,%d,%d,000", date["year"], date["month"], date["day"],
-            date["hour"], date["min"], date["sec"])
-        log.info("gnss", str)
-        uart.write(gps_uart_id, str .. "\r\n")
-        sys.wait(20)
-    end
-    -- 读取之前的位置信息
-    local gnssloc = io.readFile("/gnssloc")
-    if gnssloc then
-        str = "$AIDPOS," .. gnssloc
-        log.info("POS", str)
-        uart.write(gps_uart_id, str .. "\r\n")
-        str = nil
-        gnssloc = nil
-    else
-        -- TODO 发起基站定位
-    end
-end
-
--- function upload_stat()
---     -- if mqttc == nil or not mqttc:ready() then return end
---     local stat = {
---         csq = mobile.csq(),
---         rssi = mobile.rssi(),
---         rsrq = mobile.rsrq(),
---         rsrp = mobile.rsrp(),
---         -- iccid = mobile.iccid(),
---         snr = mobile.snr(),
---         vbat = adc.get(adc.CH_VBAT),
---         temp = adc.get(adc.CH_CPU),
---         memsys = {rtos.meminfo("sys")},
---         memlua = {rtos.meminfo()},
---         fixed = libgnss.isFix()
---     }
---     sys.publish("uplink", "/gnss/" .. mobile.imei() .. "/up/stat", (json.encode(stat)), 1)
--- end
-
--- sys.timerLoopStart(upload_stat, 60 * 1000)
-
-sys.taskInit(function()
-    sys.waitUntil("IP_READY")
-    -- Air780EG默认波特率是115200
-    local nmea_topic = "/gnss/" .. mobile.imei() .. "/up/nmea"
-    log.info("GPS", "start")
-    pm.power(pm.GPS, true)
-    libgnss.on("raw", function(data)
-        sys.publish("uplink", nmea_topic, data, 1)
-    end)
-    -- 调试日志,可选
-    libgnss.debug(true)
-    sys.wait(200) -- GPNSS芯片启动需要时间,大概150ms
-    -- 显示串口配置
-    -- uart.write(gps_uart_id, "$CFGPRT,1\r\n")
-    -- sys.wait(20)
-
-    -- uart.write(gps_uart_id, "$CFGSYS,H01\r\n") -- GPS L1+SBAS+QZSS 联合定位
-    -- sys.wait(20)
-    -- uart.write(gps_uart_id, "$CFGSYS,H10\r\n") -- 单北斗 BDS B1
-    -- sys.wait(20)
-    -- uart.write(gps_uart_id, "$CFGSYS,H01\r\n") -- GPS L1+BDS B1+QZSS 联合定位,默认
-    -- sys.wait(20)
-
-    -- 增加显示的语句,可选
-    uart.write(gps_uart_id, "$CFGMSG,0,1,1\r\n") -- GLL
-    sys.wait(20)
-    uart.write(gps_uart_id, "$CFGMSG,0,5,1\r\n") -- VTG
-    sys.wait(20)
-    uart.write(gps_uart_id, "$CFGMSG,0,6,1\r\n") -- ZDA
-    sys.wait(20)
-    
-    -- 绑定uart,底层自动处理GNSS数据
-    -- 这里延后到设置命令发送完成后才开始处理数据,之前的数据就不上传了
-    libgnss.bind(gps_uart_id)
-    log.debug("提醒", "室内无GNSS信号,定位不会成功, 要到空旷的室外,起码要看得到天空")
-    exec_agnss()
-end)
-
-sys.taskInit(function()
-    while 1 do
-        sys.wait(5000)
-        -- 6228CI, 查询产品信息, 可选
-        -- uart.write(gps_uart_id, "$PDTINFO,*62\r\n")
-        -- uart.write(gps_uart_id, "$AIDINFO\r\n")
-        -- sys.wait(100)
-
-        -- uart.write(gps_uart_id, "$CFGSYS\r\n")
-        -- uart.write(gps_uart_id, "$CFGMSG,6,4\r\n")
-        log.info("RMC", json.encode(libgnss.getRmc(2) or {}, "7f"))
-        log.info("INT", libgnss.getIntLocation())
-        -- log.info("GGA", libgnss.getGga(3))
-        -- log.info("GLL", json.encode(libgnss.getGll(2) or {}, "7f"))
-        -- log.info("GSA", json.encode(libgnss.getGsa(2) or {}, "7f"))
-        -- log.info("GSV", json.encode(libgnss.getGsv(2) or {}, "7f"))
-        -- log.info("VTG", json.encode(libgnss.getVtg(2) or {}, "7f"))
-        -- log.info("ZDA", json.encode(libgnss.getZda(2) or {}, "7f"))
-        -- log.info("date", os.date())
-        log.info("sys", rtos.meminfo("sys"))
-        log.info("lua", rtos.meminfo("lua"))
-    end
-end)
-
--- 订阅GNSS状态编码
-sys.subscribe("GNSS_STATE", function(event, ticks)
-    -- event取值有 
-    -- FIXED 定位成功
-    -- LOSE  定位丢失
-    -- ticks是事件发生的时间,一般可以忽略
-    local onoff = libgnss.isFix() and 1 or 0
-    log.info("GNSS", "LED", onoff)
-    gpio.set(LED_GNSS, onoff)
-    log.info("gnss", "state", event, ticks)
-    if event == "FIXED" then
-        local locStr = libgnss.locStr()
-        log.info("gnss", "locStr", locStr)
-        if locStr then
-            io.writeFile("/gnssloc", locStr)
-        end
-    end
-end)
-
--- mqtt 上传任务
-sys.taskInit(function()
-    -- sys.waitUntil("IP_READY", 15000)
-    mqttc = mqtt.create(nil, "lbsmqtt.airm2m.com", 1886) -- mqtt客户端创建
-
-    mqttc:auth(mobile.imei(), mobile.imei(), mobile.muid()) -- mqtt三元组配置
-    log.info("mqtt", mobile.imei(), mobile.imei(), mobile.muid())
-    mqttc:keepalive(30) -- 默认值240s
-    mqttc:autoreconn(true, 3000) -- 自动重连机制
-
-    mqttc:on(function(mqtt_client, event, data, payload) -- mqtt回调注册
-        -- 用户自定义代码,按event处理
-        -- log.info("mqtt", "event", event, mqtt_client, data, payload)
-        if event == "conack" then -- mqtt成功完成鉴权后的消息
-            sys.publish("mqtt_conack") -- 小写字母的topic均为自定义topic
-            -- 订阅不是必须的,但一般会有
-            mqtt_client:subscribe("/gnss/" .. mobile.imei() .. "/down/#")
-        elseif event == "recv" then -- 服务器下发的数据
-            log.info("mqtt", "downlink", "topic", data, "payload", payload)
-            local dl = json.decode(data)
-            if dl then
-                -- 检测命令
-                if dl.cmd then
-                    -- 直接写uart
-                    if dl.cmd == "uart" and dl.data then
-                        uart.write(gps_uart_id, dl.data)
-                    -- 重启命令
-                    elseif dl.cmd == "reboot" then
-                        rtos.reboot()
-                    elseif dl.cmd == "stat" then
-                        upload_stat()
-                    end
-                end
-            end
-        elseif event == "sent" then -- publish成功后的事件
-            log.info("mqtt", "sent", "pkgid", data)
-        end
-    end)
-
-    -- 发起连接之后,mqtt库会自动维护链接,若连接断开,默认会自动重连
-    mqttc:connect()
-    -- sys.waitUntil("mqtt_conack")
-    -- log.info("mqtt连接成功")
-    sys.timerStart(upload_stat, 3000) -- 一秒后主动上传一次
-    while true do
-        sys.wait(60*1000)
-    end
-    mqttc:close()
-    mqttc = nil
-end)
-
-sys.taskInit(function()
-    while 1 do
-        sys.wait(3600 * 1000) -- 一小时检查一次
-        local fixed, time_fixed = libgnss.isFix()
-        if not fixed then
-            exec_agnss()
-        end
-    end
-end)
-
-sys.timerLoopStart(upload_stat, 60000)
-
-sys.taskInit(function()
-    local msgs = {}
-    while 1 do
-        local ret, topic, data, qos = sys.waitUntil("uplink", 30000)
-        if ret then
-            if topic == "close" then
-                break
-            end
-            log.info("mqtt", "publish", "topic", topic)
-            -- if #data > 512 then
-            --     local start = mcu.ticks()
-            --     local cdata = miniz.compress(data)
-            --     local endt = mcu.ticks() - start
-            --     if cdata then
-            --         log.info("miniz", #data, #cdata, endt)
-            --     end
-            -- end
-            if mqttc:ready() then
-                local tmp = msgs
-                if #tmp > 0 then
-                    log.info("mqtt", "ready, send buff", #tmp)
-                    msgs = {}
-                    for k, msg in pairs(tmp) do
-                        mqttc:publish(msg.topic, msg.data, 0)
-                    end
-                end
-                mqttc:publish(topic, data, qos)
-            else
-                log.info("mqtt", "not ready, insert into buff")
-                if #msgs > 60 then
-                    table.remove(msgs, 1)
-                end
-                table.insert(msgs, {
-                    topic = topic,
-                    data = data
-                })
-            end
-        end
-    end
-end)
+_G.gps_uart_id = 2
 
--- 适配GNSS测试设备的GPIO
-sys.taskInit(function()
-    while 1 do
-        local vbat = adc.get(adc.CH_VBAT)
-        log.info("vbat", vbat)
-        if vbat < 3400 then
-            gpio.set(LED_VBAT, 1)
-            sys.wait(100)
-            gpio.set(LED_VBAT, 0)
-            sys.wait(900)
-        else
-            sys.wait(1000)
-        end
-    end
-end)
+-- 演示GNSS定位, 含AGPS
+require "testGnss"
 
-sys.subscribe("NTP_UPDATE", function()
-    if not libgnss.isFix() then
-        -- "$AIDTIME,year,month,day,hour,minute,second,millisecond"
-        local date = os.date("!*t")
-        local str = string.format("$AIDTIME,%d,%d,%d,%d,%d,%d,000", 
-                             date["year"], date["month"], date["day"], date["hour"], date["min"], date["sec"])
-        log.info("gnss", str)
-        uart.write(gps_uart_id, str .. "\r\n")
-    end
-end)
+-- 演示上报到MQTT服务器 对应的网页是 https://iot.openluat.com/iot/device-gnss
+-- require "testMqtt"
 
-if socket.sntp then
-    sys.subscribe("IP_READY", function()
-        socket.sntp()
-    end)
-end
+-- 演示定位成功后切换GPIO高低电平
+-- require "testGpio"
 
+-- 本TCP演示是连接到 gps.nutz.cn 19002 端口, irtu的自定义包格式
+-- 网页是 https://gps.nutz.cn/ 输入IMEI号可参考当前位置
+-- 微信小程序是 irtu寻物, 点击IMEI号, 扫描模块的二维码可查看当前位置和历史轨迹
+-- 服务器源码地址: https://gitee.com/wendal/irtu-gps
+require "testTcp"
 
 -- 用户代码已结束---------------------------------------------
 -- 结尾总是这一句

+ 50 - 0
demo/air780eg_gnsstest/testGnss.lua

@@ -0,0 +1,50 @@
+
+-- libgnss库初始化
+libgnss.clear() -- 清空数据,兼初始化
+
+-- LED和ADC初始化
+LED_GNSS = 24
+gpio.setup(LED_GNSS, 0) -- GNSS定位成功灯
+
+local gnss = require("uc6228")
+
+sys.taskInit(function()
+    log.debug("提醒", "室内无GNSS信号,定位不会成功, 要到空旷的室外,起码要看得到天空")
+    gnss.setup({
+        uart_id=2,
+        uart_forward = uart.VUART_0, -- 转发到虚拟串口,方便对接GnssToolKit3
+        debug=true
+    })
+    pm.power(pm.GPS, true)
+    gnss.start()
+    gnss.agps()
+end)
+
+sys.taskInit(function()
+    while 1 do
+        sys.wait(5000)
+        -- log.info("RMC", json.encode(libgnss.getRmc(2) or {}, "7f"))
+        -- log.info("INT", libgnss.getIntLocation())
+        -- log.info("GGA", libgnss.getGga(3))
+        -- log.info("GLL", json.encode(libgnss.getGll(2) or {}, "7f"))
+        -- log.info("GSA", json.encode(libgnss.getGsa(1) or {}, "7f"))
+        -- log.info("GSV", json.encode(libgnss.getGsv(2) or {}, "7f"))
+        -- log.info("VTG", json.encode(libgnss.getVtg(2) or {}, "7f"))
+        -- log.info("ZDA", json.encode(libgnss.getZda(2) or {}, "7f"))
+        -- log.info("date", os.date())
+        -- log.info("sys", rtos.meminfo("sys"))
+        -- log.info("lua", rtos.meminfo("lua"))
+    end
+end)
+
+-- 订阅GNSS状态编码
+sys.subscribe("GNSS_STATE", function(event, ticks)
+    -- event取值有 
+    -- FIXED 定位成功
+    -- LOSE  定位丢失
+    -- ticks是事件发生的时间,一般可以忽略
+    local onoff = libgnss.isFix() and 1 or 0
+    log.info("GNSS", "LED", onoff)
+    gpio.set(LED_GNSS, onoff)
+end)
+

+ 23 - 0
demo/air780eg_gnsstest/testGpio.lua

@@ -0,0 +1,23 @@
+
+
+LED_VBAT = 26
+gpio.setup(LED_VBAT, 0) -- 低电压警告灯
+
+adc.open(adc.CH_CPU)
+
+-- 适配GNSS测试设备的GPIO
+sys.taskInit(function()
+    while 1 do
+        local vbat = adc.get(adc.CH_VBAT)
+        log.info("vbat", vbat)
+        if vbat < 3400 then
+            gpio.set(LED_VBAT, 1)
+            sys.wait(100)
+            gpio.set(LED_VBAT, 0)
+            sys.wait(900)
+        else
+            sys.wait(1000)
+        end
+    end
+end)
+

+ 127 - 0
demo/air780eg_gnsstest/testMqtt.lua

@@ -0,0 +1,127 @@
+
+local mqttc = nil
+
+-- mqtt 上传任务
+sys.taskInit(function()
+    sys.waitUntil("IP_READY", 15000)
+    mqttc = mqtt.create(nil, "lbsmqtt.airm2m.com", 1886) -- mqtt客户端创建
+
+    mqttc:auth(mobile.imei(), mobile.imei(), mobile.muid()) -- mqtt三元组配置
+    log.info("mqtt", mobile.imei(), mobile.imei(), mobile.muid())
+    mqttc:keepalive(30) -- 默认值240s
+    mqttc:autoreconn(true, 3000) -- 自动重连机制
+
+    mqttc:on(function(mqtt_client, event, data, payload) -- mqtt回调注册
+        -- 用户自定义代码,按event处理
+        -- log.info("mqtt", "event", event, mqtt_client, data, payload)
+        if event == "conack" then -- mqtt成功完成鉴权后的消息
+            sys.publish("mqtt_conack") -- 小写字母的topic均为自定义topic
+            -- 订阅不是必须的,但一般会有
+            mqtt_client:subscribe("/gnss/" .. mobile.imei() .. "/down/#")
+        elseif event == "recv" then -- 服务器下发的数据
+            log.info("mqtt", "downlink", "topic", data, "payload", payload)
+            local dl = json.decode(data)
+            if dl then
+                -- 检测命令
+                if dl.cmd then
+                    -- 直接写uart
+                    if dl.cmd == "uart" and dl.data then
+                        uart.write(gps_uart_id, dl.data)
+                    -- 重启命令
+                    elseif dl.cmd == "reboot" then
+                        rtos.reboot()
+                    elseif dl.cmd == "stat" then
+                        upload_stat()
+                    end
+                end
+            end
+        elseif event == "sent" then -- publish成功后的事件
+            log.info("mqtt", "sent", "pkgid", data)
+        end
+    end)
+
+    -- 发起连接之后,mqtt库会自动维护链接,若连接断开,默认会自动重连
+    mqttc:connect()
+    -- sys.waitUntil("mqtt_conack")
+    -- log.info("mqtt连接成功")
+    sys.timerStart(upload_stat, 3000) -- 一秒后主动上传一次
+    while true do
+        sys.wait(60*1000)
+    end
+    mqttc:close()
+    mqttc = nil
+end)
+
+sys.taskInit(function()
+    while 1 do
+        sys.wait(3600 * 1000) -- 一小时检查一次
+        local fixed, time_fixed = libgnss.isFix()
+        if not fixed then
+            exec_agnss()
+        end
+    end
+end)
+
+sys.timerLoopStart(upload_stat, 60000)
+
+sys.taskInit(function()
+    local msgs = {}
+    while 1 do
+        local ret, topic, data, qos = sys.waitUntil("uplink", 30000)
+        if ret then
+            if topic == "close" then
+                break
+            end
+            log.info("mqtt", "publish", "topic", topic)
+            -- if #data > 512 then
+            --     local start = mcu.ticks()
+            --     local cdata = miniz.compress(data)
+            --     local endt = mcu.ticks() - start
+            --     if cdata then
+            --         log.info("miniz", #data, #cdata, endt)
+            --     end
+            -- end
+            if mqttc:ready() then
+                local tmp = msgs
+                if #tmp > 0 then
+                    log.info("mqtt", "ready, send buff", #tmp)
+                    msgs = {}
+                    for k, msg in pairs(tmp) do
+                        mqttc:publish(msg.topic, msg.data, 0)
+                    end
+                end
+                mqttc:publish(topic, data, qos)
+            else
+                log.info("mqtt", "not ready, insert into buff")
+                if #msgs > 60 then
+                    table.remove(msgs, 1)
+                end
+                table.insert(msgs, {
+                    topic = topic,
+                    data = data
+                })
+            end
+        end
+    end
+end)
+
+function upload_stat()
+    if mqttc == nil or not mqttc:ready() then return end
+    local stat = {
+        csq = mobile.csq(),
+        rssi = mobile.rssi(),
+        rsrq = mobile.rsrq(),
+        rsrp = mobile.rsrp(),
+        -- iccid = mobile.iccid(),
+        snr = mobile.snr(),
+        vbat = adc.get(adc.CH_VBAT),
+        temp = adc.get(adc.CH_CPU),
+        memsys = {rtos.meminfo("sys")},
+        memlua = {rtos.meminfo()},
+        fixed = libgnss.isFix()
+    }
+    sys.publish("uplink", "/gnss/" .. mobile.imei() .. "/up/stat", (json.encode(stat)), 1)
+end
+
+sys.timerLoopStart(upload_stat, 60 * 1000)
+

+ 190 - 0
demo/air780eg_gnsstest/testTcp.lua

@@ -0,0 +1,190 @@
+--[[
+连到gps.nutz.cn 19002 端口, irtu的自定义包格式
+]]
+
+-- LuaTools需要PROJECT和VERSION这两个信息
+PROJECT = "scdemo"
+VERSION = "1.0.0"
+
+log.info("main", PROJECT, VERSION)
+
+-- 一定要添加sys.lua !!!!
+sys = require("sys")
+sysplus = require("sysplus")
+libnet = require "libnet"
+
+if pm and pm.PWK_MODE then
+    pm.power(pm.PWK_MODE, false)
+end
+
+if wdt then
+    --添加硬狗防止程序卡死,在支持的设备上启用这个功能
+    wdt.init(9000)--初始化watchdog设置为9s
+    sys.timerLoopStart(wdt.feed, 3000)--3s喂一次狗
+end
+
+adc.open(adc.CH_VBAT)
+
+--=============================================================
+-- 本TCP演示是连接到 gps.nutz.cn 19002 端口, irtu的自定义包格式
+-- 网页是 https://gps.nutz.cn/ 输入IMEI号可参考当前位置
+-- 微信小程序是 irtu寻物, 点击IMEI号, 扫描模块的二维码可查看当前位置和历史轨迹
+local host = "gps.nutz.cn"  -- 服务器ip或者域名, 都可以的
+local port = 19002          -- 服务器端口号
+local is_udp = false        -- 如果是UDP, 要改成true, false就是TCP
+local is_tls = false        -- 加密与否, 要看服务器的实际情况
+--=============================================================
+
+-- 处理未识别的网络消息
+local function netCB(msg)
+	log.info("未处理消息", msg[1], msg[2], msg[3], msg[4])
+end
+
+local socket_ready = false
+local taskName = "sc"
+local topic = taskName .. "_txrx"
+log.info("socket", "event topic", topic)
+
+-- 演示task
+local function sockettest()
+    sys.waitUntil("IP_READY")
+
+    -- 开始正在的逻辑, 发起socket链接,等待数据/上报心跳
+    local txqueue = {}
+    sysplus.taskInitEx(sockettask, taskName, netCB, taskName, txqueue, topic)
+    while 1 do
+        local result, tp, data = sys.waitUntil(topic, 30000)
+        -- log.info("event", result, tp, data)
+        if not result then
+            -- 等很久了,没数据上传/下发, 发个日期心跳包吧
+            table.insert(txqueue, string.char(0))
+            sys_send(taskName, socket.EVENT, 0)
+        elseif tp == "uplink" then
+            -- 上行数据, 主动上报的数据,那就发送呀
+            table.insert(txqueue, data)
+            sys_send(taskName, socket.EVENT, 0)
+        elseif tp == "downlink" then
+            -- 下行数据,接收的数据, 从ipv6task来的
+            -- 其他代码可以通过 sys.publish()
+            log.info("socket", "收到下发的数据了", #data)
+        end
+    end
+end
+
+
+
+function sockettask(d1Name, txqueue, rxtopic)
+    -- 打印准备连接的服务器信息
+    log.info("socket", host, port, is_udp and "UDP" or "TCP", is_tls and "TLS" or "RAW")
+
+    -- 准备好所需要的接收缓冲区
+    local rx_buff = zbuff.create(1024)
+    local netc = socket.create(nil, d1Name)
+    socket.config(netc, nil, is_udp, is_tls)
+    log.info("任务id", d1Name)
+
+    while true do
+        -- 连接服务器, 15秒超时
+        log.info("socket", "开始连接服务器")
+        sysplus.cleanMsg(d1Name)
+        local result = libnet.connect(d1Name, 15000, netc, host, port)
+        if result then
+			log.info("socket", "服务器连上了")
+            local tmp = {imei=mobile.imei(),iccid=mobile.iccid()}
+			libnet.tx(d1Name, 0, netc, json.encode(tmp))
+            socket_ready = true
+        else
+            log.info("socket", "服务器没连上了!!!")
+		end
+		while result do
+            -- 连接成功之后, 先尝试接收
+            -- log.info("socket", "调用rx接收数据")
+			local succ, param = socket.rx(netc, rx_buff)
+			if not succ then
+				log.info("服务器断开了", succ, param, ip, port)
+				break
+			end
+            -- 如果服务器有下发数据, used()就必然大于0, 进行处理
+			if rx_buff:used() > 0 then
+				log.info("socket", "收到服务器数据,长度", rx_buff:used())
+                local data = rx_buff:query() -- 获取数据
+                sys.publish(rxtopic, "downlink", data)
+				rx_buff:del()
+			end
+            -- log.info("libnet", "调用wait开始等待消息")
+            -- 等待事件, 例如: 服务器下发数据, 有数据准备上报, 服务器断开连接
+			result, param, param2 = libnet.wait(d1Name, 15000, netc)
+            log.info("libnet", "wait", result, param, param2)
+			if not result then
+                -- 网络异常了, 那就断开了, 执行清理工作
+				log.info("socket", "服务器断开了", result, param)
+				break
+            elseif #txqueue > 0 then
+                -- 有待上报的数据,处理之
+                while #txqueue > 0 do
+                    local data = table.remove(txqueue, 1)
+                    if not data then
+                        break
+                    end
+                    result,param = libnet.tx(d1Name, 15000, netc,data)
+                    -- log.info("libnet", "发送数据的结果", result, param)
+                    if not result then
+                        log.info("socket", "数据发送异常", result, param)
+                        break
+                    end
+                end
+            end
+            -- 循环尾部, 继续下一轮循环
+		end
+        socket_ready = false
+        -- 能到这里, 要么服务器断开连接, 要么上报(tx)失败, 或者是主动退出
+		libnet.close(d1Name, 5000, netc)
+		-- log.info(rtos.meminfo("sys"))
+		sys.wait(3000) -- 这是重连时长, 自行调整
+    end
+end
+
+sys.taskInit(sockettest)
+
+
+sys.taskInit(function()
+    sys.waitUntil("IP_READY")
+    local stat_t = 0
+    local buff = zbuff.create(64)
+    while true do
+        if socket_ready then
+            -- 发送设备状态  >b7IHb  ==  1*7+4+2+1 = 14
+            if os.time() - stat_t > 30 then
+                -- 30秒上报一次
+                local vbat = adc.get(adc.CH_VBAT)
+                buff:seek(0)
+                buff:pack(">b7IHb", 0x55, 0, 0, 0, 0, 0, 0, 0, vbat, mobile.csq())
+                sys.publish(topic, "uplink", buff:query())
+                stat_t = os.time()
+                sys.wait(100)
+            end
+            -- 发送位置信息 >b2i3H2b3 == 1*2+4*3+2*2+1*3 == 2+12+4+3 = 21
+            if true then
+                local rmc = libgnss.getRmc(1)
+                local gsa = libgnss.getGsa()
+                local gsv = libgnss.getGsv()
+                -- log.info("socket", "rmc", rmc.lat, rmc.lng, rmc.alt, rmc.course, rmc.speed)
+                buff:seek(0)
+                buff:pack(">b2i3H2b3", 0xAA, libgnss.isFix() and 1 or 0,
+                        os.time(),
+                        rmc and rmc.lng or 0,
+                        rmc and rmc.lat or 0,
+                        0, -- rmc and rmc.alt or 0,
+                        math.floor(rmc and rmc.course or 0),
+                        math.floor(rmc and rmc.speed or 0),
+                        gsa and #gsa.sats or 0, -- msg.sateCno
+                        gsv and gsv.total_sats or 0 -- msg.sateCnt
+                )
+                sys.publish(topic, "uplink", buff:query())
+            end
+            sys.wait(1000)
+        else
+            sys.wait(100)
+        end
+    end
+end)

+ 276 - 0
demo/air780eg_gnsstest/uc6228.lua

@@ -0,0 +1,276 @@
+--[[
+
+]]
+
+local uc6228 = {
+    version = "1.0.1"
+}
+
+local sys = require("sys")
+
+function uc6228.setup(opts)
+    uc6228.opts = opts
+    if not uc6228.opts.uart_id then
+        uc6228.opts.uart_id = 2
+    end
+end
+
+function uc6228.start()
+    -- 初始化串口
+    local gps_uart_id = uc6228.opts.uart_id
+    local opts = uc6228.opts
+    local write = uc6228.writeCmd
+    uart.setup(gps_uart_id, 115200)
+    -- 是否为调试模式
+    if opts.debug then
+        libgnss.debug(true)
+    end
+    if uc6228.opts.uart_forward then
+        uart.setup(uc6228.opts.uart_forward, 115200)
+        libgnss.bind(gps_uart_id, uc6228.opts.uart_forward)
+    else
+        libgnss.bind(gps_uart_id)
+    end
+
+    -- 是否需要切换定位系统呢?
+    if opts.sys then
+        if type(opts.sys) == "number" then
+            if opts.sys == 1 then
+                uart.write(gps_uart_id, "$CFGSYS,H01\r\n")
+            elseif opts.sys == 2 then
+                uart.write(gps_uart_id, "$CFGSYS,H10\r\n")
+            elseif opts.sys == 5 then
+                uart.write(gps_uart_id, "$CFGSYS,H101\r\n")
+            else
+                uart.write(gps_uart_id, "$CFGSYS,H11\r\n")
+            end
+        end
+    end
+
+    if not opts.nmea_ver or opts.nmea_ver == 41 then
+        uart.write(gps_uart_id, "$CFGNMEA,h51\r\n") -- 切换到NMEA 4.1
+    end
+
+    -- 打开全部NMEA语句
+    if opts.rmc_only then
+        uart.write(gps_uart_id, "$CFGMSG,0,0,0\r\n")
+        sys.wait(20)
+        uart.write(gps_uart_id, "$CFGMSG,0,1,0\r\n")
+        sys.wait(20)
+        uart.write(gps_uart_id, "$CFGMSG,0,2,0\r\n")
+        sys.wait(20)
+        uart.write(gps_uart_id, "$CFGMSG,0,3,0\r\n")
+        sys.wait(20)
+        uart.write(gps_uart_id, "$CFGMSG,0,4,1\r\n")
+        sys.wait(20)
+        uart.write(gps_uart_id, "$CFGMSG,0,5,0\r\n")
+        sys.wait(20)
+        uart.write(gps_uart_id, "$CFGMSG,0,6,0\r\n")
+        sys.wait(20)
+        uart.write(gps_uart_id, "$CFGMSG,0,7,0\r\n")
+        sys.wait(20)
+    elseif uc6228.opts.no_nmea then
+        uart.write(gps_uart_id, "$CFGMSG,0,0,0\r\n")
+        sys.wait(20)
+        uart.write(gps_uart_id, "$CFGMSG,0,1,0\r\n")
+        sys.wait(20)
+        uart.write(gps_uart_id, "$CFGMSG,0,2,0\r\n")
+        sys.wait(20)
+        uart.write(gps_uart_id, "$CFGMSG,0,3,0\r\n")
+        sys.wait(20)
+        uart.write(gps_uart_id, "$CFGMSG,0,4,0\r\n")
+        sys.wait(20)
+        uart.write(gps_uart_id, "$CFGMSG,0,5,0\r\n")
+        sys.wait(20)
+        uart.write(gps_uart_id, "$CFGMSG,0,6,0\r\n")
+        sys.wait(20)
+        uart.write(gps_uart_id, "$CFGMSG,0,7,0\r\n")
+        sys.wait(20)
+    else
+        uart.write(gps_uart_id, "$CFGMSG,0,0,1\r\n") -- GGA
+        sys.wait(10)
+        uart.write(gps_uart_id, "$CFGMSG,0,1,1\r\n") -- GLL
+        sys.wait(10)
+        uart.write(gps_uart_id, "$CFGMSG,0,2,1\r\n") -- GSA
+        sys.wait(10)
+        uart.write(gps_uart_id, "$CFGMSG,0,3,1\r\n") -- GSV
+        sys.wait(10)
+        uart.write(gps_uart_id, "$CFGMSG,0,4,1\r\n") -- RMC
+        sys.wait(10)
+        uart.write(gps_uart_id, "$CFGMSG,0,5,1\r\n") -- VTG
+        sys.wait(10)
+        uart.write(gps_uart_id, "$CFGMSG,0,6,1\r\n") -- ZDA
+        sys.wait(10)
+        -- uart.write(gps_uart_id, "$CFGMSG,0,7,1\r\n") -- GST
+        -- sys.wait(10)
+    end
+end
+
+function uc6228.writeCmd(cmd)
+    log.info("uc6228", "写入指令", cmd:trim())
+    uart.write(uc6228.opts.uart_id, cmd)
+end
+
+function uc6228.reboot(mode)
+    local cmd = "$RESET,0,"
+    if not mode then
+        mode = 0
+    end
+    if mode == 2 then
+        cmd = cmd .. "hff\r\n"
+    elseif mode == 1 then
+        cmd = cmd .. "h01\r\n"
+    else
+        cmd = cmd .. "h00\r\n"
+    end
+    uart.write(uc6228.opts.uart_id, cmd)
+    if mode == 2 then
+        uc6228.agps_tm = nil
+    end
+    libgnss.clear()
+end
+
+function uc6228.stop()
+    uart.close(uc6228.opts.uart_id)
+end
+
+local function do_agps()
+    -- 首先, 发起位置查询
+    local lat, lng
+    if mobile then
+        mobile.reqCellInfo(6)
+        sys.waitUntil("CELL_INFO_UPDATE", 6000)
+        local lbsLoc2 = require("lbsLoc2")
+        lat, lng = lbsLoc2.request(5000)
+        -- local lat, lng, t = lbsLoc2.request(5000, "bs.openluat.com")
+        log.info("lbsLoc2", lat, lng)
+        if lat and lng then
+            lat = tonumber(lat)
+            lng = tonumber(lng)
+            log.info("lbsLoc2", lat, lng)
+        end
+    elseif wlan then
+        -- wlan.scan()
+        -- sys.waitUntil("WLAN_SCAN_DONE", 5000)
+    end
+    if not lat then
+        -- 获取最后的本地位置
+        local locStr = io.readFile("/hxxtloc")
+        if locStr then
+            local jdata = json.decode(locStr)
+            if jdata and jdata.lat then
+                lat = jdata.lat
+                lng = jdata.lng
+            end
+        end
+    end
+    -- 然后, 判断星历时间和下载星历
+    local now = os.time()
+    local agps_time = tonumber(io.readFile("/hxxt_tm") or "0") or 0
+    if now - agps_time > 3600 then
+        local url = uc6228.opts.url
+        if not uc6228.opts.url then
+            if uc6228.opts.sys and 2 == uc6228.opts.sys then
+                -- 单北斗
+                url = "http://download.openluat.com/9501-xingli/HXXT_BDS_AGNSS_DATA.dat"
+            else
+                url = "http://download.openluat.com/9501-xingli/HXXT_GPS_BDS_AGNSS_DATA.dat"
+            end
+        end
+        local code = http.request("GET", url, nil, nil, {dst="/hxxt.dat"}).wait()
+        if code and code == 200 then
+            log.info("uc6228", "下载星历成功", url)
+            io.writeFile("/hxxt_tm", tostring(now))
+        else
+            log.info("uc6228", "下载星历失败", code)
+        end
+    else
+        log.info("uc6228", "星历不需要更新", now - agps_time)
+    end
+
+    local gps_uart_id = uc6228.opts.uart_id or 2
+
+    -- 写入星历
+    local agps_data = io.readFile("/hxxt.dat")
+    if agps_data and #agps_data > 1024 then
+        log.info("uc6228", "写入星历数据", "长度", #agps_data)
+        for offset=1,#agps_data,512 do
+            log.info("gnss", "AGNSS", "write >>>", #agps_data:sub(offset, offset + 511))
+            uart.write(gps_uart_id, agps_data:sub(offset, offset + 511))
+            sys.wait(100) -- 等100ms反而更成功
+        end
+        -- uart.write(gps_uart_id, agps_data)
+    else
+        log.info("uc6228", "没有星历数据")
+        return
+    end
+
+    -- 写入参考位置
+    -- "lat":23.4068813,"min":27,"valid":true,"day":27,"lng":113.2317505
+    if not lat or not lng then
+        -- lat, lng = 23.4068813, 113.2317505
+        log.info("uc6228", "没有GPS坐标", lat, lng)
+        return -- TODO 暂时不写入参考位置
+    end
+    if socket.sntp then
+        socket.sntp()
+        sys.waitUntil("NTP_UPDATE", 1000)
+    end
+    local date = os.date("!*t")
+    if date.year > 2023 then
+        local str = string.format("$AIDTIME,%d,%d,%d,%d,%d,%d,000", date["year"], date["month"], date["day"],
+            date["hour"], date["min"], date["sec"])
+        log.info("uc6228", "参考时间", str)
+        uart.write(gps_uart_id, str .. "\r\n")
+        sys.wait(20)
+    end
+
+    local str = string.format("$AIDPOS,%.7f,%s,%.7f,%s,1.0\r\n",
+    lat > 0 and lat or (0 - lat), lat > 0 and 'N' or 'S',
+    lng > 0 and lng or (0 - lng), lng > 0 and 'E' or 'W')
+    log.info("uc6228", "写入AGPS参考位置", str)
+    uart.write(gps_uart_id, str)
+
+    -- 结束
+    uc6228.agps_tm = now
+end
+
+function uc6228.agps(force)
+    -- 如果不是强制写入AGPS信息, 而且是已经定位成功的状态,那就没必要了
+    if not force and libgnss.isFix() then return end
+    -- 先判断一下时间
+    local now = os.time()
+    if force or not uc6228.agps_tm or now - uc6228.agps_tm > 3600 then
+        -- 执行AGPS
+        log.info("uc6228", "开始执行AGPS")
+        do_agps()
+    else
+        log.info("uc6228", "暂不需要写入AGPS")
+    end
+end
+
+function uc6228.saveloc(lat, lng)
+    if not lat or not lng then
+        if libgnss.isFix() then
+            local rmc = libgnss.getRmc(3)
+            if rmc then
+                lat, lng = rmc.lat, rmc.lng
+            end
+        end
+    end
+    if lat and lng then
+        log.info("待保存的GPS位置", lat, lng)
+        local locStr = string.format('{"lat":%7f,"lng":%7f}', lat, lng)
+        log.info("uc6228", "保存GPS位置", locStr)
+        io.writeFile("/hxxtloc", locStr)
+    end
+end
+
+sys.subscribe("GNSS_STATE", function(event)
+    if event == "FIXED" then
+        uc6228.saveloc()
+    end
+end)
+
+
+return uc6228

+ 2 - 2
demo/air780epvh_gnsstest/hdgnss.lua

@@ -132,8 +132,8 @@ local function exec_agnss()
 
     -- 发起基站定位, 暂时禁用
     if mobile and false then
-        mobile.reqCellInfo(6000)
-        sys.waitUntil("CELL_INFO_UPDATE", 3000)
+        mobile.reqCellInfo(6)
+        sys.waitUntil("CELL_INFO_UPDATE", 6000)
         local lat2, lng2, t = lbsLoc2.request(5000)
         log.info("hdgnss", "基站定位结果", lat2, lng2)
         if lat2 and lng2 then