GPRS(Air202) Lua开发: 物联网MQTT ,DTU

2020-05-26 16:42:17 浏览数 (1)

拷贝官方MQTT源码

修改main.lua

打开看门狗,网络指示灯功能

修改mqttTask.lua

本人服务器信息

IP地址: mnif.cn

端口号: TCP:1883  TCPS:8883

用户名: yang

密    码: 11223344

修改连接信息如下:

修改mqttInMsg.lua 

修改为直接打印接收的数据,去掉hex转换

mqttOutMsg.lua 说明

1.连接上MQTT以后 mqttTask.lua调用了mqttOutMsg 里面的 mqttOutMsg.init()  函数

2.官方给的例子是每隔10S发布主题为 /qos0topic   消息为 qos0data 的消息

每隔20S发布主题为 /中文qos1topic  消息为  中文qos1data  的消息

测试

1.安装手机卡,安装天线,下载程序

2.打开我提供的调试助手

连接,订阅,设置发布的主题如下

发布的主题:111111      订阅的主题:/qos0topic

扩展:DTU

模块接收的MQTT信息转发到485/422输出

485/422接收的数据转发给MQTT发送

设备订阅的主题:user/设备的imei号码

设备发布的主题:device/设备的imei号码

1.修改 mqttTask   初始化串口;修改订阅的主题为:user/设备的imei号;把IMEI号传递给发布程序

代码语言:javascript复制
--- 模块功能:MQTT客户端处理框架
-- @author openLuat
-- @module mqtt.mqttTask
-- @license MIT
-- @copyright openLuat
-- @release 2018.03.28

module(...,package.seeall)

require"misc"
require"mqtt"
require"mqttOutMsg"
require"mqttInMsg"


local ready = false

--- MQTT连接是否处于激活状态
-- @return 激活状态返回true,非激活状态返回false
-- @usage mqttTask.isReady()
function isReady()
    return ready
end


uart.setup(1, 115200, 8, uart.PAR_NONE, uart.STOP_1)


--启动MQTT客户端任务
sys.taskInit(
    function()
        local retryConnectCnt = 0
        while true do
            if not socket.isReady() then
                retryConnectCnt = 0
                --等待网络环境准备就绪,超时时间是5分钟
                sys.waitUntil("IP_READY_IND",300000)
            end
            
            if socket.isReady() then
                local imei = misc.getImei()
                --创建一个MQTT客户端
                local mqttClient = mqtt.client(imei,30,"yang","11223344")
                --阻塞执行MQTT CONNECT动作,直至成功
                --如果使用ssl连接,打开mqttClient:connect("lbsmqtt.airm2m.com",1884,"tcp_ssl",{caCert="ca.crt"}),根据自己的需求配置
                --mqttClient:connect("lbsmqtt.airm2m.com",1884,"tcp_ssl",{caCert="ca.crt"})
                if mqttClient:connect("mnif.cn",1883,"tcp") then
                    retryConnectCnt = 0
                    ready = true
                    --订阅主题
                    if mqttClient:subscribe({["user/"..imei]=0}) then --订阅主题:
                        mqttOutMsg.init(imei)
                        --循环处理接收和发送的数据
                        while true do
                            if not mqttInMsg.proc(mqttClient) then log.error("mqttTask.mqttInMsg.proc error") break end
                            if not mqttOutMsg.proc(mqttClient) then log.error("mqttTask.mqttOutMsg proc error") break end
                        end
                        mqttOutMsg.unInit()
                    end
                    ready = false
                else
                    retryConnectCnt = retryConnectCnt 1
                end
                --断开MQTT连接
                mqttClient:disconnect()
                if retryConnectCnt>=5 then link.shut() retryConnectCnt=0 end
                sys.wait(5000)
            else
                --进入飞行模式,20秒之后,退出飞行模式
                net.switchFly(true)
                sys.wait(20000)
                net.switchFly(false)
            end
        end
    end
)

2.修改 mqttInMsg 接收的数据串口1输出

代码语言:javascript复制
--- 模块功能:MQTT客户端数据接收处理
-- @author openLuat
-- @module mqtt.mqttInMsg
-- @license MIT
-- @copyright openLuat
-- @release 2018.03.28

module(...,package.seeall)


--- MQTT客户端数据接收处理
-- @param mqttClient,MQTT客户端对象
-- @return 处理成功返回true,处理出错返回false
-- @usage mqttInMsg.proc(mqttClient)
function proc(mqttClient)
    local result,data
    while true do
        result,data = mqttClient:receive(2000)
        --接收到数据
        if result then
            log.info("mqttInMsg.proc",data.topic,data.payload)
            --TODO:根据需求自行处理data.payload

            uart.write(1, data.payload) --串口输出接收的数据

            --如果mqttOutMsg中有等待发送的数据,则立即退出本循环
            if mqttOutMsg.waitForSend() then return true end
        else
            break
        end
    end
    
    return result or data=="timeout"
end

3.大幅度裁剪 mqttOutMsg 串口接收的数据,转发给MQTT发送

代码语言:javascript复制
--- 模块功能:MQTT客户端数据发送处理

module(...,package.seeall)
-- 串口ID,串口读缓冲区
local sendQueue = {} --接收数据缓存
local uartimeout=25 -- 串口接收超时时间
local recvReady = "UART_RECV_ID" --串口准备好后发布的消息
local myimei="";
-- MQTT
local msgQueue = {}  --数据发送的消息队列
function init(imei)
    myimei = imei; --获取IMEI
end
--- 清空对象存储
function unInit()
    while #msgQueue>0 do
        local outMsg = table.remove(msgQueue,1)
    end
end
--- MQTT客户端是否有数据等待发送
-- @return 有数据等待发送返回true,否则返回false
-- @usage mqttOutMsg.waitForSend()
function waitForSend()
    return #msgQueue > 0
end
--- MQTT客户端数据发送处理
-- @param mqttClient,MQTT客户端对象
-- @return 处理成功返回true,处理出错返回false
-- @usage mqttOutMsg.proc(mqttClient)
function proc(mqttClient,imei)
    while #msgQueue>0 do--有消息
        local outMsg = table.remove(msgQueue,1)--提取一条消息
        local result = mqttClient:publish(outMsg.t,outMsg.p,outMsg.q)--发送
        if not result then return end--发送失败返回空
    end
    return true
end
-- 串口
uart.on(1, "receive", function(uid)
    table.insert(sendQueue, uart.read(uid, 1460))
    sys.timerStart(sys.publish, uartimeout, recvReady)
end)
sys.subscribe(recvReady, function()
    local str = table.concat(sendQueue) --把每一条数据拼接成一条数据
    table.insert(msgQueue,{t="device/"..myimei,p=str,q=0})--串口接收的消息,插入MQTT发送缓存
    sendQueue = {} -- 串口的数据读完后清空缓冲区
end)

扩展1:DTU 测试

1.下载本节程序

2.接上485/422模块

A ,A- 作为485通信时的接收和发送数据接口,另作为422通信时的发送数据接口

B ,B- 作为422通信时的接收数据接口

用485模块连接如下:

3.打开MQTT调试助手

提示:设备的IMEI可看自己模块上的

订阅的主题:  device/设备的imei号

发布的主题:  user/设备的imei号

4.MQTT助手发布消息

0 人点赞