ESP32 Webserver Problem

Hallo zusammen.

Leider habe ich ein Verständnisproblem beim Senden einer Seite eines Webservers. Es werden über Tastendrücke ein Wert nach oben oder unten geändert.

Der stark gekürzte Sketch welcher funktioniert ist hier:

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


// Generator variables
bool newval = 0;
float val1 = 10.0;
uint8_t maxval1 = 100;

// Network credentials
const char* ssid = "esptest";      // Enter SSID here
const char* password = "esptest";  // Enter Password here

/* Put IP Address details */
IPAddress local_ip(192, 168, 0, 1);
IPAddress gateway(192, 168, 0, 1);
IPAddress subnet(255, 255, 255, 0);

// Set web server port number to 80
WebServer server(80);

void setup() {
  Serial.begin(115200);

  WiFi.softAP(ssid, password);
  WiFi.softAPConfig(local_ip, gateway, subnet);
  delay(100);

  server.on("/", handle_OnConnect);
  server.on("/val1sub", handle_val1sub);
  server.on("/val1add", handle_val1add);
  server.onNotFound(handle_NotFound);

  server.begin();
  Serial.println("HTTP server started");
}

void loop() {
  if (newval == 1) {
    Serial.println("newval");
    newval = 0;
  }
  server.handleClient();
}

void handle_OnConnect() {
  server.send(200, "text/html", SendHTML());
}

void handle_val1sub() {
  if (val1 > 1.0) {
    val1--;
    newval = 1;
  }
  server.send(200, "text/html", SendHTML());
}

void handle_val1add() {
  if (val1 < maxval1) {
    val1++;
    newval = 1;
  }
  server.send(200, "text/html", SendHTML());
}

void handle_NotFound() {
  server.send(404, "text/plain", "Page not found.");
}

String SendHTML() {
  String ptr = "<!DOCTYPE html> <html>\n";
  ptr += "<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">\n";
  ptr += "<title>esptest</title>\n";
  ptr += "<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}\n";
  ptr += "body{margin-top: 10px;} h1 {color: #000000;margin: 10px auto 10px;} p {font-size: 14px;color: #000000;margin-bottom: 10px;}\n";
  ptr += ".button1 {display: block;width: 40px;background-color: #2e9afe;border: none;color: white;padding: 10px 10px; text-align: center; text-decoration: none;display: inline-block;font-size: 20px;margin: 0px auto;vertical-align: middle;cursor: pointer;border-radius: 4px;}\n";
  ptr += ".button2 {display: block;width: 40px; height: 40px;background-color: #2e9afe;border: none;color: white;padding: 30px 30px;  text-align: center; text-decoration: none;display: inline-block;font-size: 30px;margin: 0px auto;vertical-align: middle;cursor: pointer;border-radius: 4px;}\n";
  ptr += ".button1:active {background-color: #40ff00;}\n";  // Button1 color if pressed
  ptr += ".button2:active {background-color: #40ff00;}\n";  // Button2 color if pressed
  ptr += "</style>\n";
  ptr += "</head>\n";
  ptr += "<body>\n";
  ptr += "<p><h1>esptest</h1></p><br>\n";

  ptr += "<b><p>val1 = " + String(val1, 0) + "</p></b>\n";
  ptr += "<a class=\"button1\" href=\"/val1sub\">-</a>\n";
  ptr += "<a class=\"button1\" href=\"/val1add\">+</a>\n";
  ptr += "<br><br>\n";

  ptr += "</body>\n";
  ptr += "</html>\n";
  return ptr;
}

Nun würde ich aber gerne das Senden der Seite in die Loop verfrachten. Daher wird bei einem Tastendruck festgestellt dass sich der Wert geändert hat (newval = 1;) und server.send(200, "text/html", SendHTML()); ausgeführt. Danach newval = 0;.
Leider scheint das nicht zu funktionieren obwohl ich nicht ganz verstehe was der Unterschied in der Abfolge zum vorherigen Sketch sein soll. Der Fehler lautet "ERR_EMPTY_RESPONSE":

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


// Generator variables
bool newval = 0;
float val1 = 10.0;
uint8_t maxval1 = 100;

// Network credentials
const char* ssid = "esptest";      // Enter SSID here
const char* password = "esptest";  // Enter Password here

/* Put IP Address details */
IPAddress local_ip(192, 168, 0, 1);
IPAddress gateway(192, 168, 0, 1);
IPAddress subnet(255, 255, 255, 0);

// Set web server port number to 80
WebServer server(80);

void setup() {
  Serial.begin(115200);

  WiFi.softAP(ssid, password);
  WiFi.softAPConfig(local_ip, gateway, subnet);
  delay(100);

  server.on("/", handle_OnConnect);
  server.on("/val1sub", handle_val1sub);
  server.on("/val1add", handle_val1add);
  server.onNotFound(handle_NotFound);

  server.begin();
  Serial.println("HTTP server started");
}

void loop() {
  if (newval == 1) {
    Serial.println("newval");
    server.send(200, "text/html", SendHTML());
    newval = 0;
  }
  server.handleClient();
}

void handle_OnConnect() {
  server.send(200, "text/html", SendHTML());
}

void handle_val1sub() {
  if (val1 > 1.0) {
    val1--;
    newval = 1;
  }
}

void handle_val1add() {
  if (val1 < maxval1) {
    val1++;
    newval = 1;
  }
}

void handle_NotFound() {
  server.send(404, "text/plain", "Page not found.");
}

String SendHTML() {
  String ptr = "<!DOCTYPE html> <html>\n";
  ptr += "<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">\n";
  ptr += "<title>esptest</title>\n";
  ptr += "<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}\n";
  ptr += "body{margin-top: 10px;} h1 {color: #000000;margin: 10px auto 10px;} p {font-size: 14px;color: #000000;margin-bottom: 10px;}\n";
  ptr += ".button1 {display: block;width: 40px;background-color: #2e9afe;border: none;color: white;padding: 10px 10px; text-align: center; text-decoration: none;display: inline-block;font-size: 20px;margin: 0px auto;vertical-align: middle;cursor: pointer;border-radius: 4px;}\n";
  ptr += ".button2 {display: block;width: 40px; height: 40px;background-color: #2e9afe;border: none;color: white;padding: 30px 30px;  text-align: center; text-decoration: none;display: inline-block;font-size: 30px;margin: 0px auto;vertical-align: middle;cursor: pointer;border-radius: 4px;}\n";
  ptr += ".button1:active {background-color: #40ff00;}\n";  // Button1 color if pressed
  ptr += ".button2:active {background-color: #40ff00;}\n";  // Button2 color if pressed
  ptr += "</style>\n";
  ptr += "</head>\n";
  ptr += "<body>\n";
  ptr += "<p><h1>esptest</h1></p><br>\n";

  ptr += "<b><p>val1 = " + String(val1, 0) + "</p></b>\n";
  ptr += "<a class=\"button1\" href=\"/val1sub\">-</a>\n";
  ptr += "<a class=\"button1\" href=\"/val1add\">+</a>\n";
  ptr += "<br><br>\n";

  ptr += "</body>\n";
  ptr += "</html>\n";
  return ptr;
}

Wahrscheinlich ist die Erklärung relativ simpel :slight_smile:

Das vermute ich auch.

Der Webserver stellt Daten zur Verfügung, der Webclient fordert diese an. Die Initiative muß also vom Client ausgehen! Wenn Du auf die Knöpfe "+" oder "-" klickst, ist das auch der Fall.

Zwei Lösungswege:

  1. Du intergrierst setInterval(renew, 1000) in Deine Webseite, damit der Client sekündlich neue Daten holt.
  2. Du verwendest Websockets, siehe ESP32 WebSocket Server: Control Outputs (Arduino IDE).

Zusätzlicher Lesestoff zur Speicherung von HTML-Dateien im Dateisystem vom ESP32: Esp32 Webserver Arduino Tab und meine Anleitung: Einführung zu fipsok.de.

EDIT: Zwei Leute, ein Gedanke :smiley:

1 Like

Das ständige Senden der ganzen Website ist eigentlich unnötig. Das macht man mittlerweile mit der Fetch-API, die im Hintergrund die Daten mit dem Server abgleicht und die Werte in der Website aktualisiert.
Beispiele findest Du bei Fips. Eine Einführung zu den Seiten von agmue gibt es hier.

Gruß Tommy

1 Like

Vielen Dank euch beiden, das hört sich natürlich sehr schlüssig an :slight_smile:
Werde mir das zu Gemüte führen und so umsetzen. Die Seite ist im Originalprojekt wesentlich umfangreicher und es macht natürlich absolut Sinn nur Änderungen zu aktualisieren. :+1:

Ja, da paßt JSON schön zu JavaScript.

Websocket und LittleFS sind auch im Ökosystem von Fips möglich.

das ist aus meiner Sicht auch klar.
du rufst deine neuen Funktionen handle_val1sub und hanlde_val1add zwar auf, aber diese schicken dem Browser nichts zurück.
Wenn du dem Browser nichts zurückschicken willst, dann gib ihm wenigstens in der Funktion einen HTTP Response von 204 "no content" und er sollte zufrieden sein.

server.send(204); // no content

im loop hat das alles keinen Sinn. Du brauchst eine Antwort auf den Call aus dem .on()

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.