【2G模组Air202开发】Lua脚本编程实现MQTT协议连接Tlink平台(二)
整体思路:
- 在TLINK平台上创建一个MQTT协议的设备
- 对Air202模组进行lua编程并烧录
- 使用串口向Air202模组发送TLINK平台规定格式的payload数据,Air202接收到数据后进行封装并转发
- 观察TLINK平台的设备数据并下发数据观察串口接收到的数据
程序主要分为四大板块:
- main
- uartTask
- mqttTask
- ntpTask
其中main这是主程序的框架,uartTask负责串口任务,ntpTask是用来获取时间和信号质量的,mqttTask负责mqtt消息的收发,因为耗时、异步等因素又分为接收消息和发送消息两个小版块,分别为:
- mqttInMsg
- mqttOutMsg
首先创建一个文件夹,我这里创建的文件夹是LUAT-MQTT-TLINK
然后用vs code打开,不知道的看我前面的blog。
打开之后先是把上述的5问lua脚本文件先创建出来,下一步就是先把main的框架弄好,把合宙官网必要的程序启动框架都添加上去:
如下
--必须在这个位置定义PROJECT和VERSION变量
--PROJECT:ascii string类型,可以随便定义,只要不使用,就行
--VERSION:ascii string类型,如果使用Luat物联云平台固件升级的功能,必须按照"X.X.X"定义,X表示1位数字;否则可随便定义
PROJECT = "MQTT"
VERSION = "2.0.0"
--加载日志功能模块,并且设置日志输出等级
--如果关闭调用log模块接口输出的日志,等级设置为log.LOG_SILENT即可
require "log"
LOG_LEVEL = log.LOGLEVEL_TRACE
--[[
如果使用UART输出日志,打开这行注释的代码"--log.openTrace(true,1,115200)"即可,根据自己的需求修改此接口的参数
如果要彻底关闭脚本中的输出日志(包括调用log模块接口和Lua标准print接口输出的日志),执行log.openTrace(false,第二个参数跟调用openTrace接口打开日志的第二个参数相同),例如:
1、没有调用过sys.opntrace配置日志输出端口或者最后一次是调用log.openTrace(true,nil,921600)配置日志输出端口,此时要关闭输出日志,直接调用log.openTrace(false)即可
2、最后一次是调用log.openTrace(true,1,115200)配置日志输出端口,此时要关闭输出日志,直接调用log.openTrace(false,1)即可
]]
--log.openTrace(true,1,115200)
require "sys"
require "net"
--每1分钟查询一次GSM信号强度
--每1分钟查询一次基站信息
net.startQueryAll(60000, 60000)
--加载控制台调试功能模块(此处代码配置的是uart1,波特率115200)
--此功能模块不是必须的,根据项目需求决定是否加载
--使用时注意:控制台使用的uart不要和其他功能使用的uart冲突
--使用说明参考demo/console下的《console功能使用说明.docx》
--require "console"
--console.setup(1, 115200)
--加载硬件看门狗功能模块
--根据自己的硬件配置决定:1、是否加载此功能模块;2、配置Luat模块复位单片机引脚和互相喂狗引脚
--合宙官方出售的Air201开发板上有硬件看门狗,所以使用官方Air201开发板时,必须加载此功能模块
--加载硬件看门狗功能模块
require "wdt"
wdt.setup(pio.P0_30, pio.P0_31)
--加载网络指示灯功能模块
--根据自己的项目需求和硬件配置决定:1、是否加载此功能模块;2、配置指示灯引脚
--合宙官方出售的Air800和Air801开发板上的指示灯引脚为pio.P0_28,其他开发板上的指示灯引脚为pio.P1_1
require "netLed"
netLed.setup(true,moduleType == 2 and pio.P1_1 or pio.P2_0,moduleType == 2 and nil or pio.P2_1)--自动判断2/4g默认网络灯引脚配置
--网络指示灯功能模块中,默认配置了各种工作状态下指示灯的闪烁规律,参考netLed.lua中ledBlinkTime配置的默认值
--如果默认值满足不了需求,此处调用netLed.updateBlinkTime去配置闪烁时长
--加载错误日志管理功能模块【强烈建议打开此功能】
--如下2行代码,只是简单的演示如何使用errDump功能,详情参考errDump的api
require "errDump"
errDump.request("udp://ota.airm2m.com:9072")
--加载远程升级功能模块【强烈建议打开此功能】
--如下3行代码,只是简单的演示如何使用update功能,详情参考update的api以及demo/update
--PRODUCT_KEY = "v32xEAKsGTIEQxtqgwCldp5aPlcnPs3K"
--require "update"
--update.request()
--加载MQTT功能测试模块
require "mqttTask"
require "ntpTask"
require "uartTask"
--启动系统框架
sys.init(0, 0)
sys.run()
这里可以理解成多线程运作,所以这里就串口任务、mqtt任务、ntp任务。Main里面就这么点东西没有什么讲的。
对Air202模组串口的Lua程序编写
串口的收发主要有如下功能:
- 每5s钟打印一次实时时间和当前的网络信号强度
- 串口发送数据回显,串口发送什么就显示什么,这个是为了串口的收发测试
- 打印TLINK平台下发的数据
- 接收PC串口工具的数据作为payload进行封装后向平台发布消息
接下来将串口部分,先贴上代码:
require "utils"
require "pm"
require "mqttOutMsg"
module(..., package.seeall)
-- 配置串口1
pm.wake("uartTask.lua")
uart.setup(1, 115200, 8, uart.PAR_NONE, uart.STOP_1)
uart.on(1, "receive", function()sys.publish("UART1_RECEIVE") end)
-- 串口读指令
local function read(uid, timeout)
local cache_data = ""
if timeout == 0 or timeout == nil then timeout = 20 end
sys.wait(timeout)
while true do
local s = uart.read(uid, "*l")
if s == "" then
return cache_data
else
cache_data = cache_data .. s
end
end
end
function write(uid, s)
log.info("uartTask.write", s)
uart.write(uid, s)
end
-- 串口收到什么就返回什么 同时转发给mqtt
sys.taskInit(function()
while true do
if sys.waitUntil("UART1_RECEIVE", 1000) then
local dat = read(1, 20)
log.info("串口收到的数据:", dat)
write(1, dat)
mqttOutMsg.insertMsg("66V6H7I19QF02F90",dat,0)
end
end
end)
相关的api如下
其中有一个api没有提到
这里的uart.on里面设置的是一个消息机制,配套下面的代码使用
看到门路了把,就是这个"UART1_RECEIVE"字符串,这个字符串也不是死的,可以自己定义,可以理解为串口接收到数据之后就会发布一个"UART1_RECEIVE"字符串消息供给sys.waitUntil使用,在程序中一旦检测到这个消息,就会马上乡下执行里面的read函数,传入参数1代表的是串口1,20指的是串口读取的超时时间。而read是经过二次封装的,因为整个系统都是异步运行的,所以串口数据接收经常会出现的一个问题:数据被截断
这个现象很常见,你可以像普通单片机一样一个字节一个字节去解析,也可以加一个缓冲区定时清空处理。这里使用的是缓冲区的方法。
串口打印测试
串口收发的测试
至此,串口部分就已经实现了,这是次篇幅讲记录串口部分编程,至于网络MQTT部分请移步接下来的篇幅。