ESP32使用PubSubClient库无法连接ThingSpeak MQTT服务器求助
ESP32 PubSubClient 连接 ThingSpeak MQTT 失败问题排查与修复
问题根源分析
串口输出的 rc=-2 在 PubSubClient 库中表示连接建立失败,结合你使用 ThingSpeak 官方库能正常连接的情况,问题核心在于 PubSubClient 的配置不符合 ThingSpeak MQTT 的强制要求,主要有以下几点:
- 客户端ID错误:ThingSpeak MQTT 服务器要求客户端ID必须是你的ThingSpeak账户用户名,而非自定义字符串。
- 未使用SSL加密连接:当前ThingSpeak对明文MQTT连接(1883端口)的支持受限,官方推荐使用SSL加密端口(8883),而原代码用普通
WiFiClient不支持SSL。 - 订阅主题格式不完整:ThingSpeak的订阅主题需要包含读取API Key,原代码缺失该部分。
修复后的完整代码
#include <PubSubClient.h> #include <WiFi.h> #include <WiFiClientSecure.h> // WiFi配置 const char* ssid = "Singh"; const char* password = "12345678"; // ThingSpeak配置 const char* mqtt_server = "mqtt3.thingspeak.com"; const int mqtt_port = 8883; // SSL加密端口 const char* channel_id = "2322752"; const char* read_api_key = "GP5KY5DTF3RO3OEF"; const char* write_api_key = "OI7QW8PL9HSM7QX6"; const char* thingspeak_username = "你的ThingSpeak用户名"; // 替换为你的账户用户名! // 使用WiFiClientSecure支持SSL连接 WiFiClientSecure wifiClient; PubSubClient client(wifiClient); void callback(char* topic, byte* payload, unsigned int length) { Serial.print("Received message on topic: "); Serial.println(topic); Serial.print("Message: "); for (int i = 0; i < length; i++) { Serial.print((char)payload[i]); } Serial.println(); } void setup() { Serial.begin(115200); // 连接WiFi WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(1000); Serial.println("Connecting to WiFi..."); } Serial.println("Connected to WiFi"); // 跳过SSL证书验证(简化调试,生产环境建议添加官方根证书) wifiClient.setInsecure(); // 配置MQTT客户端 client.setServer(mqtt_server, mqtt_port); client.setCallback(callback); reconnect(); } void loop() { if (!client.connected()) { reconnect(); } client.loop(); // 生成随机值并发布到Field1 float value1 = random(100) + 0.5; char payload[50]; snprintf(payload, sizeof(payload), "field1=%.2f", value1); char write_topic[100]; snprintf(write_topic, sizeof(write_topic), "channels/%s/publish/%s", channel_id, write_api_key); if(client.publish(write_topic, payload)){ Serial.println("Data published successfully"); Serial.print("Payload: "); Serial.println(payload); } else { Serial.println("Failed to publish data"); } delay(10000); } void reconnect() { while (!client.connected()) { Serial.println("Attempting MQTT connection..."); // 使用ThingSpeak用户名作为客户端ID if (client.connect(thingspeak_username, read_api_key, "")) { Serial.println("Connected to MQTT server"); // 修正订阅主题格式:添加读取API Key char read_topic[100]; snprintf(read_topic, sizeof(read_topic), "channels/%s/subscribe/fields/field3/%s", channel_id, read_api_key); if(client.subscribe(read_topic)){ Serial.println("Subscribed to Field3 topic"); } else { Serial.println("Failed to subscribe to topic"); } } else { Serial.print("Failed to connect, rc="); Serial.print(client.state()); Serial.println(" Retrying in 5 seconds"); delay(5000); } } }
关键修改说明
- 客户端ID修正:将
client.connect的第一个参数替换为你的ThingSpeak账户用户名(登录时的用户名,不是邮箱)。 - 启用SSL连接:改用
WiFiClientSecure替代WiFiClient,使用8883端口,添加wifiClient.setInsecure()跳过证书验证。 - 订阅主题补全:在订阅主题末尾添加读取API Key,符合ThingSpeak的MQTT主题规范。
- 调试信息增强:增加发布结果的判断与输出,方便排查数据发布问题。
额外检查项
- 确认ThingSpeak的API Key与频道对应正确,且频道未被禁用。
- 检查ESP32的网络环境,确保8883端口未被防火墙或代理拦截。
- 更新PubSubClient库到最新版本,避免旧版本的兼容性问题。
内容的提问来源于stack exchange,提问作者Lakhwinder Singh
相关产品推荐
相关产品推荐

