Skocz do zawartości

Blokowanie programu przy uruchomieniu webserwera ESP32


Pieterlpl

Pomocna odpowiedź

Cześć. Projekt zbliża się ku końcowi jednakże mam problem z blokowaniem się dalszego wykonywania programu. Wykorzystałem i zmodyfikowałem pod siebie gotowy program, który tworzy i uruchamia web serwer na moim ESP32. Wszystko działa jak należy natomiast problem polega na tym, że wchodząc pod podany adres IP, w terminalu widzę następujące informacje: Klient połączony, klient odłączony i znów połączony. Wydaje mi się, że pojedyncze wejście na danych adres IP lub pojedyncze odświeżenie powinno skutkować zakończeniem na "klient odłączony". Niestety usunięcie bądź modyfikacja pętli while unieruchamia cały web serwer. Czy macie może pomysł w którym miejscu należałoby zmodyfikować program aby usunąć wspomniany problem?

Z góry dziękuję za odpowiedź.

/*********
  Rui Santos
  Complete project details at https://randomnerdtutorials.com  
*********/

// Load Wi-Fi library
#include <WiFi.h>

// Replace with your network credentials
const char* ssid     = "";
const char* password = "";

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

// Variable to store the HTTP request
String header;

// Auxiliar variables to store the current output state
String output26State = "off";
String output27State = "off";

// Assign output variables to GPIO pins
const int output26 = 26;
const int output27 = 27;

void setup() {
  Serial.begin(115200);
  // Initialize the output variables as outputs
  pinMode(output26, OUTPUT);
  pinMode(output27, OUTPUT);
  // Set outputs to LOW
  digitalWrite(output26, LOW);
  digitalWrite(output27, LOW);

  // Connect to Wi-Fi network with SSID and password
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  // Print local IP address and start web server
  Serial.println("");
  Serial.println("WiFi connected.");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
  server.begin();
}

void loop(){
  WiFiClient client = server.available();   // Listen for incoming clients

  if (client) {                             // If a new client connects,
    Serial.println("New Client.");          // print a message out in the serial port
    String currentLine = "";                // make a String to hold incoming data from the client
    while (client.connected()) {            // loop while the client's connected
      if (client.available()) {             // if there's bytes to read from the client,
        char c = client.read();             // read a byte, then
        Serial.write(c);                    // print it out the serial monitor
        header += c;
        if (c == '\n') {                    // if the byte is a newline character
          // if the current line is blank, you got two newline characters in a row.
          // that's the end of the client HTTP request, so send a response:
          if (currentLine.length() == 0) {
            // HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
            // and a content-type so the client knows what's coming, then a blank line:
            client.println("HTTP/1.1 200 OK");
            client.println("Content-type:text/html");
            client.println("Connection: close");
            client.println();
            
            // turns the GPIOs on and off
            if (header.indexOf("GET /26/on") >= 0) {
              Serial.println("GPIO 26 on");
              output26State = "on";
              digitalWrite(output26, HIGH);
            } else if (header.indexOf("GET /26/off") >= 0) {
              Serial.println("GPIO 26 off");
              output26State = "off";
              digitalWrite(output26, LOW);
            } else if (header.indexOf("GET /27/on") >= 0) {
              Serial.println("GPIO 27 on");
              output27State = "on";
              digitalWrite(output27, HIGH);
            } else if (header.indexOf("GET /27/off") >= 0) {
              Serial.println("GPIO 27 off");
              output27State = "off";
              digitalWrite(output27, LOW);
            }
            
            // Display the HTML web page
            client.println("<!DOCTYPE html><html>");
            client.println("<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">");
            client.println("<link rel=\"icon\" href=\"data:,\">");
            // CSS to style the on/off buttons 
            // Feel free to change the background-color and font-size attributes to fit your preferences
            client.println("<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}");
            client.println(".button { background-color: #4CAF50; border: none; color: white; padding: 16px 40px;");
            client.println("text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer;}");
            client.println(".button2 {background-color: #555555;}</style></head>");
            
            // Web Page Heading
            client.println("<body><h1>ESP32 Web Server</h1>");
            
            // Display current state, and ON/OFF buttons for GPIO 26  
            client.println("<p>GPIO 26 - State " + output26State + "</p>");
            // If the output26State is off, it displays the ON button       
            if (output26State=="off") {
              client.println("<p><a href=\"/26/on\"><button class=\"button\">ON</button></a></p>");
            } else {
              client.println("<p><a href=\"/26/off\"><button class=\"button button2\">OFF</button></a></p>");
            } 
               
            // Display current state, and ON/OFF buttons for GPIO 27  
            client.println("<p>GPIO 27 - State " + output27State + "</p>");
            // If the output27State is off, it displays the ON button       
            if (output27State=="off") {
              client.println("<p><a href=\"/27/on\"><button class=\"button\">ON</button></a></p>");
            } else {
              client.println("<p><a href=\"/27/off\"><button class=\"button button2\">OFF</button></a></p>");
            }
            client.println("</body></html>");
            
            // The HTTP response ends with another blank line
            client.println();
            // Break out of the while loop
            break;
          } else { // if you got a newline, then clear currentLine
            currentLine = "";
          }
        } else if (c != '\r') {  // if you got anything else but a carriage return character,
          currentLine += c;      // add it to the end of the currentLine
        }
      }
    }
    // Clear the header variable
    header = "";
    // Close the connection
    client.stop();
    Serial.println("Client disconnected.");
    Serial.println("");
  }
}

Przechwytywanie.thumb.JPG.3fa6008c4f2d34c5c337c048b5d81eea.JPG

Edytowano przez Pieterlpl
Link do komentarza
Share on other sites

Którą pętle while masz na myśli?

Problemem może być:

16 godzin temu, Pieterlpl napisał:

client.stop();

W tym momencie przy każdorazowym wejściu w funkcję i po wykonaniu całego kodu w niej, klient zostanie automatycznie rozłączony, niezależnie od wykonanych czynności.

Edytowano przez szczawiosław
Link do komentarza
Share on other sites

Dokładnie o tą pętle mi chodzi. I właśnie chciałbym żeby klient był rozłączony, a tak się nie dzieje. Rozłącza się i za moment jest ciągle połączony przez co blokuje wykonywanie dalszej części programu jaką mam napisaną

Link do komentarza
Share on other sites

No dobrze...

Klient zostaje rozłączony, a za chwilę znowu się łączy z jakiejś przyczyny. Tyle że z punktu widzenia serwera to już nie jest ten sam klient...

Testujesz to przeglądarką? Może po prostu upiera się żeby znaleźć favicon.ico? Może spróbuj lynxem albo wgetem a nie chromem (który żyje własnym życiem i nie wiadomo co on tak naprawdę pobiera z serwera)?

A tak z czystej ciekawości: ESP32 ma dość dużo zasobów, spokojnie pociągnie jakiś normalny (dla ESP) serwer HTTP z odpowiedniej biblioteki (np. WebServer z ESP32 core) - po co na 32-bitowym dwurdzeniowcu ręcznie implementujesz rozwiązanie rodem z AVR-ów?

 

  • Lubię! 1
Link do komentarza
Share on other sites

Zarejestruj się lub zaloguj, aby ukryć tę reklamę.
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.

jlcpcb.jpg

jlcpcb.jpg

Produkcja i montaż PCB - wybierz sprawdzone PCBWay!
   • Darmowe płytki dla studentów i projektów non-profit
   • Tylko 5$ za 10 prototypów PCB w 24 godziny
   • Usługa projektowania PCB na zlecenie
   • Montaż PCB od 30$ + bezpłatna dostawa i szablony
   • Darmowe narzędzie do podglądu plików Gerber
Zobacz również » Film z fabryki PCBWay

W sumie zgadza się, łączyłem się poprzez chrome na smartphonie.

A co do serwera, wykorzystałem akurat przykład który znalazłem, nie znałem rozwiązania o którym wspominasz @ethanak. W głównej mierze ESP ma pracować na baterii i jak najbardziej ją oszczędzać stąd chciałbym aby serwer oraz wifi w ESP jak najrzadziej pracowało. Dodatkowo będę korzystał z protokołu MQTT do wysyłania danych np. do Raspberry PI który mógłby być sercem Inteligentnego Domu

 

  • Lubię! 1
Link do komentarza
Share on other sites

7 minut temu, Pieterlpl napisał:

chciałbym aby serwer oraz wifi w ESP jak najrzadziej pracowało

Większość tego typu serwerów działa na zasadzie cyklicznego wywołania jakiejś funkcji typu handleClient() - jak jej nie będziesz wywoływać to i serwer działać nie będzie. Popatrz na przykłady.

  • Lubię! 1
Link do komentarza
Share on other sites

Ok, sprawdzę to w takim razie. Czy możecie mi pomóc z jeszcze jednym kłopotem jakim jest implementacja light sleep w tym przykładzie? Chciałem wykorzystać deep sleep ale on po wybudzeniu restartuje całe ESP32 więc odpada. Problem z light sleepem polega na tym że ESP również się restartuje z powodu błędu, z tego co zauważyłem problemem jest działające wifi bądź serwer i należy go najpierw zatrzymać/wyłączyć a następnie znów uruchomić. O ile to pierwsze działa dobrze o tyle ponowne uruchomienie nie skutkuje połączeniem (brak adresu IP). Czy ktoś korzystał może już z takiego rozwiązania u siebie czyli light sleep + wifi?

Link do komentarza
Share on other sites

Dołącz do dyskusji, napisz odpowiedź!

Jeśli masz już konto to zaloguj się teraz, aby opublikować wiadomość jako Ty. Możesz też napisać teraz i zarejestrować się później.
Uwaga: wgrywanie zdjęć i załączników dostępne jest po zalogowaniu!

Anonim
Dołącz do dyskusji! Kliknij i zacznij pisać...

×   Wklejony jako tekst z formatowaniem.   Przywróć formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Twój link będzie automatycznie osadzony.   Wyświetlać jako link

×   Twoja poprzednia zawartość została przywrócona.   Wyczyść edytor

×   Nie możesz wkleić zdjęć bezpośrednio. Prześlij lub wstaw obrazy z adresu URL.

×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.