me-no-dev / ESPAsyncWebServer

Async Web Server for ESP8266 and ESP32
3.59k stars 1.17k forks source link

page not loading after page refresh #1269

Open KnokTheBottle opened 1 year ago

KnokTheBottle commented 1 year ago

Hello, I am using the AsyncWebServer with SPIFFS and have the problem, that after a couple times of refreshing my webpage, the page only loads to about 2/3 (progress bar at the top) and if I refresh again, it doesnt even start loading. Also the entire AP is unreachable after that.

Sometimes I can refresh 10x until it happens and sometimes it even happens on the first time I try to load the page.

I am fairly new to developement with the ESP32, so I dont understand everything.

At first I thought something in my loop was blocking, but the problem is still there after deleting everything out of my loop. Does anyone know what causes this problem?

I have a /data Folder with 3 files (index.html, style.css, main.js) and I also read and write to /config.json to get and save some values.

Here are some code snippets of SPIFFS initialization, reading from /config.json and my http requests:

// Initialize SPIFFS
void initSPIFFS() {
  if (!SPIFFS.begin(true)) {
    Serial.println("An error has occurred while mounting SPIFFS");
  }
  Serial.println("SPIFFS mounted successfully");
}

// Read Config
void readConfig() {
  //read configuration from FS json
  Serial.println("mounting FS...");

  if (true) { //SPIFFS.begin()
    Serial.println("mounted file system");
    if (SPIFFS.exists(filePath)) {
      //file exists, reading and loading
      Serial.println("reading config file");
      File configFile = SPIFFS.open(filePath, "r");
      if (configFile) {
        Serial.println("opened config file");
        size_t size = configFile.size();
        // Allocate a buffer to store contents of the file.
        std::unique_ptr<char[]> buf(new char[size]);

        configFile.readBytes(buf.get(), size);

#ifdef ARDUINOJSON_VERSION_MAJOR >= 6
        DynamicJsonDocument json(1024);
        auto deserializeError = deserializeJson(json, buf.get());
        serializeJson(json, Serial);
        if ( ! deserializeError ) {
#else
        DynamicJsonBuffer jsonBuffer;
        JsonObject& json = jsonBuffer.parseObject(buf.get());
        json.printTo(Serial);
        if (json.success()) {
#endif
          Serial.println("\nparsed json");
          strcpy(mode, json["mode"]);
          strcpy(btDeviceName, json["btDeviceName"]);
          strcpy(baud, json["baud"]);
          strcpy(pass, json["pass"]);
          strcpy(layout, json["layout"]);
        } else {
          Serial.println("failed to load json config");
        }
        configFile.close();
      }
    }
  } else {
    Serial.println("failed to mount FS");
  }
  //end read
}

// Write to Config
void writeToConfigFile(){
  #ifdef ARDUINOJSON_VERSION_MAJOR >= 6
    DynamicJsonDocument json(1024);
  #else
    DynamicJsonBuffer jsonBuffer;
    JsonObject& json = jsonBuffer.createObject();
  #endif

  json["mode"] = mode;
  json["btDeviceName"] = btDeviceName;
  json["baud"] = baud;
  json["pass"] = pass;
  json["layout"] = layout;

  File configFile = SPIFFS.open("/config.json", "w");
  if (!configFile) {
    Serial.println("failed to open config file for writing");
  }

  #ifdef ARDUINOJSON_VERSION_MAJOR >= 6
    serializeJson(json, Serial);
    serializeJson(json, configFile);
  #else
    json.printTo(Serial);
    json.printTo(configFile);
  #endif
  configFile.close();
}

void setup() {
// Serial port for debugging purposes
  Serial.begin(115200);
  Serial2.begin(atoi(baud), SERIAL_8N1, RXD2, TXD2);
  Serial2.setTimeout(500);

  initSPIFFS();
  readConfig();

  WiFi.mode(WIFI_AP);
  WiFi.softAP(deviceNameLong, pass);

  IPAddress IP = WiFi.softAPIP();
  Serial.print("AP IP address: ");
  Serial.println(IP);

  // Web Server Root URL
  server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(SPIFFS, "/index.html", "text/html");

  });

  server.serveStatic("/", SPIFFS, "/");

  server.on("/", HTTP_POST, [](AsyncWebServerRequest *request)
            {
    Serial.println(request->host());
    int params = request->params();
    for(int i=0;i<params;i++){
      AsyncWebParameter* p = request->getParam(i);
      if(p->isPost()){
        if (p->name() == PARAM_INPUT_1) {

          String modeStr = p->value().c_str();
          strcpy(mode, modeStr.c_str());
          Serial.print("Mode set to: ");
          Serial.println(mode);
        }
        // HTTP POST name value
        if (p->name() == PARAM_INPUT_2) {
          String deviceNameStr = p->value().c_str();
          if(deviceNameStr == ""){
            Serial.println("Name not set");
            continue;
          }
          Serial.println("continue failed");
          strcpy(btDeviceName, deviceNameStr.c_str());
          Serial.print("DeviceName set to: ");
          Serial.println(btDeviceName);
        }
        .
        . // Param 3-5
        .
      }
      writeToConfigFile();
    }
    if(newPass){
      request->send(200, "text/plain", "Done. Module will restart\r\nNew Password set!");
    }else{
      request->send(200, "text/plain", "Done. Module will restart\r\nNo Password set, or invalid!\r\nPassword needs to have at least 8 Characters!");
    }
    delay(3000);
    ESP.restart();
  });

  server.on("/connect", HTTP_POST, [](AsyncWebServerRequest *request){
    Serial.println("Connect Post Request");
    bool updateMode = false;
    if(BTconnected){
      Serial.println("Bluetooth already connected!");
      return;
    }
    if((String)mode != "2"){
      Serial.println("Mode not set to Master! Updating mode and restarting!");
      updateMode = true;
    }

    int params = request->params();
    for(int i=0;i<params;i++){
      AsyncWebParameter* p = request->getParam(i);
      if(p->isPost()){
        if (p->name() == PARAM_INPUT_1) {

          String modeStr = p->value().c_str();
          strcpy(mode, modeStr.c_str());
          Serial.print("Mode set to: ");
          Serial.println(mode);
        }
        // HTTP POST name value
        if (p->name() == PARAM_INPUT_2) {
          String deviceNameStr = p->value().c_str();
          if(deviceNameStr == ""){
            Serial.println("Name not set");
            continue;
          }
          strcpy(btDeviceName, deviceNameStr.c_str());
          Serial.print("DeviceName set to: ");
          Serial.println(btDeviceName);
        }
      }
    }
    writeToConfigFile();
    if(updateMode){
      request->send(200, "text/plain", "Mode not set to 'Bluetooth Master'.\r\nUpdating mode and connecting to " + (String)btDeviceName + "...\r\nRestarting Module!");
      ESP.restart();
      return;
    }

    request->send(200, "text/plain", "Connecting to " + (String)btDeviceName + "... Please wait!");

    if(btDeviceName != ""){
      connectBtFlag = true;
    }
    //request->send(SPIFFS, "/index.html", "text/html");
  });
  server.begin();
}

Sorry for the long post, I want to give all the information i can.

Best regards

StefanoTesla commented 1 year ago

u sure that the cpu don't go in fatal error??

KnokTheBottle commented 1 year ago

Yes I'm sure. I have Serial Bluetooth running in the background and when the AsyncWebServer doesnt respond anymore, I can still connect via Bluetooth.

Aryan1718 commented 1 year ago

Check your memory usage to ensure you have enough memory to handle the data, as sometimes insufficient memory can cause issues with serving the data.

stale[bot] commented 1 year ago

[STALE_SET] This issue has been automatically marked as stale because it has not had recent activity. It will be closed in 14 days if no further activity occurs. Thank you for your contributions.