ESP32 Captive Portal to Configure Static and DHCP IP Setting

vaibhav sharma
6 min readJul 10, 2021

--

ESP32 is a device with integrated WiFi and BLE. It is kind of a boon for the IoT projects. Just give your SSID, password and IP configurations and integrate the things into the cloud. But, managing the IP settings and user credentials can be a headache to the user.

What if the User wants to change the WiFi credentials?

What if the user wants to switch the DHCP/static IP settings?

Flashing the ESP32 everytime is not reliable and not even the solution for these problems. Here in this tutorial we will be going to demonstrate.

  • How to create a captive portal.
  • Hosting a web form from the ESP32.
  • Uploading Data to SPIFFS
  • Reading and Writing from SPIFFS ESP32.
  • Creating a Soft Access Point and connecting to a station.

Creating a Captive Portal

A captive portal is a web page that is displayed to newly connected users t before they are granted broader access to network resources. Here we are serving three web pages to select between DHCP and Static IP Settings. we can define the IP address to ESP in two ways.

  • DHCP IP address- it is a way to dynamically assign the IP address to the device. The ESP’s default IP address is 192.168.4.1
  • Static IP address- assigning a permanent IP Adress to our network device. to provide the static IP to the device we need to define the IP address, gateway address, and subnet mask.

In the first webpage, the User is provided with the radio buttons to select between DHCP and Static IP settings. In the next webpage, we have to provide the IP related information to proceed further.

The HTML code for web pages can be found in this Github repository.

You can use any IDE or text editor like Sublime or notepad++ to make HTML web pages.

  • First Create an HTML webpage containing two radio buttons to choose between DHCP and Static IP Settings.
  • Now create the button to submit your response
  • Give some name to radio buttons. The ESP Web server class will take these names as arguments and get the response of the radio buttons using these arguments

Getting the Web Response From Web Pages to ESP32

Serving web pages from ESP 32 device is great fun. It can be anything from showing the temperature data in the webpage,turning the led’s from the custom webpage or storing the User WiFi credentials through a webpage. For this purpose, ESP 32 uses WebServer Class to server web pages.

  • First, Create an instance of WebServer class at port 80(HTTP port).
  • Now set up the ESP device as softAP. Give the SSID and passkey and assign a static IP to the device.
  • Begin the server.
//*********SSID and Pass for AP**************/ 
const char *ssidAP = "give SSID";
const char *passAP = "pass key";
//*********Static IPConfig**************/
IPAddress ap_local_IP(192,168,1,77);
IPAddress ap_gateway(192,168,1,254);
IPAddress ap_subnet(255,255,255,0);
//*********SoftAP Config**************/
WiFi.mode(WIFI_AP);
Serial.println(WiFi.softAP(ssidAP,passAP) ? "soft-AP setup": "Failed to connect");
delay(100);
Serial.println(WiFi.softAPConfig(ap_local_IP, ap_gateway, ap_subnet)? "Configuring Soft AP" : "Error in Configuration"); Serial.println(WiFi.softAPIP());
//begin the server
server.begin();
  • Create and serve the URL using different callbacks.
  • and handle the client asynchronously using handleClient.
server.on("/", handleRoot); server.on("/dhcp", handleDHCP); server.on("/static", handleStatic); // handle the responses server.handleClient();
  • To access the web pages. Connect to the AP that you have just created, listed within your WiFi networks. Now, go to the browser, Enter the IP configured by you in the last step and access the webpage.
  • Web server class takes the name given to inputs( ‘text’, ‘button’, ‘radiobutton’etc.) as arguments. It saves the responses of these inputs as arguments and we can get the values or check them using args(), arg(), hasArg() methods.
if(server.args()>0){ for(int i=0; i<=server.args();i++){ Serial.println(String(server.argName(i))+'\t' + String(server.arg(i))); }if(server.hasArg("ipv4static") && server.hasArg("gateway") && server.hasArg("subnet")){ staticSet(); }else if(server.arg("ipv4")!= ""){ dhcpSetManual(); }else{ dhcpSetDefault(); }

Static IP Configuration

So far we have understood how to connect to AP and how to get the values from the input fields of webpage.

In this step, we will configure the Static IP

  • Select the Static IP Setting and click on Submit button. You will be redirected to the next page.
  • In the next page enter the static IP address, gateway address and subnet Mask this page will be served at “/static” which is handled by handleStatic callback method.
String ipv4static = String(server.arg("ipv4static"));String gateway = String(server.arg("gateway"));String subnet = String(server.arg("subnet"));
  • Now, these values are in Strings and we need to convert these values in IP Address type.
  • First, convert the values into char array.
ipv4static.toCharArray(ipv4Arr,sizeof(ipv4static)+2); gateway.toCharArray(gatewayArr,sizeof(gateway)+2); subnet.toCharArray(subnetArr,sizeof(subnet)+2);
  • And parse the String values into bytes.
  • Create an IP address type of object and setup an Access Point using these static IP credentials
  • You can find the Access Point in the available WiFi Networks list.
byte ip[4];
parseBytes(ipv4Arr,'.', ip, 4, 10);
void parseBytes(const char* str, char sep, byte* bytes, int maxBytes, int base) {
for (int i = 0; i < maxBytes; i++) {
bytes[i] = strtoul(str, NULL, base);
// Convert byte str = strchr(str, sep);
// Find next separator
if (str == NULL || *str == '\0') {
break; // No more separators, exit }
str++; // Point to next character after separator
}}
ip0 = (uint8_t)ip[0];
ip1 = (uint8_t)ip[1];
ip2 = (uint8_t)ip[2];
ip3 = (uint8_t)ip[3];
IPAddress ap_local(ip0,ip1,ip2,ip3);
ap_localWeb_IP = ap_local;
WiFi.disconnect(true);
WiFi.mode(WIFI_AP);
Serial.println(WiFi.softAP(ssidAPWeb) ? "Setting up SoftAP" : "error setting up");
Serial.println(WiFi.softAPConfig(ap_localWeb_IP, ap_gate, ap_net) ? "Configuring softAP" : "not connected");

DHCP Settings

In this step, we will configure the DHCP Settings

WiFi.disconnect(false);
WiFi.enableAP(false);
InitAP();
isConnected = false;
void InitAP(){WiFi.enableAP(true);
WiFi.mode(WIFI_AP);
Serial.println(WiFi.softAP(ssidDhcpWeb) ? "SoftAP setup" : "Error Setting UP AP" );
delay(100);
Serial.println(WiFi.softAPConfig(ap_dhcp, ap_gateway, ap_subnet)? "Configuring Soft AP" : "Error in Configuration"); Serial.println(WiFi.softAPIP()); }

Read and Write From SPIFFS

Serial Peripheral Interface Flash File System, or SPIFFS for short. It’s a light-weight file system for microcontrollers with an SPI flash chip. The onboard flash chip of the ESP32 has plenty of space for your web pages. We have also stored our webpage in Flash System. There are a few steps we need to follow to upload data to spiffs

  • Download the ESP 32 SPIFFS data upload tool: https://github.com/me-no-dev/arduino-esp32fs-plugi...
  • In your Arduino sketchbook directory, create a tools directory if it doesn’t exist yet
  • Unpack the tool into the tools directory (the path will look like /Arduino/tools/ESP32FS/tool/esp32fs.jar)
  • Restart Arduino IDE
  • Open a sketch (or create a new one and save it)
  • Go to sketch directory (choose Sketch > Show Sketch Folder)
  • Create a directory named data and any files you want in the file system there. We have uploaded our HTML page with name webform.html
  • Make sure you have selected a board, port, and closed Serial Monitor
  • Select Tools > ESP8266 Sketch Data Upload. This should start uploading the files into the ESP8266 flash file system. When done, IDE status bar will display SPIFFS Image Uploaded message.
void handleDHCP(){File file = SPIFFS.open("/page_dhcp.html", "r"); server.streamFile(file,"text/html"); 
file.close();}
void handleStatic(){ File file = SPIFFS.open("/page_static.html", "r");
server.streamFile(file,"text/html");
file.close(); }

Writing to SPIFFS

Here we are writing the saved setting to the SPIFFS so that users should not have to go through these steps whenever device resets.

  • Convert the arguments received from the webpage to JSON objects
  • Write this JSON to the.txt file saved in SPIFFS.
String ipv4static = String(server.arg("ipv4static"));
String gateway = String(server.arg("gateway"));
String subnet = String(server.arg("subnet")); root["statickey"]="staticSet";
root["staticIP"] = ipv4static;
root["gateway"] = gateway;
root["subnet"] = subnet;
String JSONStatic;
char JSON[120];
root.printTo(Serial);
root.prettyPrintTo(JSONStatic); JSONStatic.toCharArray(JSON,sizeof(JSONStatic)+2);
File fileToWrite = SPIFFS.open("/ip_set.txt", FILE_WRITE); if(!fileToWrite){
Serial.println("Error opening SPIFFS"); } if(fileToWrite.print(JSON)){
Serial.println("--File Written");
}else{ Serial.println("--Error Writing File"); } fileToWrite.close(); }

Overall Code

The Over code for HTML and ESP32 can be found in this GitHub repository.

--

--

vaibhav sharma

Full Stack IoT developer working on effective Wireless Sensor Network