One of the most frequent questions I receive from my website’s contact form or from my Facebook page is whether it’s possible to publish an HTTP server when the esp32 chip is working in SoftAP mode, that is when it publishes its own wifi network.
In previous tutorials (18 – Access Point and 20 – Webserver) I’ve already blogged about the two subjects separately, today I’ll explain how to combine them.
Access Point
Let’s start defining the parameters of the TCP/IP network will be published by the esp32 chip. You have to choose an addressing plan, that is which IP addresses will belong to the network. You can use some of the IP addresses IANA assigned to private networks (RFC1918):
[checklist]
- 10.0.0.0/8
- 172.16.0.0/12
- 192.168.0.0/16
[/checklist]
In this example I’m going to use the network 192.168.1.0 with netmask 255.255.255.0 (/24), that is a network with 254 usable addresses (192.168.1.1 – 192.168.1.254). You have to statically assign to the esp32 chip an address that belongs to that network; to make things easy I chose the first one (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)); |
The other devices which will connect to the network will dynamically configure their IP address, thanks to the DHCP service. To use the DHCP server in your program, first you have to stop it before configuring the network settings and then start it:
ESP_ERROR_CHECK(tcpip_adapter_dhcps_stop(TCPIP_ADAPTER_IF_AP)); [...] ESP_ERROR_CHECK(tcpip_adapter_dhcps_start(TCPIP_ADAPTER_IF_AP)); |
After having configured the TCP/IP network and the related services, you can set up the wifi interface of the esp32 chip and activate the SoftAP mode:
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)); |
You have to prepare a wifi_config_t struct that contains all the parameters for the wifi network (SSID, authentication…) and pass it to the method:
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_AP, &ap_config)); |
You can hardcode the parameters in the program, or make them configurable via menuconfig (as in this example) or Possiamo decidere di inserire i parametri hardcoded nel programma, di renderli configurabili tramite menuconfig (come nell’esempio) or even read them from a config file or from NVS variables.
Finally start the wifi interface with:
ESP_ERROR_CHECK(esp_wifi_start()); |
HTTP server
Now you can use the Netconn API of the lwip library to bind your program to the TCP/80 port (it’s the standard port used by the HTTP protocol) and to listen for incoming connections:
struct netconn *conn; conn = netconn_new(NETCONN_TCP); netconn_bind(conn, NULL, 80); netconn_listen(conn); |
The accept() method blocks the program until a new connection is accepted:
struct netconn *newconn; netconn_accept(conn, &newconn); |
After having established the connection, your program must speak the same language (protocol) of the client; in this case the HTTP protocol used by web browsers.
To keep the example simple, it will publish a static website, whose content is stored in an SPIFFS partition (see the ESP32lights project for more information). Therefore, the program will answer requests in the form GET <resource> looking for the resource in the SPIFFS partition and, if found, sending its content using the netconn_write() method:
Bonus, mDNS
To be able to connect to the HTTP server published by the esp32 chip, a client must know the IP address (192.168.1.1) assigned to the chip.
We can leverage the mDNS service (as explained here) to allow the client to connect using an alias (for example 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")); |
If the device you’re using supports the mDNS service, it will be possible to connect to the website using the address esp32web.local:
Demo
The complete program is available in my Github repository. After having loaded it on your devboard, a new wifi network will be available:
if you connect to that network, your device will be assigned an IP addess on the 192.168.1.0/24 network:
and you’ll be able to point the browser to http://esp32web.local (or http://192.168.1.1) and display the website:
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