Una delle domande che ricevo più spesso tramite il form sul sito o nella pagina Facebook è se sia possibile pubblicare un server HTTP quando il chip esp32 è in modalità SoftAP, ovvero quando pubblica una propria rete wifi.
In precedenti tutorial (18 – Access Point e 20 – Webserver) ho già trattato separatamente le due tematiche, oggi vediamo come combinarle.
Access Point
Iniziamo con la definizione dei parametri della rete TCP/IP che sarà pubblicata dal chip esp32. Dobbiamo scegliere un piano di indirizzamento, ovvero quali indirizzi IP apparterranno alla rete. Possiamo scegliere tra gli indirizzi IP dedicati dalla IANA alle reti private (RFC1918):
[checklist]
- 10.0.0.0/8
- 172.16.0.0/12
- 192.168.0.0/16
[/checklist]
In questo esempio utilizzerò la rete 192.168.1.0 con netmask 255.255.255.0 (/24), ovvero una rete con 254 indirizzi possibili (192.168.1.1 – 192.168.1.254). Al chip esp32 dovrà essere assegnato staticamente un indirizzo appartenente a tale rete; per semplicità ho scelto il primo (192.168.1.1):
tcpip_adapter_ip_info_t info; memset(&info, 0, sizeof(info)); IP4_ADDR(&info.ip, 192, 168, 1, 1); IP4_ADDR(&info.gw, 192, 168, 1, 1); IP4_ADDR(&info.netmask, 255, 255, 255, 0); ESP_ERROR_CHECK(tcpip_adapter_set_ip_info(TCPIP_ADAPTER_IF_AP, &info)); |
I vari dispositivi che si collegheranno alla rete dovranno ricevere dinamicamente un indirizzo IP, grazie al servizio DHCP. Per utilizzarlo nel mio programma devo stopparlo prima della configurazione dei parametri di rete, quindi avviarlo al termine della configurazione:
ESP_ERROR_CHECK(tcpip_adapter_dhcps_stop(TCPIP_ADAPTER_IF_AP)); [...] ESP_ERROR_CHECK(tcpip_adapter_dhcps_start(TCPIP_ADAPTER_IF_AP)); |
Una volta terminata la configurazione della rete TCP/IP e dei servizi associati, possiamo configurare l’interfaccia wifi del chip esp32 e attivare la modalità SoftAP:
wifi_init_config_t wifi_init_config = WIFI_INIT_CONFIG_DEFAULT(); ESP_ERROR_CHECK(esp_wifi_init(&wifi_init_config)); ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM)); ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_AP)); |
Dobbiamo preparare una struct wifi_config_t con i diversi parametri della rete wifi (SSID, autenticazione…) e passarla al metodo:
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_AP, &ap_config)); |
Possiamo decidere di inserire i parametri hardcoded nel programma, di renderli configurabili tramite menuconfig (come nell’esempio) o ancora di leggerli da files di configurazione o variabili NVS.
Infine avviamo l’interfaccia wifi con:
ESP_ERROR_CHECK(esp_wifi_start()); |
HTTP server
Utilizziamo le Netconn API della libreria lwip per mettere il nostro programma in ascolto sulla porta TCP/80 (è la porta standard utilizzata dal protocollo HTTP):
struct netconn *conn; conn = netconn_new(NETCONN_TCP); netconn_bind(conn, NULL, 80); netconn_listen(conn); |
Il metodo accept() blocca il programma fino all’arrivo di una nuova connessione:
struct netconn *newconn; netconn_accept(conn, &newconn); |
Una volta stabilita la connessione, dobbiamo implementare nel nostro programma il “linguaggio” (protocollo) che parla il client; in questo caso il protocollo HTTP utilizzato dai browser web.
Per semplicità nell’esempio pubblicherò un sito statico, il cui contenuto è memorizzato in una partizione SPIFFS (vedi il progetto ESP32lights per maggiori dettagli), quindi risponderò a richieste di tipo GET <risorsa> da parte del browser cercando la risorsa nella partizione SPIFFS e inviando il suo contenuto con il metodo netconn_write():
Bonus, mDNS
Per potersi collegare al server HTTP pubblicato dal chip esp32, un client deve conoscere l’indirizzo IP (192.168.1.1) assegnato al chip.
Possiamo sfruttare il servizio mDNS (come spiegato qui) per consentire ai client di collegarsi utilizzando un alias (ad esempio esp32web):
mdns_server_t* mDNS = NULL; ESP_ERROR_CHECK(mdns_init(TCPIP_ADAPTER_IF_AP, &mDNS)); ESP_ERROR_CHECK(mdns_set_hostname(mDNS, "esp32web")); ESP_ERROR_CHECK(mdns_set_instance(mDNS, "esp32 webserver")); |
Se il dispositivo che utilizziamo supporta mDNS, il sito web sarà quindi accessibile usando l’indirizzo esp32web.local:
Demo
Il programma completo è disponibile nel mio repository Github. Una volta caricato sulla devboard, sarà disponibile una nuova rete wifi:
collegandosi a tale rete il proprio PC otterrà un IP sulla rete 192.168.1.0/24:
e collegandosi via browser al sito http://esp32web.local (o http://192.168.1.1) sarà possibile accedere al sito pubblicato:
Hi,
I don’t see the sample code in your Git repo. Is that normal ?
Thanks,
Hi, sorry I forgot to sync the local repo… now it’s present
Salve Luca, e complimenti per la serie di tutorial, veramente preziosi.
Hai in programma una puntata su un server web con pagine dinamiche, che prevedano cioè input da parte dell’utente e visualizzazione di dati variabili (tipicamente, il valore letto da un sensore)?
Grazie.
Ciao Gian Luigi, se guardi il progetto ESP32Lights trovi già un sito dinamico che visualizza lo stato del sensore di luminosità e riceve soglie e programmazione oraria da parte dell’utente
Grazie Luca, è esattamente quello che mi serviva!
Hi Luca,
Thanks for your website, very useful!
Have you tried to run an HTTP server in SoftAp + STA mode?
It seems that when SoftAP+STA mode is selected, the HTTP server is only accessible via SoftAP…
Hi Franck… no never tried before. With SoftAP+STA esp32 creates two “interfaces”… it might be (but I have to verify in the source code) that lwIP only binds to the first one.
I’ll let you know if I discover something…
Yeah, that’s my guess as well…
I am still trying to figure it out. I will post here if I get an answer.
ESP_Angus on Espressif forum has found the issue:
https://www.esp32.com/viewtopic.php?f=2&t=6851&p=29854#p29854
Hi, i have one question. Do you think it would be possible to deliver wikipedia content (stored offine in a 128 gb sdcard) by wifi, using a cheap ESP32 in AP mode, reading data from sccard. – this would revolutionize content delivery to development countries… e.g. my friends in Tanzania, with respect to power consumption and solar driven power. – Do you know or does anybody here know a similiar approach?
Thank you
regards from Berlin
gerhard
lorawan.berlin@gmail.com
Hi! I think it’s possible (the webserver implementation in the framework is able to publish rich HTML content). I’m not aware of any existing projects but it seems a great idea!
Hi Luca. I tried your code but my IDF prints a message project “does not appear to contain CMakeLists.txt”.
Can you please help me with this problem?
Thank you.
John
Hi!Did you manage to resolve this issue?
Hi Luca.
Do you have a Demo video?
Thanks you
no, sorry… it’s a very straightforward and basic example so I didn’t expect the need of a demo video