espressif / arduino-esp32

Arduino core for the ESP32
GNU Lesser General Public License v2.1
13.56k stars 7.4k forks source link

WebServer.h fails to redirect #4855

Closed wuzamarine closed 3 years ago

wuzamarine commented 3 years ago

Make your question, not a Statement, inclusive. Include all pertinent information:

What you are trying to do? submit html form Describe your system( Hardware, computer, O/S, core version, environment). Linux Android and SUSE Describe what is failing. server.sendHeader("Location", String("/"), true); fails intermittently. mostly fail.

Show the shortest possible code that will duplicate the error. https://controlc.com/c7032fa7 Show the EXACT error message(it doesn't work is not enough). https://i.imgur.com/TZyO9Wc.png All of this work on your part shows us that you have worked to solve YOUR problem. The more complete your issue posting is, the more likely someone will volunteer their time to help you. https://arduino.stackexchange.com/posts/81632/edit

If you have a Guru Meditation Error or Backtrace, please decode it: https://github.com/me-no-dev/EspExceptionDecoder

----------------------------- Remove above -----------------------------

Hardware:

Board: ESP32 Dev Module Core Installation version: 1.8.2 IDE name: Arduino IDE Flash Frequency: ?40Mhz? PSRAM enabled: ?no? ?yes? Upload Speed: 115200 Computer OS: Ubuntu, SUSE

Description:

Describe your problem here

I am trying to create a simple form and upon user clicking submit, connection will reset "most of the time" before user is redirected.

server.sendHeader("Location", String("/"), true);

appears to fail 80% of the time

Sketch: (leave the backquotes for code formatting)


//Change the code below by your sketch
#include <IRremote.h>

    //IRsend IrSender;

    // On the Zero and others we switch explicitly to SerialUSB
    #if defined(ARDUINO_ARCH_SAMD)
    #define Serial SerialUSB
    #endif

    int led_pin = 3; //pin is set to d4 on board but pin 3 here. Just the way it works out.

    //new networking stuff

    #include <WiFi.h>
    #include <WiFiClient.h>
    #include <WebServer.h>
    #include <ESPmDNS.h>

    const char *ssid = "";
    const char *password = "";

    //used for counting cycles later. Safety feature for overwatering
    int CYCLE0;
    int CYCLE1;

    WebServer server(80);

    // Current time
    unsigned long currentTime = millis();
    // Previous time
    unsigned long previousTime = 0; 
    // Define timeout time in milliseconds (example: 2000ms = 2s)
    const long timeoutTime = 2000;

    // Set your Static IP address
    IPAddress local_IP(192, 168, 1, 244);
    // Set your Gateway IP address
    IPAddress gateway(192, 168, 1, 1);

    IPAddress subnet(255, 255, 255, 0);
    IPAddress primaryDNS(1, 1, 1, 2);   //optional
    IPAddress secondaryDNS(1, 0, 0, 2); //optional

    void response(){
      int khz = 38; // 38kHz carrier frequency for the NEC protocol

      if(server.hasArg("on") && (server.arg("on").length()>0)){ // TODO check that it's not longer than 31 characters
          unsigned short irSignal0[] = {550,550, 550,1550, 600,500, 600,500, 550,1600, 550,550, 550,500, 600,500, 600,500, 600,500, 550,1600, 550,550, 550,1550, 600,1550, 550,550, 550,550, 550,550, 550,500, 600,500, 600,1550, 550,550, 550,550, 550,550, 550,500, 600,500, 550,1600, 550,1600, 550,550, 550,1550, 550,1600, 550,550, 550,550, 550,500, 600,500, 600,500, 550,550, 550,550, 550,550, 550,550, 550,500, 600,500, 600,500, 550,550, 550,550, 550,500, 600,500, 600,500, 600,1550, 550,550, 550,550, 550,550, 550,500, 600,500, 550,550, 550,550, 550,550, 550,550, 550,500, 600,500, 550,550, 550,550, 550,550, 550,550, 550,500, 600,500, 600,1550, 550,1600, 550,1550, 600,1550, 550,1600, 550,550, 550,1550, 550}; // AnalysIR Batch Export (IRremote) - RAW
          unsigned short temphackdown0[] = {600,500, 550,1600, 550,550, 550,500, 600,1550, 550,550, 550,550, 550,550, 550,550, 550,500, 600,1550, 550,550, 550,1600, 550,1600, 550,500, 600,500, 550,1600, 550,550, 550,550, 550,1550, 600,500, 550,1600, 550,550, 550,550, 550,1550, 600,500, 550,1600, 550,550, 550,550, 550,1550, 600,500, 550,550, 550,550, 550,550, 550,500, 600,500, 600,500, 600,500, 550,550, 550,550, 550,500, 600,500, 600,500, 600,500, 550,550, 550,550, 550,550, 550,1550, 600,500, 600,500, 550,550, 600,500, 550,500, 600,500, 600,500, 600,500, 600,500, 600,500, 600,500, 550,500, 600,500, 600,500, 600,500, 600,500, 600,500, 550,1550, 600,1550, 600,1550, 600,500, 550,500, 600,1550, 600,1550, 550};
          IrSender.sendRaw(irSignal0, sizeof(irSignal0) / sizeof(irSignal0[0]), khz); // Note the approach used to automatically calculate the size of the array.
          Serial.print("AC was turned on:\t");
          Serial.println(server.arg("on"));
          //hack to get temp to correct setting when turned on
          delay(2500);
          //hack to set at 72 degree (plucked from a dump)
          IrSender.sendRaw(temphackdown0, sizeof(temphackdown0) / sizeof(temphackdown0[0]), khz);
          ++CYCLE0;
          server.sendHeader("Location", String("/"), true); //how to do a redirect, next two lines
          server.send ( 302, "text/plain", "");
      } else {
        server.send(400, "text/html", "<html><body><h1>HTTP Error 400</h1><p>Bad request. Please enter a value.</p></body></html>");
      }
    }

    void handleRoot() {
      digitalWrite(led_pin, 1);
      char temp[1500];
      int sec = millis() / 1000;
      int min = sec / 60;
      int hr = min / 60;

      snprintf(temp, 1500,

               "<html>\
      <head>\
        <meta http-equiv='' content=''/>\
        <title>ESP32 Demo</title>\
        <style>\
          body { background-color: #cccccc; font-family: Arial, Helvetica, Sans-Serif; Color: #000088; }\
        </style>\
      </head>\
      <body>\
        <h1>Get the fuck off my ESP32s device #2!</h1>\
        <p>Uptime: %02d:%02d:%02d</p>\
        <h2>Turn air condistioner on</h2> \n\
        <p>AC has been cycled %d times</p> \n\
        <form name='frm0' method='post'> \
          <input type='text' name='on' value=8000> \
          <input type='submit' value='Submit'> \
        </form> \n\
      </body>\
    </html>",

               hr, min % 60, sec % 60, CYCLE0, CYCLE1
              );
      server.send(200, "text/html", temp);
      digitalWrite(led_pin, 0);
    }

    void handleNotFound() {
      digitalWrite(led_pin, 1);
      String message = "File Not Found\n\n";
      message += "URI: ";
      message += server.uri();
      message += "\nMethod: ";
      message += (server.method() == HTTP_GET) ? "GET" : "POST";
      message += "\nArguments: ";
      message += server.args();
      message += "\n";

      for (uint8_t i = 0; i < server.args(); i++) {
        message += " " + server.argName(i) + ": " + server.arg(i) + "\n";
      }

      server.send(404, "text/plain", message);
      digitalWrite(led_pin, 0);
    }

    void setup() {
        pinMode(led_pin, OUTPUT);

        Serial.begin(115200);

    #if defined(__AVR_ATmega32U4__) || defined(SERIAL_USB) || defined(SERIAL_PORT_USBVIRTUAL)
        delay(2000); // To be able to connect Serial monitor after reset and before first printout
    #endif
        // Just to know which program is running on my Arduino
        Serial.println(F("START " __FILE__ " from " __DATE__));
        Serial.print(F("Ready to send IR signals at pin "));
        Serial.println(IR_SEND_PIN);

        pinMode(led_pin, OUTPUT);
        digitalWrite(led_pin, 0);
        //Serial.begin(115200);

        WiFi.mode(WIFI_STA);
        WiFi.begin(ssid, password);
        Serial.println("");

        // Configures static IP address
        if (!WiFi.config(local_IP, gateway, subnet, primaryDNS, secondaryDNS)) {
          Serial.println("STA Failed to configure");
        }     
         // Wait for connection
        while (WiFi.status() != WL_CONNECTED) {
          delay(500);
          Serial.print(".");
        }

        Serial.println("");
        Serial.print("Connected to ");
        Serial.println(ssid);
        Serial.print("IP address: ");
        Serial.println(WiFi.localIP());

        if (MDNS.begin("esp32")) {
          Serial.println("MDNS responder started");
        }

        //server.on("/", handleRoot);
        server.on("/",HTTP_POST,response);
        server.on("/",HTTP_GET, handleRoot);
        server.on("/inline", []() {
        server.send(200, "text/plain", "this works as well");
        });
        server.onNotFound(handleNotFound);
        server.begin();
        Serial.println("HTTP server started");

    }

    void loop() {

        //new networking stuff
        server.handleClient();
        Serial.print("\nesp32s infrared AC server device 2");

        //esp_task_wdt_reset();
        delay(1500);
    }
### Debug Messages:

Enable Core debug level: Debug on tools menu of Arduino IDE, then put the serial output here


https://i.imgur.com/TZyO9Wc.png

The connection was reset

The connection to the server was reset while the page was loading.
me-no-dev commented 3 years ago

you forgot the output on the serial port with debug enabled :)

wuzamarine commented 3 years ago

@me-no-dev Forgive me but, how do you enable verbose debugging on the serial port? I have never seen this done before.

The connection reset for the URL is the most verbose output I can find.

Here is the serial output.

10:37:33.303 -> esp32s infrared AC server device 2 10:37:34.795 -> esp32s infrared AC server device 2 10:37:36.287 -> esp32s infrared AC server device 2 10:37:37.813 -> esp32s infrared AC server device 2 10:37:39.306 -> esp32s infrared AC server device 2 10:37:40.799 -> esp32s infrared AC server device 2 10:37:42.291 -> esp32s infrared AC server device 2AC was turned off: 8000 10:37:43.888 -> 10:37:43.922 -> esp32s infrared AC server device 2 10:37:45.414 -> esp32s infrared AC server device 2 10:37:46.907 -> esp32s infrared AC server device 2 10:37:48.399 -> esp32s infrared AC server device 2 10:37:49.926 -> esp32s infrared AC server device 2

It just dies in the background with no error but what's in the URL/browser.

If you can tell me what debuggers you would like, I'll be more than happy to run them. I just need to know what they are.

There is a wireshark image of a capture session in the URL presented.

lbernstone commented 3 years ago

Set your board to "ESP32 Dev Module", and you will see the core debug menu under tools. You should set WiFi.setSleep(false); for a device you intend to use for web service. This should take about 750-1000ms off your response times.

me-no-dev commented 3 years ago

@lbernstone there is a delay(2500); in the handler :)

wuzamarine commented 3 years ago

@me-no-dev Thank you so much

stale[bot] commented 3 years 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.

stale[bot] commented 3 years ago

[STALE_DEL] This stale issue has been automatically closed. Thank you for your contributions.