往期
《ESP8266通信指南》14-连接WIFI(基于Lua)-CSDN博客
《ESP8266通信指南》13-Lua 简单入门(打印数据)-CSDN博客
《ESP8266通信指南》12-Lua 固件烧录-CSDN博客
《ESP8266通信指南》11-Lua开发环境配置-CSDN博客
《ESP8266通信指南》10-MQTT通信(Arduino开发)-CSDN博客
《ESP8266通信指南》9-TCP通信(Arudino开发)-CSDN博客
《ESP8266通信指南》8-连接WIFI(Arduino开发)(非常简单)-CSDN博客
《ESP8266通信指南》7-Arduino 开发8266的环境配置与示例代码烧录-CSDN博客
《ESP8266通信指南》6-创建TCP服务器(AT指令)-CSDN博客
《ESP8266通信指南》5-TCP通信透传模式(AT指令)-CSDN博客
《ESP8266通信指南》4-以Client进行TCP通信(AT指令)-CSDN博客
《ESP8266通信指南》3-常用AT指令详解-8266连WIFI-CSDN博客
《ESP8266通信指南》2-ESP8266 AT测试-CSDN博客
《ESP8266通信指南》1-ESP8266 简介-CSDN博客
1. 小节目标
实现 MQTT 的连接,订阅主题,接收来自 MQTT 的消息,并在串口打印出来。
2. 完整代码
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 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") 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()
各位读者需要自己将 ID 更改为自己的特殊信息,或者将整个主题更改为包含自己特征的主题,因为我们使用的是公共的 MQTT 服务器,为了避免接收到别人的消息,影响我们的测试,迫不得已这样做,在后来,我们会介绍如何自己部署一个 MQTT 服务器,到时候就不需要考虑这些主题的问题了,到时候就需要考虑设备的唯一表示 ID 主题。
3. 现象
3.1. 连接上 MQTT 服务
- 首先连接 WIFI
- 连接上 MQTT 服务器
- 订阅主题,并将订阅的主题打印出来
- 这个就是 ESP8266 订阅的主题
/topic/ctiot/666/c
3.2. 接收到 MQTT 消息
我们使用之前介绍过的 MQTTX 客户端,往我们订阅的主题发送消息,我的主题是:
/topic/ctiot/666/c
使用 MQTTX 软件往上述的主题发送消息,ESP8266 就可以接收到消息了,如下
关于 MQTTX 如何使用,可参考这篇博客:《ESP8266通信指南》10-MQTT通信(Arduino开发)-CSDN博客
4. 代码详解
4.1. 初始化 Wi-Fi 连接参数
station_cfg = {} station_cfg.ssid = "xlu_2.4" station_cfg.pwd = "111222333+" station_cfg.auto = false station_cfg.save = false
在这段代码中,我们初始化了 Wi-Fi 连接参数 station_cfg,包括 SSID、密码、自动连接和保存连接信息的设置。
- station_cfg.ssid: Wi-Fi 的 SSID,即网络名称。
- station_cfg.pwd: Wi-Fi 的密码。
- station_cfg.auto: 是否自动连接 Wi-Fi。
- station_cfg.save: 是否保存 Wi-Fi 连接信息。
4.2. 设置 MQTT 连接参数
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"
这部分代码定义了 MQTT 连接的参数,包括代理主机、端口、客户端 ID、保持连接时间、用户名和密码。
- x_id: 用于客户端 ID 的标识符。
- mqtt_cfg.host: MQTT 代理的主机地址。
- mqtt_cfg.port: MQTT 代理的端口。
- mqtt_cfg.clientid: MQTT 客户端 ID,结合了固定的前缀和 x_id。
- mqtt_cfg.keepalive: 客户端与服务器之间的心跳保持时间(以秒为单位)。
- mqtt_cfg.username 和 mqtt_cfg.password: MQTT 代理的用户名和密码。
4.3. 定义 MQTT 主题
x_topic="/topic/ctiot/".. x_id
这一行代码定义了 MQTT 主题,其中包含了一个固定的前缀 "/topic/ctiot/" 和之前定义的 x_id。这个主题将用于发布和订阅消息。
4.4. 初始化 Wi-Fi 连接
m=nil wifi.setmode(wifi.STATION) wifi.sta.config(station_cfg)
在这里,我们将 Wi-Fi 模式设置为 STATION(即客户端模式),然后配置 Wi-Fi 参数为之前定义的 station_cfg。
初始化 MQTT 客户端
iot_test = mqtt.Client(mqtt_cfg.clientid, mqtt_cfg.keepalive, mqtt_cfg.username, mqtt_cfg.password)
这行代码创建了一个 MQTT 客户端实例,使用了之前定义的 MQTT 连接参数。
4.5. 定义 MQTT 客户端事件处理函数
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)
这里定义了两个事件处理函数,分别处理客户端离线和收到消息的情况。当客户端离线时,打印提示信息;当收到消息时,打印消息内容。
4.6. 定义连接到 MQTT 代理的函数
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") 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
这个函数用于连接到 MQTT 代理,并订阅一个主题以及发布一条消息。连接成功后,将打印订阅成功和发布成功的信息。
4.7. 启动函数
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
这个函数用于启动 MQTT 客户端。首先检查是否存在 init.lua 文件,如果存在,则执行 get_broker 函数。
4.8. 定义 Wi-Fi 连接事件处理函数
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
这里定义了两个 Wi-Fi 连接事件处理函数,分别处理连接到 AP 和获取 IP 地址的情况。当连接到 AP 时,打印连接成功的提示信息;当获取到 IP 地址时,打印 IP 地址,并在 3 秒后执行 startup 函数。
4.9. 注册 Wi-Fi 事件回调函数并连接 Wi-Fi
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()
最后,注册了 Wi-Fi 事件回调函数,并启动 Wi-Fi 连接。
4.10. 带有注释的完整代码
带有中文注释的代码在烧录的时候有时候会烧录不进去,原因是中文编码导致的问题,建议如下:
- 不烧录带有中文的代码
- 将注释更改为简单易懂的英文
在这里贴出中文注释代码的原因是为了方便各位同学学习和阅读代码
-- 初始化 Wi-Fi 连接参数 station_cfg = {} station_cfg.ssid = "xlu_2.4" -- Wi-Fi SSID station_cfg.pwd = "111222333+" -- Wi-Fi 密码 station_cfg.auto = false -- 不自动连接 station_cfg.save = false -- 不保存连接信息 -- 设置 MQTT 连接参数 x_id = 666 mqtt_cfg = {} mqtt_cfg.host = "broker.emqx.io" -- MQTT 代理主机 mqtt_cfg.port = 1883 -- MQTT 代理端口 mqtt_cfg.clientid = "alro_xxx" .. x_id -- MQTT 客户端 ID mqtt_cfg.keepalive = 120 -- 保持连接时间 mqtt_cfg.username = "AlvaRocha" -- MQTT 用户名 mqtt_cfg.password = "aio_KO<safety edit>sXwbgtWCboCal" -- MQTT 密码 -- 定义 MQTT 主题 x_topic = "/topic/ctiot/" .. x_id -- 初始化 Wi-Fi 连接 m = nil wifi.setmode(wifi.STATION) wifi.sta.config(station_cfg) -- 初始化 MQTT 客户端 iot_test = mqtt.Client(mqtt_cfg.clientid, mqtt_cfg.keepalive, mqtt_cfg.username, mqtt_cfg.password) -- 定义 MQTT 客户端事件处理函数 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) -- 定义连接到 MQTT 代理的函数 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") 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 -- 定义 Wi-Fi 连接事件处理函数 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 -- 注册 Wi-Fi 事件回调函数并连接 Wi-Fi 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()
5. 结语
在小节中学习了如何使用 ESP8266 连接 MQTT 服务器同时订阅一个主题,在接收到 MQTT 服务器上发送来的消息的时候,将数据打印出来,在下一小节中我们将学习,如何将串口接收到的消息发送到 MQTT 服务器。
柴头物联网出品