一、MQTT协议简介
1.1 发布/订阅模式
MQTT(Message Queuing Telemetry Transport)是一种轻量级物联网通信协议,采用发布/订阅模式:
-
发布者(Publisher):发送消息到指定主题(如:
home/light
) -
订阅者(Subscriber):订阅感兴趣的主题接收消息
-
代理(Broker):负责消息路由的中枢服务器
1.2 协议优势
-
低带宽消耗(最小消息仅2字节)
-
支持离线消息(QoS质量等级)
-
适合不稳定网络环境
-
一对多通信效率高
二、MQTT服务器搭建
2.1 本地搭建(Mosquitto)
# Ubuntu安装 sudo apt-get install mosquitto mosquitto-clients# 启动服务 sudo systemctl start mosquitto# 测试订阅(新终端) mosquitto_sub -h localhost -t "test"# 测试发布(另开终端) mosquitto_pub -h localhost -t "test" -m "Hello World"
2.2 云平台方案(EMQX)
-
访问EMQX Cloud
-
创建免费实例(15天试用)
-
获取连接信息:
复制
地址: mqtt.emqx.io 端口: 1883
三、ESP32客户端开发
3.1 开发环境准备
-
Arduino IDE安装
-
添加ESP32支持:文件 > 首选项 > 附加开发板管理器
复制
https://dl.espressif.com/dl/package_esp32_index.json
-
安装库:工具 > 管理库 > 搜索安装
PubSubClient
3.2 完整代码(逐行解析)
#include <WiFi.h> #include <PubSubClient.h>// WiFi配置 const char* ssid = "Your_WiFi_SSID"; const char* password = "Your_WiFi_Password";// MQTT配置 const char* mqttServer = "mqtt.emqx.io"; // 代理地址 const int mqttPort = 1883; // 非加密端口 const char* clientID = "ESP32Client"; // 客户端唯一ID const char* subTopic = "device/control"; // 订阅主题 const char* pubTopic = "device/status"; // 发布主题WiFiClient espClient; // WiFi客户端对象 PubSubClient client(espClient); // MQTT客户端实例void setup_wifi() {delay(10);Serial.println();Serial.print("Connecting to ");Serial.println(ssid);WiFi.begin(ssid, password); // 启动WiFi连接while (WiFi.status() != WL_CONNECTED) {delay(500);Serial.print(".");}Serial.println("");Serial.println("WiFi connected");Serial.println("IP address: ");Serial.println(WiFi.localIP()); }void callback(char* topic, byte* payload, unsigned int length) {Serial.print("Message arrived [");Serial.print(topic);Serial.print("] ");// 将字节数组转换为字符串String message;for (int i=0; i<length; i++) {message += (char)payload[i];}Serial.println(message);// 根据消息内容执行操作if(message == "ON"){digitalWrite(LED_BUILTIN, LOW); // ESP32内置LED低电平触发}else if(message == "OFF"){digitalWrite(LED_BUILTIN, HIGH);} }void reconnect() {while (!client.connected()) {Serial.print("Attempting MQTT connection...");if (client.connect(clientID)) { // 尝试连接Serial.println("connected");client.subscribe(subTopic); // 订阅主题} else {Serial.print("failed, rc=");Serial.print(client.state()); // 打印错误代码Serial.println(" retry in 5 seconds");delay(5000);}} }void setup() {pinMode(LED_BUILTIN, OUTPUT); // 初始化LED引脚Serial.begin(115200); // 启动串口通信setup_wifi(); // 连接WiFiclient.setServer(mqttServer, mqttPort); // 配置MQTT服务器client.setCallback(callback); // 设置消息回调函数 }void loop() {if (!client.connected()) { // 断线重连机制reconnect();}client.loop(); // 维持MQTT连接// 定时发布状态(示例)static unsigned long lastMsg = 0;if (millis() - lastMsg > 5000) {lastMsg = millis();String msg = "Alive: " + String(millis()/1000);client.publish(pubTopic, msg.c_str()); // 发布消息} }
四、远程控制实现
4.1 手机APP控制(MQTT Dash)
-
应用商店下载"MQTT Dash"
-
创建新连接:
复制
Host: mqtt.emqx.io Port: 1883
-
添加控制面板:
-
开关组件:绑定到
device/control
主题 -
文本组件:订阅
device/status
主题
-
4.2 网页控制(Node-RED)
// 流程配置示例 [{"id": "switch","type": "ui_switch","z": "flow1","name": "LED控制","topic": "device/control","layout": "row-center"},{"id": "status","type": "ui_text","z": "flow1","name": "设备状态","topic": "device/status","layout": "row-center"} ]
五、常见问题排查
5.1 连接失败分析
错误代码 | 含义 | 解决方案 |
---|---|---|
-2 | 网络不可达 | 检查WiFi连接 |
-1 | 连接被拒绝 | 检查端口/防火墙设置 |
2 | 无效客户端标识 | 修改clientID |
4 | 用户名/密码错误 | 检查认证信息 |
5.2 消息不达的可能原因
-
主题名称不一致(注意大小写)
-
QoS等级不匹配
-
未成功订阅主题
-
消息载荷格式错误
六、进阶技巧
-
保留消息:
client.publish(topic, message, true)
-
遗嘱消息:配置断开时自动发布状态
-
QoS等级:
-
0:最多一次
-
1:至少一次
-
2:精确一次
-
-
TLS加密:使用8883端口+CA证书
// 启用SSL示例 WiFiClientSecure espClient; espClient.setCACert(root_ca); // 添加根证书 PubSubClient client(mqttServer, 8883, callback, espClient);
七、项目扩展建议
-
添加温湿度传感器(DHT11)
-
实现OTA无线升级
-
接入Home Assistant平台
-
设计JSON消息格式
{"device": "ESP32-001","timestamp": 1629782400,"temperature": 25.5,"humidity": 60 }
通过本教程,您已掌握ESP32通过MQTT协议实现物联网通信的核心技能。建议在实际项目中逐步加入异常处理、安全机制等要素,打造稳定可靠的物联网系统。