一、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)
-
创建免费实例(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(); // 连接WiFi
client.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协议实现物联网通信的核心技能。建议在实际项目中逐步加入异常处理、安全机制等要素,打造稳定可靠的物联网系统。