Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Should I migrate from ESPAsyncWebServer to WebServer ?! #2677

Closed
GeorgeFlorian opened this issue Apr 16, 2019 · 6 comments

Comments

Projects
None yet
2 participants
@GeorgeFlorian
Copy link

commented Apr 16, 2019

OS: Linux Mint 19.1
Board: ESP32 Wrover-B DevKitV4
Display: 2727 SMD P5 64x32

Hello !

Recently I've tried integrating a LED Display Library inside my project, which uses SPIFFS + ESPAsyncWebServer to serve some web-pages while in AP Mode and some other web-pages while in STA Mode.

The problem is that the LED Library is not compatible with the SPIFFS file system.

The LED Library uses the following functions to work:

void IRAM_ATTR display_updater(){
  // Increment the counter and set the time of ISR
  portENTER_CRITICAL_ISR(&timerMux);
  display.display(display_draw_time);
  portEXIT_CRITICAL_ISR(&timerMux);
}

void display_update_enable(bool is_enable){
  if (is_enable) {
    timer = timerBegin(0, 80, true);
    timerAttachInterrupt(timer, &display_updater, true);
    timerAlarmWrite(timer, 2000, true);
    timerAlarmEnable(timer);
  }
  else  {
    timerDetachInterrupt(timer);
    timerAlarmDisable(timer);
  }
}

I should close the display when manipulating a SPIFFS file and then open it. So let's say:

  server.on("/url", HTTP_GET, [](AsyncWebServerRequest *request){
    display_update_enable(false);
    request->send(SPIFFS, "/url_page.html", "text/html");
  });
  server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
    display_update_enable(false);
    request->redirect("/url");
  });

That should work.

But I have a HTTP Client inside void loop() that constantly GETs the body of a URL. The URL is stored in a txt file inside the ESP and I need SPIFFS to access it. So, again, I need to close the display before SPIFFS.open() and open it after I finish with the SPIFFS.

void loop() {
  display_update_enable(false);
  if (WiFi.status() == WL_CONNECTED) {  //Check the current connection status 
    File urlRead = SPIFFS.open("/urlFile.txt");
    if(!urlRead) logOutput((String)"ERROR_INSIDE_loop ! Couldn't open file to read !");

    if(urlRead.size() > 10) {
      HTTPClient http;
      String URL;
      logOutput((String)"URL: ");
      fileReadLines(urlRead, &URL);
      http.begin(URL); //Specify the URL
      urlRead.close();
      display_update_enable(true);
      int httpCode = http.GET(); //Make the request
  
      if (httpCode > 0) { //Check for the returning code
        logOutput((String)"[HTTP] GET... code: " + httpCode);
        if(httpCode == HTTP_CODE_OK) {
            String payload = http.getString();
            logOutput(payload);
            getPlaces(payload);
          }
      } else {
          logOutput((String)"[HTTP] GET... failed, error: " + http.errorToString(httpCode).c_str());
        }  
      http.end(); //Free the resources
      } else {
        logOutput("URL Link is invalid ! Please enter another URL");
      }
  }
  display.clearDisplay();
  display.print(payload);
  delay(3000);
}

Again, this is good and all, but the problem is that the ESPAsyncWebServer is always on.
I can access a web-page while void loop is going like crazy and I have no means to know when I access a web-page.

This means that the display can be on while I try to access a web-page that's stored in SPIFFS.
Trying to access http://*myIP* or http://*myIP*/url sometimes work, sometimes it returns A LOT of Guru Meditation Errors.
If I access one of the respective web-page it's like walking on thin ice, because if I refresh it, it can always break.

I thought of some things but I don't really know which one to try and implement:

  1. I would like to try to check for client connection inside the loop. If there's a connection on one of the web-pages then close the display, else keep the display up. But I couldn't figure out a way to do this with ESPAsyncWebServer.

  2. Like the title says, I would like to know if migrating from ESPAsyncWebServer to the normal WebServer provided by arduino-esp32 would be a solution. But I've never worked with it and I don't know if I can use SPIFFS with it, I have no idea how to process GET or POST parameters.

How do I do the following with WebServer.h ?

  server.on("/url", HTTP_GET, [](AsyncWebServerRequest *request){
    display_update_enable(false);
    request->send(SPIFFS, "/url_page.html", "text/html");
  });
  server.on("/url", HTTP_POST, [](AsyncWebServerRequest * request){
    display_update_enable(false);
    int params = request->params();
    String URL;
    for(int i=0;i<params;i++){
      AsyncWebParameter* p = request->getParam(i);
        if(p->isPost()){
          Serial.println((String)"POST[" + p->name().c_str() + "]: " + p->value().c_str() + "\n");             
          URL = p->value();      
        } else {
            Serial.println((String)"GET[" + p->name().c_str() + "]: " + p->value().c_str() + "\n"); 
          }
    } // for(int i=0;i<params;i++)
    
    if(URL != NULL && URL.length() != 0) {
      File urlWrite = SPIFFS.open("/urlFile.txt", "w");
      if(!urlWrite) Serial.println((String)"ERROR_INSIDE_URL_POST ! Couldn't open file to write URL !");
      urlWrite.println(URL);
      urlWrite.close();
      request->redirect("/url");
    } else {
      request->redirect("/url");
    }
  });  
  1. Is there any other LED Library that doesn't rely as heavily as PxMatrix on IRAM_ATTR functions and interrupts so that it would be possible to work with SPIFFS, ESPAsyncWebServer and HTTPClient ?

Thank you and sorry for the long post !

@GeorgeFlorian GeorgeFlorian changed the title How to go from ESPAsyncWebServer to WebServer ?! Should I migrate from ESPAsyncWebServer to WebServer ?! Apr 16, 2019

@atanisoft

This comment has been minimized.

Copy link
Contributor

commented Apr 16, 2019

Moving to WebServer won't fix your issue. The problem is your display_updater method is doing things it shouldn't be doing inside an ISR context.

@GeorgeFlorian

This comment has been minimized.

Copy link
Author

commented Apr 16, 2019

Moving to WebServer won't fix your issue. The problem is your display_updater method is doing things it shouldn't be doing inside an ISR context.

The problem is that it isn't my method. It's the library's method: https://github.com/2dom/PxMatrix

@atanisoft

This comment has been minimized.

Copy link
Contributor

commented Apr 16, 2019

Then file a bug against that library. It isn't the fault of the AsyncWebServer code, nor does this issue really belong here.

@atanisoft

This comment has been minimized.

Copy link
Contributor

commented Apr 16, 2019

Another option you can try is use the Ticker library instead of a hardware timer to update your display every 2000ms (roughly).

@GeorgeFlorian

This comment has been minimized.

Copy link
Author

commented Apr 16, 2019

Then file a bug against that library. It isn't the fault of the AsyncWebServer code, nor does this issue really belong here.

That wouldn't fix a thing, as I've already tried communicating with the developer but to no avail.

Another option you can try is use the Ticker library instead of a hardware timer to update your display every 2000ms (roughly).

Can you leave more pointers to how should I start doing that ?

@atanisoft

This comment has been minimized.

Copy link
Contributor

commented Apr 16, 2019

If the original developer won't help you with their code that is unfortunate. I can't help you with their code either.

The Ticker library is available with examples in this repo I believe.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.