You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现基于ESP32的MQTT连接AWS设备稳定运行并避免锁定

ESP32 AWS IoT Core 连接稳定性问题排查与解决方案需求

设备基础信息

  • 硬件:ESP32 WROOM开发板
  • 开发环境:VS Code + PlatformIO,基于Arduino框架
  • 核心依赖库:Arduino、WiFiClientSecure、MQTTClient、ArduinoJson、WiFi、time
  • 业务逻辑:单设备通过专属主题每5-60秒向AWS IoT Core上报数据
  • 供电方式:5V手机充电器

问题现象

设备运行一段时间后(无固定周期),AWS IoT Core停止接收设备上报的消息,但设备串口打印输出正常,且无法通过MQTT消息触发设备重启,必须手动复位才能恢复。需构建可靠解决方案,但无法长期进行串口调试,同时对MQTT遗嘱消息的用法存在疑问。

代码框架

#include <Arduino.h>
#include <secret.h> //change
#include <WiFiClientSecure.h>
#include <MQTTClient.h>
#include <ArduinoJson.h>
#include <WiFi.h>
#include "time.h"


#define AWS_IOT_PUBLISH_TOPIC   "topic/pub" //change
#define AWS_IOT_SUBSCRIBE_TOPIC "topic/sub" //change


const byte relay_gpio = 16; // the relay
const char* ntpServer = "pool.ntp.org"; // timeserver
const long  gmtOffset_sec = 3600; 
const int   daylightOffset_sec = 3600;
int relayState = 0;

String IoTID = "IoTID";
String sensorID = "IoTID_1"; //change

WiFiClientSecure net = WiFiClientSecure();
MQTTClient client = MQTTClient(1024);

void messageHandler(String &topic, String &payload)
{
  Serial.println("alive");
  // deserialize json
  StaticJsonDocument<200> doc;
  deserializeJson(doc, payload);
  String message = doc["message"];
  Serial.println(message);
  if (message == "restart"){
    ESP.restart();
  }
  if (message == "remote_on"){
    digitalWrite(relay_gpio, HIGH);  
  }
  if (message == "remote_off"){
    digitalWrite(relay_gpio, LOW);
  }
}

void connectAWS()
{
  WiFi.mode(WIFI_STA);
  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
  Serial.println("Connecting to Wi-Fi");
 
  while (WiFi.status() != WL_CONNECTED)
  {
    delay(500);
    Serial.print(".");
  }
 
  // Configure WiFiClientSecure to use the AWS IoT device credentials
  net.setCACert(AWS_CERT_CA);
  net.setCertificate(AWS_CERT_CRT);
  net.setPrivateKey(AWS_CERT_PRIVATE);
 
  // Connect to the MQTT broker on the AWS endpoint we defined earlier
  client.begin(AWS_IOT_ENDPOINT, 8883, net);
 
  // Create a message handler
  client.onMessage(messageHandler);
  
  Serial.println("Connecting to AWS IOT");
 
  while (!client.connect(THINGNAME))
  {
    Serial.print(".");
    delay(100);
  }
 
  if (!client.connected())
  {
    Serial.println("AWS IoT Timeout!");
    return;
  }
 
  // Subscribe to a topic
  client.setCleanSession(false); // That's one thing that was recommended
  client.subscribe(AWS_IOT_SUBSCRIBE_TOPIC);
  //client.setOptions(60, false, 2000); // I tried some of those, but with either none or negative effects

  Serial.println("AWS IoT Connected!");
}

void publishMessage()
{
StaticJsonDocument<256> doc;

doc["IoTID"] = IoTID;

JsonObject meta_0 = doc["meta"].createNestedObject();
meta_0["SensorID"] = sensorID;
meta_0["key"] = "XX";
meta_0["latitude"] = 12.345;
meta_0["longitude"] = 67.890;
meta_0["LocName"] = "Somewhere";
meta_0["TimeCET"] = time(NULL);

JsonObject data_0 = doc["data"].createNestedObject();
data_0["switch_state"] = relayState;
char jsonBuffer[512];
serializeJson(doc, jsonBuffer);
 
client.publish(AWS_IOT_PUBLISH_TOPIC, jsonBuffer);
}


//

void setup() {
  pinMode(relay_gpio, OUTPUT);
  Serial.begin(9600);
  configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
  connectAWS(); //always connects. so far so good
}

void loop() {

  
  client.loop();  // Putting this
  delay(10);   // and this at the beginning of the loop improved stability and was recommended
  relayState  = digitalRead(relay_gpio);

  if (!client.connected()){
    client.connect(THINGNAME);
    client.loop();
  }

  client.onMessage(messageHandler);
  

  if (isnan(relayState)) {
    Serial.println("measurement error - waiting");
    delay(5000);
    ESP.restart();
  }

  lwmqtt_err_t lastError(); // for serial debugging
  lwmqtt_return_code_t returnCode();  // for serial debugging


  Serial.print(F("relayState: "));
  Serial.print(relayState);
  Serial.print(F(", Timestamp:"));
  Serial.println(time(NULL));
  if(time(NULL) > 1e9){ //make sure connection to timeserver is established
    publishMessage();
  }
  delay(5000);
  
} 

已尝试的解决措施

  • 替换MQTT库:从PubSubClient切换到MQTTClient,稳定性有所提升
  • 优化循环逻辑:在client.loop()后添加10ms延迟
  • 调整JSON缓冲区大小
  • 测试不同循环延迟:延迟越短,稳定性相对越好
  • 添加定时自动重启:22小时自动重启,无改善
  • 添加远程重启指令:仅在设备未出现连接锁定时有效

内容的提问来源于stack exchange,提问作者Chris Kn

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 20:14:59