ESP32 e pagina HTML

Salve a tutti.
Sto cercando di salvare dei dati inseriti su una pagina HTML sul micro. La pagina si apre tranquillamente una volta digitato l'indirizzo IP di riferimento, ma non riesco a capire come salvare i dati che inserisco. Allego il codice per essere più chiaro possibile anche perché non conosco minimamente HTML.

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

#include "index.h"  

WebServer server(80);

char ssidAP[] = "ESP32"; // identificatico dell'AP
char passwordAP[] = "12345678"; //Password per la connessione 


void handleRoot() {
 String s = MAIN_page; 
 server.send(200, "text/html", s); 
}

//===============================================================
// Setup
//===============================================================

void setup(void){
  Serial.begin(115200);
  Serial.println();
  Serial.println("Booting Sketch...");

//ESP32 access point IP: 192.168.4.1
  WiFi.mode(WIFI_AP); //Access Point 
  WiFi.softAP(ssidAP, passwordAP); 

  server.on("/", handleRoot);      display page
 
  server.begin();                  //Start server
  Serial.println("HTTP server started");
}

void loop(void){
  server.handleClient();

}

Codice HTML:

<!DOCTYPE html>
<html>
<head>
  <title>Configurazione Rete</title>
</head>
<body>
  <h2>Configurazione Rete</h2>
  <form>
    <label for="ssid">SSID:</label>
    <input type="text" id="ssid" name="ssid" required><br><br>

    <label for="password">Password:</label>
    <input type="password" id="password" name="password" required><br><br>

    <label for="ip">Indirizzo IP:</label>
    <input type="text" id="ip" name="ip" required><br><br>

    <input type="submit" value="Salva">
  </form>
</body>
</html>

La tua pagina web sta inviando i dati con un classico form HTML, ti basta recuperare gli argomenti e poi farci quello che vuoi.

Siccome nella tua form non hai specificato nessuna proprietà "action", il submit verrà indirizzata alla pagina home "/" quindi questa cosa dovrai farla nella funzione che hai definito come handleRoot()

String ssid, password, ip;
.....
void handleRoot() {
  if(server.hasArg("ssid")) {
    ssid = server.arg("ssid");
  }
  if(server.hasArg("password")) {
    password = server.arg("password");
  }
  if(server.hasArg("ip")) {
    ip= server.arg("ip");
  }
  server.send(200, "text/html", MAIN_page); 
}

Ad ogni modo, volevo sottolineare che l'esp32 (cosi come l'esp8266) ha un'area di memoria flash dedicata dove vengono salvate tutte le proprietà della connessione WiFi e non è necessario usare variabili nello sketch per fare questa cosa.

//  Get the current configuration of the ESP32 WiFi station.
wifi_config_t config;
esp_wifi_get_config(WIFI_IF_STA, &config);

// Clear current configuration
memset(&config, 0, sizeof(config));

// Set the new ssid and password (from String variables)
memcpy(&config.sta.ssid, ssid.c_str(), ssid.length());
memcpy(&config.sta.password, password.c_str(), password.length());

// Set the configuration of the ESP32 station and save it to the Flash.
esp_wifi_set_config(WIFI_IF_STA, &config);

Grazie mille, ora riesco a stamparle in seriale.
Posso usarle adesso come variabili da inserire all'interno del WiFi.begin() per trasformare il mio ESP32 da AccessPoint a Client?

Da AccessPoint a Station :wink:

Si, devi solo fare attenzione che il metodo WiFi.begin() non accetta String come parametri, ma devi passargli un char* o un const char*

 WiFi.begin(ssid.c_str(), password.c_str()); 

Ok come immaginavo ed in effetti il codice l'ho modificato nel seguente modo:

void setup(void){
  Serial.begin(115200);
  Serial.println();
  Serial.println("Booting Sketch...");
  delay(100);

//ESP32 access point IP: 192.168.4.1
  WiFi.mode(WIFI_AP); //Access Point 
  WiFi.softAP(ssidAP, passwordAP); 

  server.on("/", handleRoot);      //display page
 
  server.begin();                  //Start server
  Serial.println("HTTP server started");

  const char* ssid2= ssid.c_str();
  const char* password2= password.c_str();

  if(strlen(ssid2)!=0 && strlen(password2)!=0){
    WiFi.begin(ssid2, password2);  //ESP Client
    while(WiFi.status() != WL_CONNECTED){
      delay(1000);
      Serial.println("Connessione alla rete WiFi in corso...");
    }
    Serial.println("Connesso!!");
    Serial.print("Verifica indirizzo IP: ");
    Serial.println(WiFi.localIP());
  }
}

Il problema ora è che le istruzioni presenti nell'if non vengono eseguite, dunque suppongo che l'ESP non riesce a connettersi al router attraverso le ssid e password che inserisco nella pagina HTML. Giusta supposizione?

Metti lo sketch completo perché non riesco a capire cosa stai combinando con 'ste variabili.

eccolo perdonami :pray: :joy:

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

#include "index.h"  

WebServer server(80);

char ssidAP[] = "ESP32"; // identificatico dell'AP
char passwordAP[] = "12345678"; //Password per la connessione 
String ssid, password, ip;

void handleRoot() {
 String s = MAIN_page; 
 server.send(200, "text/html", s); 

 if(server.hasArg("ssid")) {
    ssid = server.arg("ssid");
  }
  if(server.hasArg("password")) {
    password = server.arg("password");
  }
  if(server.hasArg("ip")) {
    ip= server.arg("ip");
  }
  Serial.println(ssid);
  Serial.println(password);
  Serial.println(ip);
}


void setup(void){
  Serial.begin(115200);
  Serial.println();
  Serial.println("Booting Sketch...");
  delay(100);

//ESP32 access point IP: 192.168.4.1
  WiFi.mode(WIFI_AP); //Access Point 
  WiFi.softAP(ssidAP, passwordAP); 

  server.on("/", handleRoot);      //display page
 
  server.begin();                  //Start server
  Serial.println("HTTP server started");

  const char* ssid2= ssid.c_str();
  const char* password2= password.c_str();

  if(strlen(ssid2)!=0 && strlen(password2)!=0){
    WiFi.mode(WIFI_STA);          //ESP station
    WiFi.begin(ssid2, password2);
    while(WiFi.status() != WL_CONNECTED){
      delay(1000);
      Serial.println("Connessione alla rete WiFi in corso...");
    }
    Serial.println("Connesso!!");
    Serial.print("Verifica indirizzo IP: ");
    Serial.println(WiFi.localIP());
  }
}

void loop(void){
  server.handleClient();
  delay(1);

}

L'obiettivo è quello di "trasformare" l'ESP da AccessPoint a Station una volta che vengono inserite (attraverso la pagina web) le credenziali della rete a cui dovrà connettersi.

Prova cosi. Ti ho commentato i passaggi salienti per evidenziare il principio di funzionamento.

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

WebServer server(80);
char ssidAP[] = "ESP32"; // identificatico dell'AP
char passwordAP[] = "12345678"; //Password per la connessione 
String ssid, password, ip;

void handleRoot() {
 // String s = MAIN_page; // completamente inutile questo passaggio
 server.send(200, "text/html", MAIN_page); 

 if(server.hasArg("ssid")) {
    ssid = server.arg("ssid");
  }
  if(server.hasArg("password")) {
    password = server.arg("password");
  }
  if(server.hasArg("ip")) {
    ip= server.arg("ip");
  }
  // Serial.println(ssid);
  // Serial.println(password);
  // Serial.println(ip);

  // Prova a connettersi con le credenziali passate con la form,con gestione errore e timeout
  if (ssid.length() && password.length()) {
    WiFi.begin(ssid.c_str(), password.c_str());
    uint32_t timeout = millis();
    Serial.println("Connessione alla rete WiFi in corso");
    while (WiFi.status() != WL_CONNECTED){
      delay(500);
      Serial.print(".");
      if (millis() - timeout > 10000) {
        Serial.println("\nImpossibile connettersi alla rete Wifi. Controlla i dati inseriti nella form");
        return;
      }
    }
    Serial.print("\nIndirizzo IP: ");
    Serial.println(WiFi.localIP());
  }
  else {
    Serial.println("Impossibile connettersi alla rete Wifi. I dati inseriti nella form sono incompleti");
  }
}


void setup(void){
  Serial.begin(115200);
  Serial.println();
  Serial.println("Booting Sketch...");
  delay(100);

  // Prova a connettersi con le credenziali già memorizzate (se presenti)
  // Se dopo 10 secondi ancora nulla, avvia in AP mode
  WiFi.persistent(true); 
  WiFi.mode(WIFI_STA); // Station mode
  WiFi.begin();  
  uint32_t timeout = millis();
  Serial.println("Connessione alla rete WiFi in corso");
  while(WiFi.status() != WL_CONNECTED){
    delay(500);
    Serial.print(".");
    
    if (millis() - timeout > 10000) {
      Serial.println("\nImpossibile connettersi alla rete Wifi. Avvio Access Point");
      //ESP32 access point IP: 192.168.4.1
      WiFi.mode(WIFI_AP); //Access Point 
      WiFi.softAP(ssidAP, passwordAP); 
      break;
    }
  }

  Serial.print("\nIndirizzo IP: ");
  Serial.println(WiFi.localIP());

  server.on("/", handleRoot);      //display page
  server.begin();                  //Start server
  Serial.println("HTTP server started");
}

void loop(void){
  server.handleClient();
  delay(1); // Completamente inutile
}
1 Like

Grazie infinite, sei stato gentilissimo! :pray:

Ho voluto ampliare il progetto. Vorrei che, l'ESP inizialmente facesse un controllo per connettersi con le credenziali già memorizzate (come effettivamente fa), successivamente setta una variabile connesso ad un valore tra 0 e 4. In base a quest'ultimo valore, l'ESP entra in modalità AP oppure STATION. Nel caso in cui è in modalità AP, effettua un collegamento con una pagina web che mi chiede di inserire le credenziali della rete a cui deve connettersi per passare in modalità STATION; una volta in modalità STATION, effettua un collegamento con una pagina web che mi chiede di accendere o spegnere un led.
Ho messo dei delay così lunghi per avere tempo di connettermi all'AP e per fornire il tempo necessario per inserire le credenziali sulla pagina web.
Spero di essere stato il più chiaro possibile. Allego codice:

#include <WiFi.h>
#include <WebServer.h>
#include "index2.h"
#include "page2.h"  

WebServer server(80);
char ssidAP[] = "ESP32"; // identificatico dell'AP
char passwordAP[] = "12345678"; //Password per la connessione 
String ssid, password, ip;
int connesso;

int LED=LOW;
int pinLed=33;
int statoled=0;

void handleRoot() {
 server.send(200, "text/html", MAIN_page); 

 if(server.hasArg("ssid")) {
    ssid = server.arg("ssid");
  }
  if(server.hasArg("password")) {
    password = server.arg("password");
  }
  if(server.hasArg("ip")) {
    ip= server.arg("ip");
  }

  // Prova a connettersi con le credenziali passate con la form,con gestione errore e timeout
  if (ssid.length() && password.length()) {
    WiFi.begin(ssid.c_str(), password.c_str());
    uint32_t timeout = millis();
    Serial.println("Connessione alla rete WiFi in corso");
    while (WiFi.status() != WL_CONNECTED){
      delay(500);
      Serial.print(".");
      if (millis() - timeout > 10000) {
        Serial.println("\nImpossibile connettersi alla rete Wifi. Controlla i dati inseriti nella form");
        return;
      }
    }
    Serial.print("\nConnesso!!\nIndirizzo IP: ");
    Serial.println(WiFi.localIP());
  }
  else {
    Serial.println("Impossibile connettersi alla rete Wifi. I dati inseriti nella form sono incompleti");
    connesso=4;
  }
}

void home(){
  server.send(200, "text.html", codice_pagina(LED));
}

void LED_funzione(){
  LED= !LED;
  if(LED==LOW){
    statoled=1;
  }
  else{
    statoled=0;
  }
  digitalWrite(pinLed, LED);
  server.send(200, "text/html", codice_pagina(LED));
}

void setup(void){
  Serial.begin(115200);
  Serial.println();
  Serial.println("Booting Sketch...");
  delay(100);
  pinMode(pinLed, OUTPUT);

  // Prova a connettersi con le credenziali già memorizzate (se presenti)
  // Se dopo 10 secondi ancora nulla, avvia in AP mode
  WiFi.persistent(true); 
  WiFi.mode(WIFI_STA); // Station mode
  WiFi.begin();  
  uint32_t timeout = millis();
  Serial.println("Connessione alla rete WiFi in corso");
  while(WiFi.status() != WL_CONNECTED){
    delay(500);
    Serial.print(".");
    
    if (millis() - timeout > 10000) {
      connesso==0;
      break;
    }
  }
  connesso==3;
}

void loop(void){
  server.handleClient();  
  WiFi.begin();
  switch(connesso){
    case 0:
      Serial.println("\nImpossibile connettersi alla rete Wifi. Avvio Access Point");
      //ESP32 access point IP: 192.168.4.1
      WiFi.mode(WIFI_AP); //Access Point 
      WiFi.softAP(ssidAP, passwordAP);      
      connesso=2;
      break;

    case 1: 
      //ESP come Client 
      Serial.print("\nConnesso!!\nIndirizzo IP: ");
      Serial.println(WiFi.localIP());
      connesso=3;
      break;

    case 2: 
    //pagina HTML scelta 
    server.on("/", handleRoot);      //display page
    server.begin();                  //Start server
    Serial.println("HTTP server started");
    delay(90000);
    connesso=3;
    break;

    case 3: 
    //reindirizzamento a pagina HTML accenione led
    server.begin();
    server.on("/", home);
    server.on("/LEDurl", LED_funzione);
    break;

    case 4:
    //controllo connessione del setup
    WiFi.persistent(true); 
    WiFi.mode(WIFI_STA); // Station mode
    WiFi.begin();  
    uint32_t timeout = millis();
    Serial.println("Connessione alla rete WiFi in corso");
    while(WiFi.status() != WL_CONNECTED){
    delay(500);
    Serial.print(".");
    
    if (millis() - timeout > 10000) {
      Serial.println("\nImpossibile connettersi alla rete Wifi. Avvio Access Point");
      connesso==0;
    }
  }
  connesso==3;
  break;
  } //fine switch
}

Il problema ora, è che non riesco più a connettermi alla pagina Web ma finisco dentro un ciclo infinito in cui l'ESP passa di continuo ad essere STATION e AP ma senza consentirmi il collegamento a nessuna delle due pagine web.

Sono riuscito a risolvere il problema, ora vorrei fare un ulteriore passo in avanti.
Vorrei che il collegamento con la pagina Web avvenisse senza digitare l'indirizzo IP sul browser ma ad esempio la scritta "ESP32" che suppongo vada a mascherare (?) l'indirizzo. Purtroppo non conosco HTML dunque non saprei minimamente come procedere. Vi ringrazio anticipatamente.
Allego codice:

#include <WiFi.h> 
#include <WiFiClient.h>
#include <WebServer.h>
// Includiamo la pagina HTML
#include "index2.h"
#include "page2.h"

WebServer server(80); // identifichiamo il server 
char ssidAP[] = "ESP32"; // identificatico dell'AP
char passwordAP[] = "12345678"; //Password per la connessione 
// definizione degli indirizzi 
IPAddress local_ip(192,168,2,1); 
IPAddress gateway(192,168,2,1);
IPAddress subnet(255,255,255,0);
String ssid, password, ip;

int Pin_LED = 33; // definizione del pin
int connesso;
int LED = LOW; // default  dello stato dei LED
unsigned long timeoutCurrent= millis();
unsigned long timeout = millis();

void setup()
  {
    Serial.begin(9600);
    pinMode(Pin_LED, OUTPUT); // definiamo i pins dei LEDs come output
  WiFi.persistent(true); 
  WiFi.mode(WIFI_STA); // Station mode
  WiFi.begin();  
  
  Serial.println("Connessione alla rete WiFi in corso");
  while(WiFi.status() != WL_CONNECTED){
    delay(500);
    Serial.print(".");
    
    if (millis() - timeout > 10000) {
      Serial.println("Connessione fallita. Avvio AP mode");
      connesso=0;
      break;
    }
    else
    connesso=4;
  }
    
   }

   void handleRoot() {
 // String s = MAIN_page; // completamente inutile questo passaggio
 server.send(200, "text/html", MAIN_page); 

 if(server.hasArg("ssid")) {
    ssid = server.arg("ssid");
  }
  if(server.hasArg("password")) {
    password = server.arg("password");
  }
  if(server.hasArg("ip")) {
    ip= server.arg("ip");
  }
  Serial.println(ssid);
  Serial.println(password);
  Serial.println(ip);

   }

void home() // funzione di default 
  { // invio della pagina HTML
    server.send(200, "text.html", codice_pagina(LED));
  }
void LED_funzione() // funzione del diodo LED verde,
  { 
    LED = !LED; // invio della pagina HTML
    digitalWrite(Pin_LED, LED);
    server.send(200, "text/html", codice_pagina(LED));
  }

void loop()
  {
   //server.handleClient(); // gestione delle richieste HTTP
    switch(connesso){
      
    case 0:
    Serial.println("\nAP mode in fase di avvio....");
    WiFi.mode(WIFI_AP); // configurazioendel wifi come AP 
    // inizializzazione   del WIFI
    WiFi.softAP(ssidAP, passwordAP); 
    WiFi.softAPConfig(local_ip, gateway , subnet);
    delay(40000);
    connesso=2;
    break;

    case 1:
    // inizializzazione  del server
    server.close();
    server.begin(); 
    server.on("/", home); // pagina iniziale
    server.on("/LEDurl", LED_funzione); // mappiamo l'URLs delle funzioni
    Serial.println("pagina Web creata!");
    connesso=5;
    break;

    case 2:
    //pagina html credenziali
    Serial.println("\nPuoi inserire dati nella pagina Web dedicata 192.168.2.1");
    server.close();
    server.begin();
    server.on("/", handleRoot);
    connesso=3; 
    timeoutCurrent=millis();
    break;

    case 3: 
    server.handleClient();// gestione delle richieste HTTP
    if (millis()- timeoutCurrent>= 30000)  //test whether the period has elapsed
  {
   timeoutCurrent=millis(); 
   connesso= 4; //IMPORTANT to save the start time of the current LED state.
  }
  break;

  case 4:
    if (ssid.length() && password.length()) {
      WiFi.begin(ssid.c_str(), password.c_str());
      uint32_t timeout = millis();
      Serial.println("Connessione alla rete WiFi in corso");

      while (WiFi.status() != WL_CONNECTED){
        delay(500);
        Serial.print(".");
        if (millis() - timeout > 10000) {
          Serial.println("\nImpossibile connettersi alla rete Wifi. Controlla i dati inseriti nella form, ricarica la pagina");
          connesso=3;
          return;
        }
      }

    Serial.print("\nIndirizzo IP: ");
    Serial.println(WiFi.localIP());
    connesso=1;
    break;
    }
    else {
      Serial.println("Impossibile connettersi alla rete Wifi. I dati inseriti nella form sono incompleti");
      connesso=0;
      break;
    }
    break;

    case 5: 
    server.handleClient();
    break;
   
    }
  }
 

Allego codice HTML pagina di Configurazione Rete:

const char MAIN_page[] PROGMEM = R"=====(
<!DOCTYPE html>
<html>
<head>
  <title>Configurazione Rete</title>
</head>
<body>
  <h2>Configurazione Rete</h2>
  <form>
    <label for="ssid">SSID:</label>
    <input type="text" id="ssid" name="ssid" required><br><br>

    <label for="password">Password:</label>
    <input type="password" id="password" name="password" required><br><br>

    <label for="ip">Indirizzo IP:</label>
    <input type="text" id="ip" name="ip" required><br><br>

    <input type="submit" value="Salva">
  </form>
</body>
</html>
)=====";

Allego codice HTML accensione LED:

String codice_pagina(int LED)
{
String page = "<!DOCTYPE html><html><head>";
page +="<title>Rete WLAN</title>";
page +="<style>";
page +="body {margin-top:50px; font-family:Arial;";
page +="font-size:20px; text-align:center}";
page +=".btn {display:block; width:220px;";
page += "margin:auto; padding:30px}";
page +=".btn {font-size:30px; color:black;";
page += "text-decoration:none}";
page +=".on {background-color:#4CAF50}";
page +=".off {background-color:#008CBA}";
page +="td {font-size:30px; margin-top:50px;";
page += "margin-bottom:5px}";
page +="p {font-size:30px; margin-top:50px;";
page += "margin-bottom:5px}";
page +="</style></head>";
page +="<body>";
page +="<h1>Rete locale con ESP32</h1>";
page +="<table style='width:100%'><tr>";
if(LED>0)
{
page +="<td>Il LED  e' acceso ";
page +="<a href='/LEDurl' class='btn on'>";
page +="Premi per segnere il LED </a></td>";
}
else
{
page +="<td>Il LED  e' spento ";
page +="<a href='/LEDurl' class='btn off'>";
page +="Premi per accendere il LED </a></td>";
}

page +="</body></html>";
return page;
}

Questo non ha nulla a che fare con l'HTML.
Oltre al webserver, sul microcontrollore devi far girare anche un server mDNS (multicast Domain Name System)

E naturalmente c'è un esempio già incluso nel core Arduino ESP32

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