指南-示例-luat示例-MQTT

关键词:MQTT

如何用开发板实现mqtt功能

简介

MQTT 指南
mqtt是物联网中最常用的功能,本文介绍如何用Air724开发板,进行mqtt数据订阅,发布,接收的功能演示。

材料准备

  1. EVB_Air724UG_A13开发板一套,包括天线SIM卡,USB线。

  2. luat开发环境:环境搭建方法
    图片.png

步骤

本文以demo\mqtt\sync\sendWaitRecv这个DEMO为例做演示。

  1. 我们可以通过MQTT.fx工具来测试mqtt运行状况,我们这里和脚本连接同一个MQTT服务器,用来监视MQTT运行状态。我们脚本里会10秒钟发布一个/qos0topic主题的数据,20秒钟会发布一个/中文qos1topic主题的数据,监视结果如下。可以看到/qos0topic主题的数据的数据是/中文qos1topic主题的数据的2倍。
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-090cBW1u-1624852639082)(http://openluat-luatcommunity.oss-cn-hangzhou.aliyuncs.com/images/20210409165602270_2.png “undefined”)]

  2. 代码分析

  • mqttTask.lua实现的是建立一个mqtt的流程和异常处理机制。要先等待网络就绪了才可以做mqtt相关操作,这里的等待超时时间位5分钟,如果模块等待5分钟还没注册上网络的话,会通过进入飞行模式和退出飞行模式的方法重启一下协议栈。
--启动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,600,"user","password")
            else
                --进入飞行模式,20秒之后,退出飞行模式
                net.switchFly(true)
                sys.wait(20000)
                net.switchFly(false)
            end
        end
    end
)
  • 创建MQTT客户端,并连接,这里clientId用的时设备的IMEI号,设置的心跳时间为600秒,连接类型这里用的是’tcp’,支持’tcp’和’tcp_ssl’两种连接方式,可以根据实际需求来选择不同的连接方式。
   --创建一个MQTT客户端
   local mqttClient = mqtt.client(imei,600,"user","password")
   --连接MQTT
   mqttClient:connect("lbsmqtt.airm2m.com",1884,"tcp")
  • 主题订阅和数据的发布和接收,这里订阅了topic为"/event0"和"/中文event1"为的2这个主题,这里通过while循环处理接收和发送的数据。
if mqttClient:subscribe({["/event0"]=0, ["/中文event1"]=1}) then
   mqttOutMsg.init()
   --循环处理接收和发送的数据
   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
  • 数据接收的处理是在mqttInMsg.lua脚本中实现的,这里通过在while循环里调用mqttc:receive()函数来实现的,这里设置的超时时间为60秒,60秒没收到数据的话会跳出次循环。
--- MQTT客户端数据接收处理
-- @param mqttClient,MQTT客户端对象
-- @return 处理成功返回true,处理出错返回false
-- @usage mqttInMsg.proc(mqttClient)
function proc(mqttClient)
    local result,data
    while true do
        result,data = mqttClient:receive(60000,"APP_SOCKET_SEND_DATA")
        --接收到数据
        if result then
            log.info("mqttInMsg.proc",data.topic,string.toHex(data.payload))
                
            --TODO:根据需求自行处理data.payload
        else
            break
        end
    end
	
    return result or data=="timeout" or data=="APP_SOCKET_SEND_DATA"
end
  • 数据发送的处理是在mqttOutMsg.lua中实现的,发送的消息是通过消息队列维护的,要发送的数据先通调用insertMsg()函数插入要发送的消息到msgQueue,等之前的数据发送完成后会通过调用proc()函数从msgQueue队列中取出第一个消息,通过调用mqttClient:publish()函数,真正的把数据发送出去。这里定时发送是通过在回调函数里启动定时的方式实现的。
--数据发送的消息队列
local msgQueue = {}

--插入发发送的数据到消息队列
local function insertMsg(topic,payload,qos,user)
    table.insert(msgQueue,{t=topic,p=payload,q=qos,user=user})
    sys.publish("APP_SOCKET_SEND_DATA")
end

--主题为"/qos0topic"的消息回调函数
local function pubQos0TestCb(result)
    log.info("mqttOutMsg.pubQos0TestCb",result)
    if result then sys.timerStart(pubQos0Test,10000) end
end

--插入主题为"/qos0topic"的消息到消息队列
function pubQos0Test()
    insertMsg("/qos0topic","qos0data",0,{cb=pubQos0TestCb})
end

--主题为"/中文qos1topic"的消息回调函数
local function pubQos1TestCb(result)
    log.info("mqttOutMsg.pubQos1TestCb",result)
    if result then sys.timerStart(pubQos1Test,20000) end
end

--插入主题为"/中文qos1topic"的消息到消息队列
function pubQos1Test()
    insertMsg("/中文qos1topic","中文qos1data",1,{cb=pubQos1TestCb})
end

--从消息队列中取出消息,发送到服务器 
function proc(mqttClient)
    while #msgQueue>0 do
        local outMsg = table.remove(msgQueue,1)
        local result = mqttClient:publish(outMsg.t,outMsg.p,outMsg.q)
        if outMsg.user and outMsg.user.cb then outMsg.user.cb(result,outMsg.user.para) end
        if not result then return end
    end
    return true
end
  • log解析,服务器连接,这个也实际上也是通过SOCKET连接的,连接方式TCP,超时时间也是默认的120S
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NZ1JP1mN-1624852639084)(http://openluat-luatcommunity.oss-cn-hangzhou.aliyuncs.com/images/20210412112856752_3.png “undefined”)]

数据发送,可以看出"/qos0topic"主题是10S一次,"/中文qos1topic"主题是20S一次
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kyTkDxWG-1624852639086)(http://openluat-luatcommunity.oss-cn-hangzhou.aliyuncs.com/images/20210412113215147_4.png “undefined”)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GhIA0WGc-1624852639086)(http://openluat-luatcommunity.oss-cn-hangzhou.aliyuncs.com/images/20210412113057561_5.png “undefined”)]

数据接收,通过MQTT.fx工具,发送一个主题为"/event0"的消息,模块正常收到,并打印出来。
发送
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OU7UrQtm-1624852639087)(http://openluat-luatcommunity.oss-cn-hangzhou.aliyuncs.com/images/20210412113821281_6.png “undefined”)]
接收
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CsPKxlSL-1624852639088)(http://openluat-luatcommunity.oss-cn-hangzhou.aliyuncs.com/images/20210412113837000_7.png “undefined”)]
这里打印出的数据是HEX格式的,可以看出接收的数据是也是正确的
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FzQofodP-1624852639088)(http://openluat-luatcommunity.oss-cn-hangzhou.aliyuncs.com/images/20210412143218456_7.png “undefined”)]

完整代码,直接下载\demo\mqtt\sync\sendWaitRecv下的脚本即可。

常见问题

连接服务器失败

  1. 使用mqtt.fx,连接服务器确认一下是否可以连接成功,排除服务器故障
  2. 检查下模块信号、网络注册、网络附着、PDP激活状态
  3. 检查下SIM卡是否欠费【4G模块有一种欠费表现:无法注册4G网络,可以注册2G网络】

频繁掉线是什么原因

  1. 检查下是否存在代码逻辑错误,导致异常
  2. 检查下是否不断重启,导致异常
  3. 检查下服务器网络是否稳定,不要用内网穿透方式搭建服务器
  4. 检查下使用环境是否网络覆盖不好,例如车库、地下、电梯、山区等
  5. 排查是否为设备天线问题

如何实现掉线自动重连

  1. 参考mqtt demo,实现自动重连即可

相关资料以及购买链接

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值