Comunicazione tra due ESP32 con protocollo HTTP client-server
La comunicazione tra client-server si instaura quando il client invia una richiesta al server e quest’ultimo risponde fornendo il servizio o la risorsa richiesta.
Questa è una configurazione comune in reti e applicazioni distribuite in cui il server fornisce servizi centralizzati ai client connessi.
I sistemi client-server hanno avuto origine negli anni ’60 e ’70 con sistemi di elaborazione dati centralizzati, come i mainframe.
In questo modello, i mainframe funzionavano come server centralizzati che fornivano servizi di elaborazione dati ai terminali dei client, che non avevano potenza di calcolo.
Con l’avvento dei personal computer e delle reti locali negli anni ’80 e ’90, l’architettura client-server è diventata sempre più diffusa anche nei sistemi basati su PC, grazie allo sviluppo della rete web che fornisce sempre più servizi.
il modello client-server è diventato uno dei principali modelli di architettura per le applicazioni e i servizi di rete.
Nel contesto di una rete, il client utilizza protocolli di rete standard per stabilire una connessione al server e inviare richieste.
Il server utilizza queste richieste per fornire il servizio o la risorsa al client.
Questo modello è utilizzato in molti servizi e applicazioni comuni, come i siti web, i sistemi di posta elettronica, i database e le applicazioni di cloud computing.
Vantaggi e svantaggi del modello client-server
Vantaggi
- L’architettura centralizzata del modello client-server offre una maggiore protezione dei dati. Infatti tutte le richieste passano attraverso il server, ed è possibile applicare controlli di accesso in modo centralizzato, invece di doverli applicare su ogni client.
- I protocolli client-server sono indipendenti dalla piattaforma usata, è possibile utilizzare client e server che usano sistemi operativi diversi. Ciò consente una maggiore flessibilità nella scelta delle piattaforme e nell’integrazione con altri sistemi.
Svantaggi
- Uno svantaggio significativo del modello client-server è la sua vulnerabilità ai problemi di sovraccarico dovuti alla richiesta simultanea dei dati da parte di troppi client. Se il server non è in grado di gestire il carico di lavoro, può causare congestione della rete e rallentamenti delle prestazioni.
Per risolvere il problema sopraindicato, può essere quello di utilizzare dei server distribuiti per condividere il carico di lavoro, con l’ausilio di tecniche di bilanciamento del carico per distribuire le richieste tra i server disponibili.
Protocollo a basso livello client-server
Protocollo TCP
Il protocollo TCP (Transmission Control Protocol ) è utilizzato per le comunicazioni tra client e server.
TCP è un protocollo orientato alla connessione che garantisce la consegna affidabile dei dati su una rete.
TCP stabilisce una connessione tra i programmi applicativi su client e server, suddivide i dati dell’applicazione in pacchetti che possono essere trasmessi sulla rete, gestisce il controllo del flusso dei dati, gestisce la ritrasmissione dei pacchetti persi o danneggiati, e garantisce l’affidabilità e l’ordine nella consegna dei pacchetti.
Inoltre, TCP si occupa anche di effettuare un controllo di flusso tra i client e il server, monitorando il traffico per evitare il sovraccarico del server e garantire una comunicazione efficiente.
Protocollo UDP
UDP (User Datagram Protocol) è un protocollo di trasporto utilizzato per inviare pacchetti di dati senza garantire la consegna affidabile.
In altre parole, non ci sono meccanismi di controllo dell’errore o di ritrasmissione dei pacchetti in caso di perdita. Ciò lo rende più veloce e leggero rispetto al protocollo TCP, ma meno affidabile.
Protocollo HTTP
Nei precedenti paragrafi ho descritto, in modo sintetico il principio di funzionamento di un sistema client-server, e i protocolli a basso livello per la comunicazione tra due sistemi connessi in rete.
Per il progetto esposto in questo post utilizzeremo il protocollo ad alto livello http, per la comunicazione tra due schede ESP32, mentre i concetti esposti in precedenza sono sempre validi.
HTTP è un protocollo di comunicazione basato su testo che consente la trasmissione di risorse attraverso una rete, indipendentemente dal loro formato.
Può essere utilizzato per trasmettere documenti HTML, file binari o altre strutture dati più complesse.
Anche il protocollo HTTP, si basa sulla comunicazione client-server, come descritto nel paragrafo precedente. La comunicazione si basa sulla richiesta di connessione del cliente al server e se è accetta, si richiede anche la risorsa.
In HTTP 1.1 è possibile utilizzare la stessa connessione per inviare più richieste e ricevere più risposte, il che consente di ridurre il numero di connessioni necessarie per caricare una pagina web e migliorare le prestazioni complessive.
Inoltre, in HTTP 1.1, le risposte devono essere restituite nello stesso ordine delle richieste, poiché non viene fornito un metodo esplicito per associare le risposte alle richieste corrispondenti.
Ecco un esempio di una richiesta da parte di un client:
GET /prova.htm HTTP/1.1 User-Agent: Mozilla/4.0 (compatible; MSIE5.01; Windows NT) Host: www.quattrodispositivi.it Accept-Language: en-us Accept-Encoding: gzip, deflate Connection: Keep-Alive
Metodo GET
GET è un metodo HTTP che viene utilizzato per richiedere una risorsa da un server.
È il metodo più comune e viene attivato facendo clic su un link ipertestuale o digitando un URL nel browser.
Metodo POST
Il metodo HTTP POST viene utilizzato per inviare dati dal client al server, solitamente per creare o aggiornare una risorsa.
Comunicazione HTTP, client-server tra due ESP32
In questa applicazione, utilizzeremo le conoscenze acquisite in precedenza per implementare una comunicazione tra due dispositivi ESP32 utilizzando il protocollo di comunicazione HTTP in modalità client-server.
Verranno configurati un ESP32 come server e l’altro come client, entrambi connessi alla stessa rete Wi-Fi.
Inoltre, questo progetto è la base per un’aplicazione più complessa che pubblicherò su questo sito.
Per far comunicare due ESP32 utilizzando il protocollo HTTP in modalità client-server, è necessario seguire i seguenti passi:
- Configurare un ESP32 come server e un ESP32 come client.
- Nel codice del server ESP32, impostare un server HTTP utilizzando la libreria ESPAsyncWebServer.
- Nel codice del client ESP32, utilizzare la libreria HTTPClient per inviare richieste HTTP al server ESP32.
- Nel codice del server ESP32, bisogna gestire le richieste HTTP in arrivo dal client ESP32.
- Nel codice del client ESP32, inviare richieste HTTP al server ESP32.
Codice server
#include <WiFi.h> #include <ESPAsyncWebServer.h> const char* ssid = "----------"; const char* password = "-------"; AsyncWebServer server(80); //Imposta l'indirizzo IP del tuo server IPAddress local_IP(192, 168, 1, 184); // imposta Gateway dell'indirizzo IP address IPAddress gateway(192, 168, 1, 1); // imposta la tua subnet IPAddress subnet(255, 255, 0, 0); void setup() { Serial.begin(115200); Serial.setTimeout(10); // Configures static IP address if (!WiFi.config(local_IP, gateway, subnet)) { Serial.println("non è stato possible configurare la rete"); } WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(1000); Serial.println("mi sto connettendo al WIFI......"); } Serial.println("mi sono connesso al WiFi"); Serial.println(WiFi.localIP()); server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){ request->send(200, "text/plain", " Ciao ti sei connesso al server ESP32!"); }); server.begin(); } void loop() { }
#include <WiFi.h>
Questa libreria fornisce le funzionalità per la gestione della connessione ad una rete WiFI, la scansione delle reti disponibili e la gestione degli eventi di connessione.
#include <ESPAsyncWebServer.h>
Questa libreria fornisce un’interfaccia semplice per creare un server web asincrono su ESP32.
Con questa libreria, è possibile creare un server HTTP che può gestire richieste HTTP in arrivo, come GET, POST, PUT, ecc.
const char* ssid = "YourWiFiSSID"; const char* password = "YourWiFiPassword";
Definiscono le costanti di tipo stringa per la connessione Wi-Fi.
La prima riga, “const char* ssid = “YourWiFiSSID”;”, definisce una costante chiamata “ssid” che contiene il nome della rete Wi-Fi a cui si desidera connettersi.
La seconda riga, “const char* password = “YourWiFiPassword”;”, definisce una costante chiamata “password” che contiene la password della rete Wi-Fi a cui si desidera connettersi.
AsyncWebServer server(80);
Crea un oggetto di tipo AsyncWebServer chiamato “server” e lo assegna alla porta 80.
E’ stata assegnata la porta 80, predefinita per la nostra applicazione per il protocollo HTTP.
Il server HTTP creato in questo modo risponderà alle richieste in arrivo sulla suddetta porta.
WiFi.config(local_IP, gateway, subnet)
La funzione WiFi.config() configura l’IP locale, il gateway e la subnet mask della connessione WiFi sul dispsositivo ESP32.
“local_IP” è l’indirizzo IP assegnato al dispositivo sulla rete locale, “gateway” è l’indirizzo IP del router sulla rete e “subnet” è la maschera di sottorete utilizzata per identificare i dispositivi appartenenti alla stessa rete.
WiFi.begin(ssid, password);
La funzione WiFi.begin() accetta due parametri: il nome della rete (ssid) e la password della rete (password).
La funzione WiFi.begin() tenta di connettersi alla rete Wi-Fi specificata utilizzando le credenziali fornite.
Se la connessione si stabilisce con successo, la funzione restituisce il parmetro WL_CONNECTED, altrimenti restituirà un codice d’errore.
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){ request->send(200, "text/plain", " Ciao ti sei connesso al server ESP32!");
La funzione server.on() indica che si vuole configurare una determinata risorsa (“/”) per un determinato tipo di richiesta HTTP (in questo caso “HTTP_GET”).
Quando un client effettua una richiesta GET per la risorsa “/”, la funzione richiama request->send() per inviare una risposta al client con un codice di stato HTTP 200 (OK), se la richiesta è andata a buon fine, e il tipo di contenuto “text/plain” e il messaggio “Ciao ti sei connesso al server ESP32!”.
server.begin();
Una volta chiamata questa funzione, il server inizierà ad ascoltare le richieste in entrata sulla porta predefinita (80) e gestirle utilizzando le risorse e le funzioni di gestione delle richieste configurate in precedenza con la funzione server.on().
In altre parole, questa funzione rende effettivo l’avvio del server web su ESP32 ed è in grado di rispondere alle richieste HTTP fatte dei client.
Codice client
#include <WiFi.h> #include <HTTPClient.h> const char* ssid = "-------"; const char* password = "--------"; const char* serverName = "http://192.168.1.184/"; int i = 0; void setup() { WiFi.begin(ssid, password); Serial.begin(115200); Serial.setTimeout(10); while (WiFi.status() != WL_CONNECTED) { delay(1000); Serial.println("Connessione al WIFI..."); } Serial.println("Connesso al WIFI"); } void loop() { HTTPClient http; http.begin(serverName); int httpCode = http.GET(); if (httpCode > 0) { String payload = http.getString(); Serial.println(httpCode); Serial.println(payload); } else { Serial.println("Errore sulla richiesta HTTP"); } http.end(); delay(5000); }
#include <HTTPClient.h>
Questa libreria fornisce lefunzioni per effettuare richieste HTTP, come GET, POST, PUT e DELETE, nonché funzioni per gestire le risposte del server, come l’acquisizione del codice di stato HTTP, dei header e del contenuto della risposta.
const char* serverName = "http://192.168.1.184/";
E’ l’indirizzo IP del server a cui vogliamo connetterci.+
http.begin(serverName);
Inizializza la connessione al server specificando l’indirizzo IP (nel nostro caso) o il nome host del server.
Questa funzione non stabilisce effettivamente la connessione, ma inizializza solo i parametri per la connessione.
La connessione verrà stabilita solo quando si effettua una richiesta HTTP, ad esempio con http.GET(), http.POST(), http.PUT(), etc.
int httpCode = http.GET();
Effettua una richiesta GET al server specificato nella funzione http.begin().
Una volta chiamata, la funzione invia la richiesta al server e attende la risposta.
La funzione restituisce un intero che rappresenta il codice di stato HTTP della risposta del server.
I codici di stato HTTP indicano l’esito della richiesta. Ad esempio, il codice 200 indica che la richiesta è stata completata con successo, mentre il codice 404 indica che la risorsa richiesta non è stata trovata sul server.
Il valore di httpCode può essere utilizzato per verificare che la richiesta sia andata a buon fine, in caso contrario bisogna gestire gli errori.
String payload = http.getString();
La funzione restituisce una stringa che rappresenta il contenuto della risposta del server.
Conclusioni
Spero che le informazioni fornite siano fonti di ispirazione per nuovi progetti.
Se hai domande o osservazioni, sarò felice di aiutarti, lascia un commento di seguito.
Inoltre, ti invito a condividere i tuoi progetti e risultati con la comunità, in modo che possano essere di ispirazione per gli altri.
Buona fortuna con i tuoi progetti futuri!