1. 小节目标
在本小节中,实现 MQTT 的双向传输,即:
- 将从 MQTT 接收到的数据通过串口打印
- 将串口接收到的数据发送到 MQTT
2. 思路解析
从之前的学习中,我们已经知道了 ESPlorer 烧录代码是通过串口发送到 ESP8266 上的,当然了,此处肯定是使用了特定格式的代码,如
- 通过 file.witeline 往文件中写入行
但是我们又得实现通过接收串口的数据发送到 MQTT 上,那么我们需要自定义的实现串口接收函数,如下:
uart.setup(0, 115200, 8, uart.PARITY_NONE, uart.STOPBITS_1)
uart.on("data","\n",function(data)
m:publish(x_topic.."/m", data, 0, 0, function(client)
print("sent")
end)
end, 0)
但是我们又会面临一个问题,当我们自定义的实现了串口接收函数,烧录代码的功能就失效了。
所以我们需要使用特定的技巧来解决这个问题。
方法一:
我们需要将串口拦截函数存放到一个新的文件中,我们通过 lua 指令,dofile("filename");的方式来执行,这样就只有我们通过串口发送该字符串的时候,才会开始拦截串口的数据,否则就还是烧录代码的操作,通过此方法可以有效的解决此问题。
方法二:
当然我们也可以将连接 WIFI、MQTT、自定义串口接收所有的功能放到一个文件中,命名为 mqtt.lua
,然后在 init.lua
中只打印系统运行的操作,我们通过发送
dofile(mqtt.lua)
让 ESP8266 执行mqtt.lua
文件,操作 ESP8266 连接 WIFI、MQTT服务器,这样在重启之后也能正常的进行代码烧录。
方法三:
改写串口接收方法,在接收到+++数据的时候复位,就会自动进入 init.lua 文件,接下来就再调用 dofile(mqtt.lua); 来启动 MQTT 连接
uart.setup(0, 115200, 8, uart.PARITY_NONE, uart.STOPBITS_1)
uart.on("data","\n",function(data)
if data=="+++" then
node.restart()
end
m:publish(x_topic.."/m", data, 0, 0, function(client)
print("sent")
end)
end, 0)
3. 完整代码
3.1. mqtt.lua
station_cfg = {}
station_cfg.ssid = "xlu_2.4"
station_cfg.pwd = "111222333+"
station_cfg.auto = false
station_cfg.save = false
x_id=666
mqtt_cfg = {}
mqtt_cfg.host = "broker.emqx.io"
mqtt_cfg.port = 1883
mqtt_cfg.clientid = "alro_xxx".. x_id
mqtt_cfg.keepalive = 120
mqtt_cfg.username = "AlvaRocha"
mqtt_cfg.password = "aio_KO<safety edit>sXwbgtWCboCal"
--
x_topic="/topic/ctiot/".. x_id
m=nil
mqtt_ready=false
wifi.setmode(wifi.STATION)
wifi.sta.config(station_cfg)
iot_test = mqtt.Client(mqtt_cfg.clientid, mqtt_cfg.keepalive, mqtt_cfg.username, mqtt_cfg.password)
iot_test:on("offline", function(client)
print("client offline")
end)
iot_test:on("message", function(client, topic, data)
if data ~= nil then
print(data)
end
end)
function get_broker(mqtt_client)
mqtt_client:connect(mqtt_cfg.host, mqtt_cfg.port, false,
function(client)
client:subscribe(x_topic.."/c", 0, function(client)
print("subscribe success "..x_topic.."/c")
mqtt_ready=true
end)
m:publish(x_topic.."/m", "success", 0, 0, function(client)
print("init success")
end)
end,
function(client, reason)
print('connection failed', reason)
end)
m=mqtt_client
end
function startup()
if file.open("init.lua") == nil then
print("init.lua deleted or renamed")
else
print("Running")
file.close("init.lua")
get_broker(iot_test)
end
end
wifi_connect_event = function(T)
print("Connection to AP(" .. T.SSID .. ") established!")
print("Waiting for IP address...")
if disconnect_ct ~= nil then
disconnect_ct = nil
end
end
wifi_got_ip_event = function(T)
print("Wifi connection is ready! IP address is: " .. T.IP)
print("Startup will resume momentarily, you have 3 seconds to abort.")
print("Waiting...")
tmr.create():alarm(3000, tmr.ALARM_SINGLE, startup)
end
wifi.eventmon.register(wifi.eventmon.STA_CONNECTED, wifi_connect_event)
wifi.eventmon.register(wifi.eventmon.STA_GOT_IP, wifi_got_ip_event)
wifi.sta.connect()
uart.setup(0, 115200, 8, uart.PARITY_NONE, uart.STOPBITS_1)
uart.on("data","\n",function(data)
if data=="+++\r\n" then
node.restart()
end
if mqtt_ready then
m:publish(x_topic.."/m", data, 0, 0, function(client)
print("sent")
end)
end
end, 0)
3.2. init.lua
print("ctiot esp8266 start!")
3.3. 烧录代码
忽略该步骤,太简单不用再讲了
3.4. 操作步骤
烧录完代码后,可以看到以下现象
在这个时候我们可以通过发送
dofile("mqtt.lua");
来运行 mqtt 的连接
发送开始 mqtt.lua 的演示
发送完成后就可以进行双向的 MQTT 发送了
3.5. MQTT 双向通信演示
MQTTX 发送到 ESP8266,也就是 ESP8266 接收消息
ESP8266 将串口上的消息发送到 MQTTX上,也就是 ESP8266 接收消息上报
- 先订阅主题
- 在 ESP8266 上发送
3.6. 在 XCOM 串口调试组手上测试
ESP8266 复位之后,发送打开 mqtt.lua 的指令就可以了,非常的简单,各位可以尝试!!!