Gestione HTTP request Arduino

Salve a tutti…

Sto cercando di portar su le prime pagine del webserver che dovrò caricare su arduino.
Il progetto di partenza è un sistema di allarme, con relativi sensori di movimento, schermo lcd, tatiera, riconoscimento RFID, ecc ecc…il tutto funzionante, ma pensando di implementare una gestione remota del sistema, ho iniziato a fare dei test…(Utilizzo un’arduino Mega 2560 r3 e una scheda di rete compatibile con chipset Wiznet 5100…)

Sono riuscito con qualche esempio trovato online a caricare un’ipotetica pagina INDEX.htm dalla scheda SD.
A questo punto, ho pensato di caricare una pagina di LOGIN per gestire gli accessi. Ecco il codice della stessa:

<!DOCTYPE html>
<html>
<head >
 <title>OSAS - Login</title>
</head>
<body >
<hr>
<hr>
 <table width="40%" border="0" align="center" bgcolor="#e8e8e8">
 <tr align="center">
 <td><form>
 <font face="Arial" size="2"><b>User</b></font>
 

 <input type="text" name="login">
 

 <font face="Arial" size="2"><b>Password</b></font>
 

 <input type="password" name="password">
 

 

 <input type="submit" value=" Accedi ">
 </form></td>
 </tr>
 </table>
<hr>
</body>
</html>
<hr>

Adesso, se volessi gestire le richieste HTTP che invio col codice soprastante(sul quale ho qualche dubbio rispetto alla gestione del tag “Action” nel form),cosa dovrei fare con arduino?

Ho questo codice:

#include <SPI.h>
#include <Ethernet.h>
#include <SD.h>

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = {192, 168, 1, 127};

EthernetServer server(80);
File htmlFile;


void setup () 
{
  Ethernet.begin(mac, ip);
  server.begin();
  if (!SD.begin(4)) { return; }
  Serial.begin(9600);
}

void loop ()
{
  EthernetClient client = server.available();
  if (client) 
    {
     boolean currentLineIsBlank = true;
     while (client.connected()) 
           {
            if (client.available()) 
              {
               char c = client.read();
               
               if (c == '\n' && currentLineIsBlank) 
                  {
                    client.println("HTTP/1.1 200 OK");
                    client.println("Content-Type: text/html");
                    client.println();
                    htmlFile = SD.open("login.htm");
                    if (htmlFile) 
                       {
                       while (htmlFile.available()) 
                              {
                                client.write(htmlFile.read());
                              }
                        htmlFile.close();
                       }
               break;
              }
              
            else if (c == '\n') 
              {
               currentLineIsBlank = true;
               }
              
            else if (c != '\r') 
                   {
                    currentLineIsBlank = false;
                   }
           }
        }
     delay(1);
     client.stop();
    }
}

Se ora volessi controllare che non sia una stringa vuota, ma appunto una richiesta di tipo POST inviata dalla pagina, ipoteticamente potrei aggiungere qualche linea di codice, e far scrivere il contenuto della variabile C in una stringa e poi eseguire i relativi controlli per definire il tipo di richiesta e ho pensato di farlo in questo modo…

#include <SPI.h>
#include <Ethernet.h>
#include <SD.h>

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = {192, 168, 1, 127};

EthernetServer server(80);
File htmlFile;



void setup () 
{
  Ethernet.begin(mac, ip);
  server.begin();
  if (!SD.begin(4)) { return; }
  Serial.begin(9600);
}



void loop ()
{
  EthernetClient client = server.available();
  if (client) 
    {
     boolean currentLineIsBlank = true;
     boolean currentLineIsGet = true;
     boolean currentReqIsOk = false;
     int i=0;
     int bufind = 0;
     char buffer[64];
     
     while (client.connected()) 
         {
         if (client.available()) 
           {
            char c = client.read();
            
            if(currentLineIsGet && bufind < 63)
              {
               buffer[bufind] = c;
               bufind++;
               buffer[bufind] = 0;
               i++; 
               if (c== '\n' && i>1)
                  {
                    CurrentReqIsOk = true;
                  }         
              }
            
            if (CurrentReqIsOk)
               {
                ///ISTRUZIONI DI CONTROLLO
                //poi apertura file INDEX.htm
               }
                          
            if (c == '\n' && currentLineIsBlank) 
              {
               client.println("HTTP/1.1 200 OK");
               client.println("Content-Type: text/html");
               client.println();
               htmlFile = SD.open("login.htm");
               if (htmlFile) 
                 {
                  while (htmlFile.available()) 
                      {
                       client.write(htmlFile.read());
                      }
                  htmlFile.close();
                 }
               break;
              }
              
            else if (c == '\n') 
              {
               currentLineIsBlank = true;
               currentLineIsGet = false;
              }
              
            else if (c != '\r') 
                   {
                    currentLineIsBlank = false;
                   }
           }
        }
     delay(1);
     client.stop();
    }
    
}

Mancano le operazioni di controllo stringa, ma anche decidendo di stampare su serial monitor la stringa ricevuta, non mi stampa nulla…cosa sbaglio?

Qualcuno sa darmi una mano?

stampa i valori di c ogni ciclo, e se entri nell'if (e quind le condizioni per entrarci) della costruzione della stringa da cercare.

Ho risolto utilizzando dei metodi GET e analizzando le stringhe ricevute..
mi chiedevo piu che altro come è possibile leggere le richieste POST..
hanno bisogno di una conferma per ricevere i valori inviati o come è possibile gestirle?dovrei appoggiarmi ad altre librerie?

Parlando d'altro, è possibile determinare gli utenti connessi al webserver?
ossia..volendo ad esempio che solo un utente alla volta sia connesso (onde evitare ulteriori problemi nella gestione del possibile "multi-utente"), che logica si potrebbe seguire?

Ho provato utilizzando una variabile globale di tipo booleano, che al momento dell'autenticazione modificavo se le credenziali erano corrette. Ma quando capisco che realmente un client è disconnesso per poter nuovamente cambiare il valore della variabile?

RIngrazio per le risposte..

le richieste post sono un poco differenti, devi cercare l'header leght, che indica la lunghezza X in byte dal payload, e poi a fine header (una riga vuota) inizi a leggere X byte. Per il resto sono praticamente identiche alle GET.

Parlando d'altro, è possibile determinare gli utenti connessi al webserver?

difficile, quasi impossibile. puoi limitarti ad uno come hai detto, l'oggetto EthernetClient ha un modo per capire se il client è connesso (isConnect o similiìe). Se lo è, allora farai un altra EthernetServer.aceept()

Ho notato che sono differenti...ho provato a stamparle su monitor seriale, ma mi rendo conto che non riportano alcuno dei dati passati dai form..per questo mi chiedevo se c'era bisogno di avere una risposta..quello che non ho capito, è se quindi, devo fare nuovamente una nuova lettura sul buffer per trovare i dati passati?perchè ti ripeto che non risulta nessuno dei dati passati..

difficile, quasi impossibile. puoi limitarti ad uno come hai detto, l'oggetto EthernetClient ha un modo per capire se il client è connesso (isConnect o similiìe). Se lo è, allora farai un altra EthernetServer.aceept()

Si, si può definire in quel modo..ma a quel punto se già "client" è connesso, "client2" troverà irraggiungibile il sito..o sbaglio?

Si, si può definire in quel modo..ma a quel punto se già "client" è connesso, "client2" troverà irraggiungibile il sito..o sbaglio?

il wiznet (il chip dell'ethernet shield) gli risponde perchè indipendente, quindi si connette, ma non ottiene risposta quasiasi cosa faccia.

Ho notato che sono differenti...ho provato a stamparle su monitor seriale, ma mi rendo conto che non riportano alcuno dei dati passati dai form..per questo mi chiedevo se c'era bisogno di avere una risposta..quello che non ho capito, è se quindi, devo fare nuovamente una nuova lettura sul buffer per trovare i dati passati?perchè ti ripeto che non risulta nessuno dei dati passati..

percè i dati sono in cosa. Laddove la GET si chiude, la POST invece aggiunge i dati. Quindi se è una POST, leggi come la GET, però quando la GET si disconnette inevec tu devi leggere i famosi X byte.

Ho trovato difficoltà nell'implementare quello che mi dicevi rispetto alla gestione dei client connessi..
Stampando su serial monitor le entrate e le uscite dai cicli, posso notare che il loop principale che inizia cosi

void loop ()
{
  EthernetClient client = server.available();
  Serial.println("EthernetClient client = server.available();");
   if (client) 
     {
       Serial.println("if (client)");
       ....
       ...

cicla infinitamente sino a quando qualcuno non si connette. Ma una volta svolte le istruzioni contenute nell'"if" ricicla all'infinito, e quindi è normale che può accogliere nuove richieste anche da ulteriori utenti.
SInceramente mi sono un po perso..e non riesco proprio a intravedere una soluzione al problema..

Sto cercando di portar su le prime pagine del webserver

stai facendo un trasloco dal piano terra all' ottavo piano? :slight_smile:

è possibile determinare gli utenti connessi al webserver?

la connessione dura uno o due secondi per ogni utente, è un entrata e uscita immediata, è quasi improbabile che vengano usati più di un solo socket con questo metoto.
E' possibile se non usi client.stop() e ad ogni connessione gli fai usare un socket diverso fino ad esaurimento.

ho provato a stamparle su monitor seriale, ma mi rendo conto che non riportano alcuno dei dati passati dai form.

Elabora bene l'header anche i messaggi POST arrivano e sono leggibili

ciao

skull6m:
Ho trovato difficoltà nell'implementare quello che mi dicevi rispetto alla gestione dei client connessi..
Stampando su serial monitor le entrate e le uscite dai cicli, posso notare che il loop principale che inizia cosi

void loop ()

{
  EthernetClient client = server.available();
  Serial.println("EthernetClient client = server.available();");
   if (client)
     {
       Serial.println("if (client)");
       ....
       ...


cicla infinitamente sino a quando qualcuno non si connette. Ma una volta svolte le istruzioni contenute nell'"if" ricicla all'infinito, e quindi è normale che può accogliere nuove richieste anche da ulteriori utenti. 
SInceramente mi sono un po perso..e non riesco proprio a intravedere una soluzione al problema..

direi che ti mancano le basi. Una persono non rimane "connessa al sito" se non il tempo necessari a richeidere UNA pagina e ricevere risposta. fine. Infatti via HTTP è complicato mantenere traccia di un utente, e si usano trucchi come cookie, campi nascosti, ip, etc...