How to configure ESP8266 Web Server in Station and Access Point Mode

ESP8266 Web Server

Sharing is Caring!

Do you want to build a standalone ESP8266 web server, and collect sensor data or control various electronics over the internet?

This article outlines how you can set up such a simple webserver on ESP8266 and use it to control 4 LEDs in real-time via a web browser in your smartphone, laptop, or tablet.

For this tutorial, I will be using Arduino IDE to configure the ESP8266 webserver. To help you get started with NodeMCU ESP8266 and Arduino IDE, I have written a separate article that lists 5 simple steps to program ESP8266 using Arduino IDE:

Also, I will be using both the Station (STA) and the Access Point (AP) WiFi Modes of ESP8266 to build a standalone ESP8266 web server. You can refer to the following article to get a comprehensive overview of STA/AP modes and how to program ESP8266 in both of these modes:

Before I get my hands dirty with the code to configure the ESP8266 web server, let’s first understand the working of a simple web server in the context of the Internet.

What is a Web Server?

In the internet world, most of the devices communicate with each other using a client-server model. In such a model, there is a single web server that hosts files, images, text, videos, blog posts, or other relevant data of a specific website i.e., Wikipedia, Google, Yahoo, etc.

Multiple clients can connect to such a web server anytime and fetch relevant information. For example, you came across this webpage because you were interested in configuring the ESP8266 web server. Another user may be interested in reading about machine learning, so she will load a different web page related to the basics of machine learning.

Communication between a client and a web server takes place using HTTP Request or HTTP Response. To get any data or file from a web server, a client sends an HTTP request to the web server. In response, a web server sends the relevant data or file via HTTP Response.

What is Web Server
What is Web Server

In the majority of the cases, the web browser (Chrome, Edge, Safari, Opera) acts as the HTTP client and requests for a specific web page from the server via an HTTP request. The web server then returns the relevant web page as the HTTP response. Finally, the web browser renders the HTTP Response message into a human-readable format just like this blog post.

How ESP8266 Web Server Works

By now, you have a thorough understanding of a web server in the context of the internet, but how will this whole web server thing operate on a miniature ESP8266?

Don’t worry… It’s as easy as pie!

In simple words, a web browser has a lot of information but it only takes a specific action (or delivers a specific webpage) as per the HTTP request.

To host a standalone web server onto ESP8266, you will need to serve specific HTTP web pages to a client as per the HTTP request while taking some action alongside i.e., turning an LED on/off, reading the status of an input switch, etc.

Each web page is to be hosted on a different URL, and the client will need to pass a specific URL in the HTTP request to get a customized HTTP response from the ESP8266 web server. To control the LEDs, the ESP8266 web server will also perform a specific action i.e., Turn LED2 On, Turn LED3 Off, etc.

Since ESP8266 will be accessible via a Wi-Fi network either in AP or STA mode, the client will need to specify the ESP8266 IP address in the web browser to access the ESP8266 web server.

Hardware Interfacing

To evaluate the working of the ESP8266 web server, you need to assemble an electric circuit consisting of the following components:

  1. Breadboard
  2. NodeMCU ESP8266 12-E
  3. Light Emitting Diodes (LEDs) x 4
  4. 100 Ohm Resistor x 4

LED1, LED2, LED3, and LED4 will be interfaced to D0, D1, D2, and D5 pins of the NodeMCU ESP8266 respectively, as shown in the figure below:

ESP8266 Interfacing with LEDs
ESP8266 Interfacing with LEDs

Configuring ESP8266 Web Server in STA Mode

In STA mode, ESP8266 connects to a router’s WiFi network just like your smartphone or laptop. You can access the ESP8266 web server in a local network via the IP assigned to ESP8266.

ESP8266 Server Web Page in STA Mode
ESP8266 Web Server

Let’s now code up a standalone web server on ESP8266…

ESP8266 STA Web Server Code

To configure the ESP8266 web server in STA mode, compile and upload the following sketch in your NodeMCU ESP8266 using Arduino IDE. However, don’t forget to put in the SSID and Password of your router’s WiFi network in the following two variables:

  1. const char *SSID = “PTCL_BB”; //Put in the SSID of your Router’s WiFi
  2. const char *password = “F4D22ABF”; //Put in the Password of your Router’s WiFi
/*
 * This code will configure ESP8266 in station mode and it will then act as a web server after connecting to a WiFi Router. It will then turn On/Off 4 LEDs as per input from the connected client
 */

#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>

/*Specifying the SSID and Password of the WiFi*/

const char *ssid = "PTCL_BB";
const char *password = "F4D22ABF";

//Specifying the Webserver instance to connect with HTTP Port: 80
ESP8266WebServer server(80);

//Specifying the Pins connected from LED1 to LED4
uint8_t led1_pin=D0;
uint8_t led2_pin=D1;
uint8_t led3_pin=D2;
uint8_t led4_pin=D5;

//Specifying the boolean variables indicating the status of LED1 to LED4
bool led1_status=false, led2_status=false, led3_status=false, led4_status=false;

void setup() {
  //Starting the serial communication channel
  Serial.begin(115200);
  Serial.println();
  Serial.print("Connecting to ");
  Serial.print(ssid);

 //Output mode for the LED Pins
  pinMode(led1_pin,OUTPUT);
  pinMode(led2_pin,OUTPUT);
  pinMode(led3_pin,OUTPUT);
  pinMode(led4_pin,OUTPUT);
  
  //Connecting to the local WiFi network
  WiFi.begin(ssid,password);

  //Keep checking the WiFi status until it is connected to the wifi network

  while(WiFi.status()!=WL_CONNECTED)
  {
    delay(1000);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print("WiFi Connected with IP Address: ");
  Serial.println(WiFi.localIP());

  //Specifying the functions which will be executed upon corresponding GET request from the client
  server.on("/",handle_OnConnect);
  server.on("/led1on",handle_led1on);
  server.on("/led1off",handle_led1off);
  server.on("/led2on",handle_led2on);
  server.on("/led2off",handle_led2off);
  server.on("/led3on",handle_led3on);
  server.on("/led3off",handle_led3off);
  server.on("/led4on",handle_led4on);
  server.on("/led4off",handle_led4off);
  server.onNotFound(handle_NotFound);
  
  //Starting the Server
  server.begin();
  Serial.println("HTTP Server Started");
}

void loop() {

  if(WiFi.status()==WL_CONNECTED)//Check if ESP8266 is still connected to the internet
  {
    //Assign the server to handle the clients
    server.handleClient();

    //Turn the LEDs ON/OFF as per their status set by the connected client
  
    //LED1
    if(led1_status==false)
    {
      digitalWrite(led1_pin,LOW);
    }
    else
    {
      digitalWrite(led1_pin,HIGH);
    }
  
    //LED2
    if(led2_status==false)
    {
      digitalWrite(led2_pin,LOW);
    }
    else
    {
      digitalWrite(led2_pin,HIGH);
    }
  
    //LED3
    if(led3_status==false)
    {
      digitalWrite(led3_pin,LOW);
    }
    else
    {
      digitalWrite(led3_pin,HIGH);
    }
  
    //LED4
    if(led4_status==false)
    {
      digitalWrite(led4_pin,LOW);
    }
    else
    {
      digitalWrite(led4_pin,HIGH);
    }
  }
  else
  {
    Serial.println("WiFi Disconnected!!!");
    Serial.print("Trying to establish the connection...");
    
    //Keep checking the WiFi status until it is connected to the wifi network
    while(WiFi.status()!=WL_CONNECTED)
    {
      delay(1000);
      Serial.print(".");
    }
    Serial.println("");
    Serial.print("WiFi Connected with IP Address: ");
    Serial.println(WiFi.localIP());
  }
}

void handle_OnConnect()
{
  Serial.println("Client Connected");
  server.send(200, "text/html", HTML()); 
}

void handle_led1on()
{
  Serial.println("LED1 ON");
  led1_status=true;
  server.send(200, "text/html", HTML());
}

void handle_led1off()
{
  Serial.println("LED1 OFF");
  led1_status=false;
  server.send(200, "text/html", HTML());
}

void handle_led2on()
{
  Serial.println("LED2 ON");
  led2_status=true;
  server.send(200, "text/html", HTML());
}

void handle_led2off()
{
  Serial.println("LED2 OFF");
  led2_status=false;
  server.send(200, "text/html", HTML());
}

void handle_led3on()
{
  Serial.println("LED3 ON");
  led3_status=true;
  server.send(200, "text/html", HTML());
}

void handle_led3off()
{
  Serial.println("LED3 OFF");
  led3_status=false;
  server.send(200, "text/html", HTML());
}

void handle_led4on()
{
  Serial.println("LED4 ON");
  led4_status=true;
  server.send(200, "text/html", HTML());
}

void handle_led4off()
{
  Serial.println("LED4 OFF");
  led4_status=false;
  server.send(200, "text/html", HTML());
}

void handle_NotFound()
{
  server.send(404, "text/plain", "Not found");
}

String HTML()
{
  String msg="<!DOCTYPE html> <html>\n";
  msg+="<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">\n";
  msg+="<title>LED Control</title>\n";
  msg+="<style>html{font-family:Helvetica; display:inline-block; margin:0px auto; text-align:center;}\n";
  msg+="body{margin-top: 50px;} h1{color: #444444; margin: 50px auto 30px;} h3{color:#444444; margin-bottom: 50px;}\n";
  msg+=".button{display:block; width:80px; background-color:#f48100; border:none; color:white; padding: 13px 30px; text-decoration:none; font-size:25px; margin: 0px auto 35px; cursor:pointer; border-radius:4px;}\n";
  msg+=".button-on{background-color:#f48100;}\n";
  msg+=".button-on:active{background-color:#f48100;}\n";
  msg+=".button-off{background-color:#26282d;}\n";
  msg+=".button-off:active{background-color:#26282d;}\n";
  msg+="</style>\n";
  msg+="</head>\n";
  msg+="<body>\n";
  msg+="<h1>ESP8266 Web Server</h1>\n";
  msg+="<h3>Using Station (STA) Mode</h3>\n";
  
  if(led1_status==false)
  {
    msg+="<p>LED1 Status: OFF</p><a class=\"button button-on\" href=\"/led1on\">ON</a>\n";    
  }
  else
  {
    msg+="<p>LED1 Status: ON</p><a class=\"button button-off\" href=\"/led1off\">OFF</a>\n";
  }

  if(led2_status==false)
  {
    msg+="<p>LED2 Status: OFF</p><a class=\"button button-on\" href=\"/led2on\">ON</a>\n";    
  }
  else
  {
    msg+="<p>LED2 Status: ON</p><a class=\"button button-off\" href=\"/led2off\">OFF</a>\n";
  }

  if(led3_status==false)
  {
    msg+="<p>LED3 Status: OFF</p><a class=\"button button-on\" href=\"/led3on\">ON</a>\n";    
  }
  else
  {
    msg+="<p>LED3 Status: ON</p><a class=\"button button-off\" href=\"/led3off\">OFF</a>\n";
  }

  if(led4_status==false)
  {
    msg+="<p>LED4 Status: OFF</p><a class=\"button button-on\" href=\"/led4on\">ON</a>\n";    
  }
  else
  {
    msg+="<p>LED4 Status: ON</p><a class=\"button button-off\" href=\"/led4off\">OFF</a>\n";
  }
  
  msg+="</body>\n";
  msg+="</html>\n";
  return msg;
}

Once you have successfully uploaded the code in ESP8266, open the serial terminal with a Baud Rate of 115200. You will get an IP address assigned to ESP8266 by your router in the local area network:

ESP8266 Web Server Serial Monitor in STA Mode
ESP8266 Web Server Serial Monitor in STA Mode

Enter the assigned IP in your web browser (chrome, edge, safari), and an interface will be displayed on a web page to control LEDs:

ESP8266 Server Web Page in STA Mode
ESP8266 Server Web Page in STA Mode

Now you can turn the LEDs on/off simply by pressing the relevant interface buttons:

ESP8266 Web Server STA - LED2,LED4=ON - LED1,LED3=OFF
ESP8266 Web Server STA – LED2,LED4=ON – LED1,LED3=OFF
ESP8266 Web Server STA - LED2, LED3, LED4=ON - LED1=OFF
ESP8266 Web Server STA – LED2, LED3, LED4=ON – LED1=OFF
ESP8266 Web Server STA - LED2, LED3, LED4=OFF - LED1=ON
ESP8266 Web Server STA – LED2, LED3, LED4=OFF – LED1=ON
ESP8266 Web Server STA - LED1,LED3=ON - LED2,LED4=OFF
ESP8266 Web Server STA – LED1,LED3=ON – LED2,LED4=OFF

If all went well, you should be able to control all the LEDs via a web browser on your laptop, mobile, or tablet.

Let’s now explore how this code works so that you can customize it as per your requirements…

Code Explanation

Firstly, include ESP8266WiFi.h and ESP8266WebServer.h to give the WiFi and Web Server capability to ESP8266. Then specify the Router’s WiFi Network SSID and Password:

#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
/*Specifying the SSID and Password of the WiFi*/
const char *ssid = "PTCL_BB";
const char *password = "F4D22ABF";

Since HTTP Request and HTTP Response use Port 80 to communicate, you need to instantiate a web server with the same port:

//Specifying the Webserver instance to connect with HTTP Port: 80
ESP8266WebServer server(80);

Define the initial status of LEDs and also the pins of NodeMCU ESP8266 which are interfaced to LEDs:

//Specifying the Pins connected from LED1 to LED4
uint8_t led1_pin=D0;
uint8_t led2_pin=D1;
uint8_t led3_pin=D2;
uint8_t led4_pin=D5;
//Specifying the boolean variables indicating the status of LED1 to LED4
bool led1_status=false, led2_status=false, led3_status=false, led4_status=false;

setup()

Specify the serial communication channel with the Baud Rate of 115200, and declare the Output direction of the NodeMCU ESP8266 pins:

void setup() {
  //Starting the serial communication channel
  Serial.begin(115200);
  Serial.println();
  Serial.print("Connecting to ");
  Serial.print(ssid);
 //Output mode for the LED Pins
  pinMode(led1_pin,OUTPUT);
  pinMode(led2_pin,OUTPUT);
  pinMode(led3_pin,OUTPUT);
  pinMode(led4_pin,OUTPUT);

Connect the ESP8266 with the specified WiFi network and print the assigned IP on the serial monitor, which will be later used to access the web server:

//Connecting to the local WiFi network
  WiFi.begin(ssid,password);
  //Keep checking the WiFi status until it is connected to the wifi network
  while(WiFi.status()!=WL_CONNECTED)
  {
    delay(1000);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print("WiFi Connected with IP Address: ");
  Serial.println(WiFi.localIP());

Specify the handles (or functions) which will be executed whenever a user clicks on a specific LED button to turn it on/off. Finally, start the web server and exit the setup() loop:

  //Specifying the functions which will be executed upon corresponding GET request from the client
  server.on("/",handle_OnConnect);
  server.on("/led1on",handle_led1on);
  server.on("/led1off",handle_led1off);
  server.on("/led2on",handle_led2on);
  server.on("/led2off",handle_led2off);
  server.on("/led3on",handle_led3on);
  server.on("/led3off",handle_led3off);
  server.on("/led4on",handle_led4on);
  server.on("/led4off",handle_led4off);
  server.onNotFound(handle_NotFound);
//Starting the Server
  server.begin();
  Serial.println("HTTP Server Started");
}

LED Handles and HTTP Communication

When you specify the IP address of the ESP8266 in your web browser (HTTP client), the ESP8266 web server displays a web page with the current status of LEDs using the handle ‘handle_OnConnect’ as specified in the setup() loop.

To turn the LED2 off, you can specify the IP address of ESP8266 with the extension ‘/led2off’ in your browser i.e., 192.168.1.8/led2off. This will execute the handle ‘handle_led2off’, which will turn LED2 Off and load a completely new webpage indicating the current status of all LEDs.

ESP8266 will load a separate web page for the on/off states of all LEDs as per the corresponding handlers defined in the setup() loop. Thus, there will be 8 different web pages to turn 4 LEDs on/off, plus, one default handler (‘handle_OnConnect’) and an invalid URL handler (‘handle_NotFound’).

You can specify these URLs yourself in the web browser, or you can click the buttons to generate these URLs. The choice is yours, however, I prefer to use buttons as they provide a more intuitive way to control the LEDs.

These handler functions are specified as follows in the code:

void handle_OnConnect()
{
  Serial.println("Client Connected");
  server.send(200, "text/html", HTML()); 
}

void handle_led1on()
{
  Serial.println("LED1 ON");
  led1_status=true;
  server.send(200, "text/html", HTML());
}

void handle_led1off()
{
  Serial.println("LED1 OFF");
  led1_status=false;
  server.send(200, "text/html", HTML());
}

void handle_led2on()
{
  Serial.println("LED2 ON");
  led2_status=true;
  server.send(200, "text/html", HTML());
}

void handle_led2off()
{
  Serial.println("LED2 OFF");
  led2_status=false;
  server.send(200, "text/html", HTML());
}

void handle_led3on()
{
  Serial.println("LED3 ON");
  led3_status=true;
  server.send(200, "text/html", HTML());
}

void handle_led3off()
{
  Serial.println("LED3 OFF");
  led3_status=false;
  server.send(200, "text/html", HTML());
}

void handle_led4on()
{
  Serial.println("LED4 ON");
  led4_status=true;
  server.send(200, "text/html", HTML());
}

void handle_led4off()
{
  Serial.println("LED4 OFF");
  led4_status=false;
  server.send(200, "text/html", HTML());
}

void handle_NotFound()
{
  server.send(404, "text/plain", "Not found");
}

HTML() function in each handler function specifies a custom web page that will be loaded in case a corresponding handler is called by specifying the desired URL either explicitly or via interface buttons:

String HTML()
{
  String msg="<!DOCTYPE html> <html>\n";
  msg+="<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">\n";
  msg+="<title>LED Control</title>\n";
  msg+="<style>html{font-family:Helvetica; display:inline-block; margin:0px auto; text-align:center;}\n";
  msg+="body{margin-top: 50px;} h1{color: #444444; margin: 50px auto 30px;} h3{color:#444444; margin-bottom: 50px;}\n";
  msg+=".button{display:block; width:80px; background-color:#f48100; border:none; color:white; padding: 13px 30px; text-decoration:none; font-size:25px; margin: 0px auto 35px; cursor:pointer; border-radius:4px;}\n";
  msg+=".button-on{background-color:#f48100;}\n";
  msg+=".button-on:active{background-color:#f48100;}\n";
  msg+=".button-off{background-color:#26282d;}\n";
  msg+=".button-off:active{background-color:#26282d;}\n";
  msg+="</style>\n";
  msg+="</head>\n";
  msg+="<body>\n";
  msg+="<h1>ESP8266 Web Server</h1>\n";
  msg+="<h3>Using Station (STA) Mode</h3>\n";
  if(led1_status==false)
  {
    msg+="<p>LED1 Status: OFF</p><a class=\"button button-on\" href=\"/led1on\">ON</a>\n";    
  }
  else
  {
    msg+="<p>LED1 Status: ON</p><a class=\"button button-off\" href=\"/led1off\">OFF</a>\n";
  }
  if(led2_status==false)
  {
    msg+="<p>LED2 Status: OFF</p><a class=\"button button-on\" href=\"/led2on\">ON</a>\n";    
  }
  else
  {
    msg+="<p>LED2 Status: ON</p><a class=\"button button-off\" href=\"/led2off\">OFF</a>\n";
  }
  if(led3_status==false)
  {
    msg+="<p>LED3 Status: OFF</p><a class=\"button button-on\" href=\"/led3on\">ON</a>\n";    
  }
  else
  {
    msg+="<p>LED3 Status: ON</p><a class=\"button button-off\" href=\"/led3off\">OFF</a>\n";
  }
  if(led4_status==false)
  {
    msg+="<p>LED4 Status: OFF</p><a class=\"button button-on\" href=\"/led4on\">ON</a>\n";    
  }
  else
  {
    msg+="<p>LED4 Status: ON</p><a class=\"button button-off\" href=\"/led4off\">OFF</a>\n";
  }
  msg+="</body>\n";
  msg+="</html>\n";
  return msg;
}

loop()

In the loop function, keep checking if ESP8266 is still connected to the internet.

void loop() {
  if(WiFi.status()==WL_CONNECTED)//Check if ESP8266 is still connected to the internet

If connected, configure the server to handle each incoming client and update the Output status of the LEDs as per the status variables updated in the corresponding handler function.

    //Assign the server to handle the clients
    server.handleClient();
    //Turn the LEDs ON/OFF as per their status set by the connected client
    //LED1
    if(led1_status==false)
    {
      digitalWrite(led1_pin,LOW);
    }
    else
    {
      digitalWrite(led1_pin,HIGH);
    }
    //LED2
    if(led2_status==false)
    {
      digitalWrite(led2_pin,LOW);
    }
    else
    {
      digitalWrite(led2_pin,HIGH);
    }
    //LED3
    if(led3_status==false)
    {
      digitalWrite(led3_pin,LOW);
    }
    else
    {
      digitalWrite(led3_pin,HIGH);
    }
    //LED4
    if(led4_status==false)
    {
      digitalWrite(led4_pin,LOW);
    }
    else
    {
      digitalWrite(led4_pin,HIGH);
    }
  }

Configuring ESP8266 Web Server in AP Mode

In Access Point (AP) mode, ESP8266 will advertise its WiFi network and you can access the web server hosted on ESP8266 by connecting to the advertised network. However, you will still need to provide the IP assigned to ESP8266 to access the web server.

Let’s now write the code to set up the ESP8266 web server in AP Mode…

ESP8266 AP Web Server Code

To configure the ESP8266 web server in AP mode, compile and upload the following sketch in your NodeMCU ESP8266 using Arduino IDE.

/*
 * This code will configure ESP8266 in SoftAP mode and will act as a web server for all the connecting devices. It will then turn On/Off 4 LEDs as per input from the connected station devices.
 */

#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>

/*Specifying the SSID and Password of the AP*/

const char* ap_ssid = "ESP8266"; //Access Point SSID
const char* ap_password= "embedded-robotics"; //Access Point Password
uint8_t max_connections=8;//Maximum Connection Limit for AP
int current_stations=0, new_stations=0;

//Specifying the Webserver instance to connect with HTTP Port: 80
ESP8266WebServer server(80);

//Specifying the Pins connected from LED1 to LED4
uint8_t led1_pin=D0;
uint8_t led2_pin=D1;
uint8_t led3_pin=D2;
uint8_t led4_pin=D5;

//Specifying the boolean variables indicating the status of LED1 to LED4
bool led1_status=false, led2_status=false, led3_status=false, led4_status=false;

void setup() {
  //Start the serial communication channel
  Serial.begin(115200);
  Serial.println();

  //Output mode for the LED Pins
  pinMode(led1_pin,OUTPUT);
  pinMode(led2_pin,OUTPUT);
  pinMode(led3_pin,OUTPUT);
  pinMode(led4_pin,OUTPUT);
  
  //Setting the AP Mode with SSID, Password, and Max Connection Limit
  if(WiFi.softAP(ap_ssid,ap_password,1,false,max_connections)==true)
  {
    Serial.print("Access Point is Created with SSID: ");
    Serial.println(ap_ssid);
    Serial.print("Max Connections Allowed: ");
    Serial.println(max_connections);
    Serial.print("Access Point IP: ");
    Serial.println(WiFi.softAPIP());
  }
  else
  {
    Serial.println("Unable to Create Access Point");
  }

  //Specifying the functions which will be executed upon corresponding GET request from the client
  server.on("/",handle_OnConnect);
  server.on("/led1on",handle_led1on);
  server.on("/led1off",handle_led1off);
  server.on("/led2on",handle_led2on);
  server.on("/led2off",handle_led2off);
  server.on("/led3on",handle_led3on);
  server.on("/led3off",handle_led3off);
  server.on("/led4on",handle_led4on);
  server.on("/led4off",handle_led4off);
  server.onNotFound(handle_NotFound);
  
  //Starting the Server
  server.begin();
  Serial.println("HTTP Server Started");
}

void loop() {
  //Assign the server to handle the clients
  server.handleClient();
    
  //Continuously check how many stations are connected to Soft AP and notify whenever a new station is connected or disconnected
  new_stations=WiFi.softAPgetStationNum();
  
  if(current_stations<new_stations)//Device is Connected
  {
    current_stations=new_stations;
    Serial.print("New Device Connected to SoftAP... Total Connections: ");
    Serial.println(current_stations);
  }
  
  if(current_stations>new_stations)//Device is Disconnected
  {
    current_stations=new_stations;
    Serial.print("Device disconnected from SoftAP... Total Connections: ");
    Serial.println(current_stations);
  }

  //Turn the LEDs ON/OFF as per their status set by the connected client
  
  //LED1
  if(led1_status==false)
  {
    digitalWrite(led1_pin,LOW);
  }
  else
  {
    digitalWrite(led1_pin,HIGH);
  }

  //LED2
  if(led2_status==false)
  {
    digitalWrite(led2_pin,LOW);
  }
  else
  {
    digitalWrite(led2_pin,HIGH);
  }

  //LED3
  if(led3_status==false)
  {
    digitalWrite(led3_pin,LOW);
  }
  else
  {
    digitalWrite(led3_pin,HIGH);
  }

  //LED4
  if(led4_status==false)
  {
    digitalWrite(led4_pin,LOW);
  }
  else
  {
    digitalWrite(led4_pin,HIGH);
  }
}

void handle_OnConnect()
{
  Serial.println("Client Connected");
  server.send(200, "text/html", HTML()); 
}

void handle_led1on()
{
  Serial.println("LED1 ON");
  led1_status=true;
  server.send(200, "text/html", HTML());
}

void handle_led1off()
{
  Serial.println("LED1 OFF");
  led1_status=false;
  server.send(200, "text/html", HTML());
}

void handle_led2on()
{
  Serial.println("LED2 ON");
  led2_status=true;
  server.send(200, "text/html", HTML());
}

void handle_led2off()
{
  Serial.println("LED2 OFF");
  led2_status=false;
  server.send(200, "text/html", HTML());
}

void handle_led3on()
{
  Serial.println("LED3 ON");
  led3_status=true;
  server.send(200, "text/html", HTML());
}

void handle_led3off()
{
  Serial.println("LED3 OFF");
  led3_status=false;
  server.send(200, "text/html", HTML());
}

void handle_led4on()
{
  Serial.println("LED4 ON");
  led4_status=true;
  server.send(200, "text/html", HTML());
}

void handle_led4off()
{
  Serial.println("LED4 OFF");
  led4_status=false;
  server.send(200, "text/html", HTML());
}

void handle_NotFound()
{
  server.send(404, "text/plain", "Not found");
}

String HTML()
{
  String msg="<!DOCTYPE html> <html>\n";
  msg+="<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">\n";
  msg+="<title>LED Control</title>\n";
  msg+="<style>html{font-family:Helvetica; display:inline-block; margin:0px auto; text-align:center;}\n";
  msg+="body{margin-top: 50px;} h1{color: #444444; margin: 50px auto 30px;} h3{color:#444444; margin-bottom: 50px;}\n";
  msg+=".button{display:block; width:80px; background-color:#f48100; border:none; color:white; padding: 13px 30px; text-decoration:none; font-size:25px; margin: 0px auto 35px; cursor:pointer; border-radius:4px;}\n";
  msg+=".button-on{background-color:#f48100;}\n";
  msg+=".button-on:active{background-color:#f48100;}\n";
  msg+=".button-off{background-color:#26282d;}\n";
  msg+=".button-off:active{background-color:#26282d;}\n";
  msg+="</style>\n";
  msg+="</head>\n";
  msg+="<body>\n";
  msg+="<h1>ESP8266 Web Server</h1>\n";
  msg+="<h3>Using Access Point (AP) Mode</h3>\n";
  
  if(led1_status==false)
  {
    msg+="<p>LED1 Status: OFF</p><a class=\"button button-on\" href=\"/led1on\">ON</a>\n";    
  }
  else
  {
    msg+="<p>LED1 Status: ON</p><a class=\"button button-off\" href=\"/led1off\">OFF</a>\n";
  }

  if(led2_status==false)
  {
    msg+="<p>LED2 Status: OFF</p><a class=\"button button-on\" href=\"/led2on\">ON</a>\n";    
  }
  else
  {
    msg+="<p>LED2 Status: ON</p><a class=\"button button-off\" href=\"/led2off\">OFF</a>\n";
  }

  if(led3_status==false)
  {
    msg+="<p>LED3 Status: OFF</p><a class=\"button button-on\" href=\"/led3on\">ON</a>\n";    
  }
  else
  {
    msg+="<p>LED3 Status: ON</p><a class=\"button button-off\" href=\"/led3off\">OFF</a>\n";
  }

  if(led4_status==false)
  {
    msg+="<p>LED4 Status: OFF</p><a class=\"button button-on\" href=\"/led4on\">ON</a>\n";    
  }
  else
  {
    msg+="<p>LED4 Status: ON</p><a class=\"button button-off\" href=\"/led4off\">OFF</a>\n";
  }
  
  msg+="</body>\n";
  msg+="</html>\n";
  return msg;
}

Once you have successfully uploaded the code in ESP8266, open the serial terminal with a Baud Rate of 115200. You will get an IP address assigned to ESP8266 in its advertised local network:

ESP8266 Web Server Serial Monitor in AP Mode
ESP8266 Web Server Serial Monitor in AP Mode

Next, you need to connect your laptop/mobile to the WiFi network advertised by ESP8266 as an Access Point. In the sketch, SSID and Password of the advertised network are specified as “ESP8266” and “embedded-robotics”, respectively. You can change these as per your liking.

Please note that you will lose access to the internet by doing so, but you can still communicate with the server hosted on ESP8266 because you are connected to its WiFi network:

Laptop Connected to ESP8266 Wifi Network in AP Mode
Laptop Connected to ESP8266 WiFi Network in AP Mode

Enter the assigned IP in your web browser (chrome, edge, safari), and an interface will be displayed on a web page to control the LEDs. Now you can turn the LEDs on/off simply by pressing the relevant interface buttons:

ESP8266 Web Server AP -LED2,LED3=ON -LED1,LED4=OFF
ESP8266 Web Server AP -LED2,LED3=ON -LED1,LED4=OFF
ESP8266 Web Server AP -LED1,LED4=ON -LED2,LED3=OFF
ESP8266 Web Server AP -LED1,LED4=ON -LED2,LED3=OFF
ESP8266 Web Server AP - LED3=ON - LED1, LED2, LED4=OFF
ESP8266 Web Server AP – LED3=ON – LED1, LED2, LED4=OFF
ESP8266 Web Server AP - LED2=ON -LED1, LED3, LED4=OFF
ESP8266 Web Server AP – LED2=ON -LED1, LED3, LED4=OFF

If all went well, you should be able to control all the LEDs via a web browser by connecting to the WiFi network advertised by ESP8266 itself.

Now, how cool is that!

Let’s explore the minor changes which you need to make in the ESP8266 web server STA code to operate it in AP mode…

Code Explanation

If you truly understand how we configured the ESP8266 web server in STA mode, you don’t need to understand much to set up the web server in AP mode.

All you need to do is to replace the STA code of ESP8266 with that of AP mode and the rest of the implementation details will remain the same.

Firstly, specify the details about WiFi Access Point (AP) rather than your router:

/*Specifying the SSID and Password of the AP*/
const char* ap_ssid = "ESP8266"; //Access Point SSID
const char* ap_password= "embedded-robotics"; //Access Point Password
uint8_t max_connections=8;//Maximum Connection Limit for AP
int current_stations=0, new_stations=0;

Finally, configure the AP mode for the ESP8266 with SSID, Password, and Max Connection Limit in the setup() loop:

if(WiFi.softAP(ap_ssid,ap_password,1,false,max_connections)==true)
  {
    Serial.print("Access Point is Created with SSID: ");
    Serial.println(ap_ssid);
    Serial.print("Max Connections Allowed: ");
    Serial.println(max_connections);
    Serial.print("Access Point IP: ");
    Serial.println(WiFi.softAPIP());
  }
  else
  {
    Serial.println("Unable to Create Access Point");
  }

Conclusion

ESP8266 is not only a miniature microcontroller that allows you to access the internet, but also gives you the option of hosting a standalone web server. Besides, you can host the web server either in Station Mode or Access Point Mode. Through that webserver, you can control the electronic components interfaced with the ESP8266 or even collect remote sensor data.

This article illustrated how you can control 4 LEDs over the internet through the ESP8266 web server in both STA and AP mode. The web server was accessed using the web browser as the HTTP client on mobile, laptop, or tablet. This allowed the user to manipulate the state of the LEDs in real-time over the internet. This technique can be used to build an isolated Home Automation system in which you can trigger the state of electronic devices with the help of the relays, or even host a simple web server that can satisfy the queries of HTTP clients.

Sharing is Caring!

Subscribe for Latest Articles

Don't miss new updates on your email!

2 thoughts on “How to configure ESP8266 Web Server in Station and Access Point Mode”

  1. Hi Awais Naeem,

    First of all, thanks for sharing your knowledge.
    It is clearly and easy to read.

    I just started with the ESP8266 and the Arduino IDE and followed your writing ‘5 Simple Steps for Programming ESP8266 NodeMCU 12E using Arduino IDE’
    Loaded the Blink program and it’s running. Perfect.

    After that I followed ‘How to configure ESP8266 Web Server in Station and Access Point Mode’ and tried to compile the ‘ESP8266 STA Web Server Code’
    I directly get the compile error: ‘Server_Station_Mode:17:18: error: ‘D0’ was not declared in this scope;

    Any idea which file is missing or which setting is wrong?

    Many thanks,

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top