NodeMcu ESP8266(Lua)连接Mosquitto MQTT Broker失败求助
ESP8266通过PubSubClient连接Mosquitto失败(rc=-2)问题排查
问题描述
我使用NodeMcu ESP8266(Lua)连接本地Mosquitto MQTT Broker,通过控制台执行mosquitto_sub -v -t 'test/topic'和mosquitto_pub -t 'test/topic' -m 'helloWorld'测试,Broker运行正常。但使用适配了WiFi与MQTT服务器IP的PubSubClient代码时,设备无法建立MQTT连接:串口显示WiFi已成功连接(IP:192.168.0.101),但MQTT连接持续失败,报错rc=-2。已尝试关闭防火墙、改用Node-RED测试,均未解决问题。
所用代码
#include <PubSubClient.h> // Update these with values suitable for your network. const char* ssid = "310"; const char* password = "1234567890"; const char* mqtt_server = "192.168.0.114"; WiFiClient espClient; PubSubClient client(espClient); unsigned long lastMsg = 0; #define MSG_BUFFER_SIZE (50) char msg[MSG_BUFFER_SIZE]; int value = 0; void setup_wifi() { delay(10); // We start by connecting to a WiFi network Serial.println(); Serial.print("Connecting to "); Serial.println(ssid); WiFi.mode(WIFI_STA); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } randomSeed(micros()); 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("] "); for (int i = 0; i < length; i++) { Serial.print((char)payload[i]); } Serial.println(); // Switch on the LED if an 1 was received as first character if ((char)payload[0] == '1') { digitalWrite(BUILTIN_LED, LOW); // Turn the LED on (Note that LOW is the voltage level // but actually the LED is on; this is because // it is active low on the ESP-01) } else { digitalWrite(BUILTIN_LED, HIGH); // Turn the LED off by making the voltage HIGH } } void reconnect() { // Loop until we're reconnected while (!client.connected()) { Serial.print("Attempting MQTT connection..."); // Create a random client ID String clientId = "ESP8266Client-"; clientId += String(random(0xffff), HEX); // Attempt to connect if (client.connect(clientId.c_str())) { Serial.println("connected"); // Once connected, publish an announcement... client.publish("test/topic", "hello world"); // ... and resubscribe client.subscribe("inTopic"); } else { Serial.print("failed, rc="); Serial.print(client.state()); Serial.println(" try again in 5 seconds"); // Wait 5 seconds before retrying delay(5000); } } } void setup() { pinMode(BUILTIN_LED, OUTPUT); // Initialize the BUILTIN_LED pin as an output Serial.begin(115200); setup_wifi(); client.setServer(mqtt_server, 1883); client.setCallback(callback); } void loop() { if (!client.connected()) { reconnect(); } client.loop(); unsigned long now = millis(); if (now - lastMsg > 2000) { lastMsg = now; ++value; snprintf (msg, MSG_BUFFER_SIZE, "hello world #%ld", value); Serial.print("Publish message: "); Serial.println(msg); client.publish("test/topic", msg); } }
串口输出
14:25:01.014 -> ........ 14:25:05.270 -> WiFi connected 14:25:05.270 -> IP address: 14:25:05.270 -> 192.168.0.101 14:25:05.270 -> Attempting MQTT connection...failed, rc=-2 try again in 5 seconds 14:25:15.261 -> Attempting MQTT connection...failed, rc=-2 try again in 5 seconds
解决方法
1. 检查Mosquitto监听地址
默认Mosquitto可能仅监听本地回环地址(127.0.0.1),导致局域网设备无法访问:
- 打开Mosquitto配置文件(如
/etc/mosquitto/mosquitto.conf) - 注释掉
bind_address 127.0.0.1这一行 - 添加
bind_address 0.0.0.0允许所有IP访问 - 重启Mosquitto服务:
sudo systemctl restart mosquitto
2. 适配MQTT协议版本
PubSubClient默认仅支持MQTT 3.1.1,若Mosquitto协议配置严格,可能导致不兼容:
- 更新PubSubClient库到最新版本
- 或在Mosquitto配置文件中添加
protocol mqttv311强制使用对应协议
3. 调整连接超时参数
ESP8266网络延迟可能导致连接超时,在setup()函数中添加:
client.setTimeout(10000); // 设置10秒连接超时
4. 验证网络连通性
在setup_wifi()函数末尾添加代码,测试ESP8266与MQTT服务器的连通性:
Serial.print("Pinging MQTT server "); Serial.print(mqtt_server); Serial.print("..."); IPAddress mqttIp; if(mqttIp.fromString(mqtt_server)){ byte error = WiFi.ping(mqttIp); if(error == 0){ Serial.println(" success!"); } else { Serial.print(" failed, error code: "); Serial.println(error); } } else { Serial.println(" invalid IP address!"); }
5. 处理Broker认证(若开启)
如果Mosquitto启用了账号密码认证,修改client.connect调用,传入认证信息:
if (client.connect(clientId.c_str(), "你的MQTT用户名", "你的MQTT密码")) { // 连接成功逻辑 }
6. 缩短客户端ID
PubSubClient对客户端ID长度有限制(默认最长23字符),当前代码生成的ID刚好符合,但若Broker有特殊限制,可尝试缩短:
String clientId = "ESP-"; clientId += String(random(0xfff), HEX);
内容的提问来源于stack exchange,提问作者leonardus
相关产品推荐
相关产品推荐

