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

ESP32作为AP接收POST请求触发panic重启及JSON传参问题求助

ESP32 AP模式POST请求崩溃问题排查与JSON传输实现

一、POST请求触发panic重启的排查步骤

  • 优先抓取串口崩溃日志:ESP32触发panic时会通过串口输出错误详情,将串口波特率设为115200,抓取崩溃时的Guru Meditation Error错误码,最常见的错误原因为非法内存访问、栈溢出、堆越界,可直接定位问题方向。
  • 检查AsyncWebServer POST回调写法:

    绝大多数崩溃都是因为未正确处理POST请求体,SPAsyncWebServer不能直接在主回调中调用request->content()读取全量数据,请求体超过默认buffer大小时会直接触发内存越界,必须注册onBody回调分段接收数据。

  • 检查参数解析的边界处理:如果使用strcpy、sscanf等无边界校验的函数解析字符串,或者未限制输入长度,下发的WiFi凭证超出buffer大小时会触发栈溢出。需提前校验:SSID最长32字符、WiFi密码最长64字符,超出阈值直接返回错误,不进入后续处理逻辑。
  • 检查内存占用:POST处理过程中如果频繁使用String类拼接字符串、申请动态内存未释放,会导致堆内存不足或碎片化,可在回调前后打印ESP.getFreeHeap()的返回值,排查内存泄漏问题。
  • 检查WiFi连接逻辑:如果在AsyncWebServer的回调中直接执行WiFi.begin()切换STA模式,会和正在运行的WebServer服务产生资源冲突,直接触发崩溃。正确做法是在POST回调中仅将凭证存储到全局变量、标记连接标志位,在loop()函数中异步执行WiFi连接逻辑,不要在WebServer回调中执行任何阻塞/修改网络状态的操作。

二、JSON格式数据传输实现

ESP32侧实现

首先安装ArduinoJson库,参考代码如下:

#include <ArduinoJson.h>
#include <ESPAsyncWebServer.h>

// 全局变量存储WiFi凭证和连接标志
char global_ssid[33] = {0};
char global_pwd[65] = {0};
uint8_t wifi_connect_flag = 0;
String post_body;
AsyncWebServer server(80);

void setup(){
  // 省略AP初始化、串口初始化代码
  server.on("/setWiFi", HTTP_POST, [](AsyncWebServerRequest *request){
    // 全量body接收完成后处理
    if(post_body.length() > 0){
      StaticJsonDocument<256> doc;
      DeserializationError err = deserializeJson(doc, post_body);
      if(err){
        request->send(400, "application/json", "{\"code\":400,\"msg\":\"JSON格式错误\"}");
      }else{
        const char* recv_ssid = doc["ssid"];
        const char* recv_pwd = doc["pwd"];
        strncpy(global_ssid, recv_ssid, sizeof(global_ssid)-1);
        strncpy(global_pwd, recv_pwd, sizeof(global_pwd)-1);
        wifi_connect_flag = 1;
        request->send(200, "application/json", "{\"code\":200,\"msg\":\"凭证接收成功\"}");
      }
      post_body.clear();
    }else{
      request->send(400, "application/json", "{\"code\":400,\"msg\":\"请求体为空\"}");
    }
  }, NULL, [](AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t index, size_t total){
    // 分段接收请求体
    if(!index){
      post_body.clear();
      // 提前拦截过大的请求体,避免内存溢出
      if(total > 256){
        request->send(413, "application/json", "{\"code\":413,\"msg\":\"请求体过大\"}");
        return;
      }
    }
    for(size_t i=0; i<len; i++){
      post_body += (char)data[i];
    }
  });
  server.begin();
}

void loop(){
  // 异步执行WiFi连接
  if(wifi_connect_flag == 1){
    wifi_connect_flag = 0;
    WiFi.begin(global_ssid, global_pwd);
    // 省略WiFi连接状态判断逻辑
  }
}

Python侧请求代码

import requests

# ESP32 AP模式默认IP为192.168.4.1
ESP_AP_IP = "192.168.4.1"
wifi_config = {
    "ssid": "待接入的WiFi名称",
    "pwd": "待接入的WiFi密码"
}

try:
    response = requests.post(f"http://{ESP_AP_IP}/setWiFi", json=wifi_config, timeout=5)
    response.raise_for_status()
    print("下发成功:", response.json())
except Exception as e:
    print("请求失败:", str(e))

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 05:06:00