【2G模组Air202开发】Lua脚本编程实现MQTT协议连接Tlink平台(三)
整体思路:
- 在TLINK平台上创建一个MQTT协议的设备
- 对Air202模组进行lua编程并烧录
- 使用串口向Air202模组发送TLINK平台规定格式的payload数据,Air202接收到数据后进行封装并转发
- 观察TLINK平台的设备数据并下发数据观察串口接收到的数据
因为篇幅过长,我这里分成5篇来详细记录。
【2G模组Air202开发】Lua脚本编程实现MQTT协议连接Tlink平台(一)
【2G模组Air202开发】Lua脚本编程实现MQTT协议连接Tlink平台(二)
【2G模组Air202开发】Lua脚本编程实现MQTT协议连接Tlink平台(三)
【2G模组Air202开发】Lua脚本编程实现MQTT协议连接Tlink平台(四)
【2G模组Air202开发】Lua脚本编程实现MQTT协议连接Tlink平台(五)
对Air202模组MQTT的Lua程序编写,同样的先贴上第一部分的代码
--- 模块功能: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
local mqttip,mqttport,mqttuser,mqttpassword,mqttheartbeat = "mq.tlink.io","1883","MQTT","MQTTPW",60
socket.setSendMode(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
--是否获取到分配的IP(是否连上网)
if socket.isReady() then
local imei = misc.getImei()
--创建一个MQTT客户端
local mqttClient = mqtt.client(imei,mqttheartbeat,mqttuser,mqttpassword)
--阻塞执行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(mqttip,mqttport,"tcp") then
--连接成功
log.info("mqttTask.mqttClient","Connet ok!","imei = " .. imei)
retryConnectCnt = 0 --失败次数清零
--ready = true
--订阅主题
if mqttClient:subscribe({["xxx".."/+"]=0}) then --xxx代表的是序列号
mqttOutMsg.insertMsg("xxx","Iccid = " .. sim.getIccid(),0)--这个没啥用
--循环处理接收和发送的数据
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
end
--ready = false
else
log.info("mqttTask.mqttClient","Connet fail!")
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
)
贴上部分api:
这个部分就是mqtt任务的核心了,也是最难理解的地方,下面硬着头皮来记录下心得:
mqtt连接都是异步运行的,何时应该发送数据,何时应该接收数据,这些逻辑应该让mqtt收发的进程自己进行控制。一般来说,我们会在模块成功获取基站分配的ip后,才会进行网络的连接操作,所以我们需要使用socket.isReady()
函数来判断是否连接网络,然后再进行网络操作,在成功获取ip后,我们才能新建一个mqtt对象,对其进行联网操作。为了增加代码的稳健性,我们可以利用sys.waitUntil()
函数,设置五分钟内没有获取到ip就开启飞行模式几秒,再关闭,让模块重新去获取GPRS连接。同样,我们也可以给mqttClient:connect(mqttip,mqttport,"tcp")
的连接加上错误次数的判断,连接错误超过五次,强制断开socket连接,等待五秒后重试。这些都理解之后那就是mqtt的收发数据了,这里是直接写在一个死循环里面的。
要注意的是:
在接收和发送函数不返回false的情况下,接收和发送循环会一直进行下去;只有当两个函数之一返回false时,才会触发break导致退出该接收和发送循环。所以接收和发送函数里面还要加上一定的机制才能使得mqtt任务的健全。
好了,此篇就只记录这个mqtt主任务,接收和发送函数留在下一篇。
这是次篇幅记录网络MQTT的主任务部分,MQTT的收发消息实现请移步接下来的篇幅。
By Urien 2019年6月29日 09:05:04