Nurgaliyev Shakhizat
Published © GPL3+

Internet-Controlled LED Using ESP32-Based Web Server

In this article I will explain how to use the Arduino IDE to create a web server based on ESP32 that allows to turn on/off LED remotely.

BeginnerProtip3 hours8,889
Internet-Controlled LED Using ESP32-Based Web Server

Things used in this project

Story

Read more

Schematics

uploads2ftmp2f78242204-3d82-4ec4-ade3-44f797f8bf4e2funtitledsketch2_bb_KCa1Q7x0Xh.jpg

Code

ESP32_Web_Server.ino

Arduino
// Import required libraries
#include "WiFi.h"
#include "ESPAsyncWebServer.h"
#include "SPIFFS.h"
#include <LiquidCrystal_I2C.h>

// Replace with your network credentials
const char* ssid = "#######";
const char* password = "########";

// set the LCD number of columns and rows
int lcdColumns = 16;
int lcdRows = 2;


// set LCD address, number of columns and rows
// if you don't know your display address, run an I2C scanner sketch
LiquidCrystal_I2C lcd(0x27, lcdColumns, lcdRows);  

// Set LED GPIO
const int ledPin = 23;
// Stores LED state
String ledState;

// Create AsyncWebServer object on port 80
AsyncWebServer server(80);

// Replaces placeholder with LED state value
String processor(const String& var){
  Serial.println(var);
  if(var == "STATE"){
    if(digitalRead(ledPin)){
      ledState = "ON";
    }
    else{
      ledState = "OFF";
    }
    Serial.print(ledState);
    return ledState;
  }
  return String();
}
 
void setup(){

 // initialize LCD
  lcd.init();
  // turn on LCD backlight                      
  lcd.backlight();
  
  // Serial port for debugging purposes
  Serial.begin(115200);
  pinMode(ledPin, OUTPUT);

  // Initialize SPIFFS
  if(!SPIFFS.begin(true)){
    Serial.println("An Error has occurred while mounting SPIFFS");
    return;
  }

  // Connect to Wi-Fi
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connecting to WiFi..");
  } 

  // Print ESP32 Local IP Address
  Serial.println(WiFi.localIP());
  lcd.setCursor(0, 0);
  lcd.print("IP address is ");
  lcd.setCursor(0, 1);
  lcd.print(WiFi.localIP());
  // Route for root / web page
  server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(SPIFFS, "/index.html", String(), false, processor);
  });
  
  // Route to load style.css file
  server.on("/style.css", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(SPIFFS, "/style.css", "text/css");
  });

  // Route to set GPIO to HIGH
  server.on("/on", HTTP_GET, [](AsyncWebServerRequest *request){
    digitalWrite(ledPin, HIGH);    
    request->send(SPIFFS, "/index.html", String(), false, processor);
  });
  
  // Route to set GPIO to LOW
  server.on("/off", HTTP_GET, [](AsyncWebServerRequest *request){
    digitalWrite(ledPin, LOW);    
    request->send(SPIFFS, "/index.html", String(), false, processor);
  });

  // Start server
  server.begin();
}
 
void loop(){
  
}

index.html

HTML
<!DOCTYPE html>
<html>
<head>
  <title>Internet controlled LED using ESP32 based web server</title>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="icon" href="data:,">
  <link rel="stylesheet" type="text/css" href="style.css">
  <script type="text/javascript">
      document.addEventListener("DOMContentLoaded", function(event) {
      var button_text = "";
      button_text = document.getElementById("status").innerHTML;
      if (button_text == "ON") {
        document.getElementById("switch1").checked = true;
      }
      else if (button_text == "OFF") {
        document.getElementById("switch1").checked = false;
      } 
    });
</script>
  <script type="text/javascript">
    function fun1()
    {
      var text = document.getElementById("status").innerHTML;
      var chbox=document.getElementById("switch1");
      if (chbox.checked == true && text == "OFF")
      {
       window.location.pathname = '/on';
       chbox.checked = true;
    }
      else 
      {
        window.location.pathname = '/off';
        chbox.checked = false;
      }  
    }
</script>

</head>
<body >
  <h1>Internet controlled LED using ESP32 based web server <div id="status" style = "display: none;">%STATE%</div></h1>
  <span class="switch">
    <span class="switch-border1">
      <span class="switch-border2">
        <input id="switch1" type="checkbox" onclick="fun1()" />
        <label for="switch1"></label>
        <span class="switch-top"></span>
        <span class="switch-shadow"></span>
        <span class="switch-handle"></span>
        <span class="switch-handle-left"></span>
        <span class="switch-handle-right"></span>
        <span class="switch-handle-top"></span>
        <span class="switch-handle-bottom"></span>
        <span class="switch-handle-base"></span>
        <span class="switch-led switch-led-green">
          <span class="switch-led-border">
            <span class="switch-led-light">
              <span class="switch-led-glow"></span>
            </span>
          </span>
        </span>
        <span class="switch-led switch-led-red">
          <span class="switch-led-border">
            <span class="switch-led-light">
              <span class="switch-led-glow"></span>
            </span>
          </span>
        </span>
      </span>
    </span>
  </span>
  
</body>
</html>

style.css

CSS
body {
	font-family: arial, verdana, sans-serif;
	font-size: 8px;
	background: #1E1E20;
	text-align: center;
}

h1{
color: white;
font-size:30px;

}

.switch {
	display: inline-block;
	margin: 10em 2em;
	position: relative;
	border-radius: 3.5em;
	-webkit-box-shadow: 0 0 0.5em rgba(255,255,255,0.2);
	-moz-box-shadow: 0 0 0.5em rgba(255,255,255,0.2);
	box-shadow: 0 0 0.5em rgba(255,255,255,0.2);
}

.switch label {
	width: 100%;
	height: 100%;
	margin: 0;
	padding: 0;
	display: block;
	position: absolute;
	top: 0;
	left: 0;
	z-index: 10;
}

.switch input {
	display: none;
}

.switch span {
	display: block;
	-webkit-transition: top 0.2s;
	-moz-transition: top 0.2s;
	-ms-transition: top 0.2s;
	-o-transition: top 0.2s;
	transition: top 0.2s;
}

.switch-border1 {
	border: 0.1em solid #000;
	border-radius: 3.5em;
	-webkit-box-shadow: 0 0.2em rgba(255, 255, 255, 0.2);
	-moz-box-shadow: 0 0.2em rgba(255, 255, 255, 0.2);
	box-shadow: 0 0.2em rgba(255, 255, 255, 0.2);
}

.switch-border2 {
	width: 6.6em;
	height: 12.6em;
	position: relative;
	border: 0.1em solid #323232;
	background-image: -webkit-gradient(linear, left top, right top, from(#2D2D2D), color-stop(0.5, #4B4B4B), to(#2D2D2D));
	background-image: -webkit-linear-gradient(left, #2D2D2D, #4B4B4B, #2D2D2D);
	background-image: -moz-linear-gradient(left, #2D2D2D, #4B4B4B, #2D2D2D);
	background-image: -ms-linear-gradient(left, #2D2D2D, #4B4B4B, #2D2D2D);
	background-image: -o-linear-gradient(left, #2D2D2D, #4B4B4B, #2D2D2D);
	background-image: linear-gradient(to right, #2D2D2D, #4B4B4B, #2D2D2D);
	border-radius: 3.4em;
}

.switch-border2:before,
.switch-border2:after {
	content: '';
	display: block;
	width: 100%;
	height: 100%;
	position: absolute;
	top: 0;
	left: 0;
	z-index: 0;
	opacity: .3;
	border-radius: 3.4em;
}

.switch-border2:before {
	background: -webkit-gradient(linear, left top, left bottom, from(#000), to(rgba(0,0,0,0)));
	background: -webkit-linear-gradient(#000, rgba(0,0,0,0));
	background: -moz-linear-gradient(#000, rgba(0,0,0,0));
	background: -ms-linear-gradient(#000, rgba(0,0,0,0));
	background: -o-linear-gradient(#000, rgba(0,0,0,0));
	background: linear-gradient(#000, rgba(0,0,0,0));
}

.switch-border2:after {
	background: -webkit-gradient(linear, left top, left bottom, from(rgba(0,0,0,0)), to(#000));
	background: -webkit-linear-gradient(rgba(0,0,0,0), #000);
	background: -moz-linear-gradient(rgba(0,0,0,0), #000);
	background: -ms-linear-gradient(rgba(0,0,0,0), #000);
	background: -o-linear-gradient(rgba(0,0,0,0), #000);
	background: linear-gradient(rgba(0,0,0,0), #000);
}

.switch-top {
	width: 100%;
	height: 84%;
	position: absolute;
	top: 8%;
	left: 0;
	z-index: 1;
	background-image: -webkit-gradient(linear, left top, right top, from(#2D2D2D), color-stop(0.5, #4B4B4B), to(#2D2D2D));
	background-image: -webkit-linear-gradient(left, #2D2D2D, #4B4B4B, #2D2D2D);
	background-image: -moz-linear-gradient(left, #2D2D2D, #4B4B4B, #2D2D2D);
	background-image: -ms-linear-gradient(left, #2D2D2D, #4B4B4B, #2D2D2D);
	background-image: -o-linear-gradient(left, #2D2D2D, #4B4B4B, #2D2D2D);
	background-image: linear-gradient(to right, #2D2D2D, #4B4B4B, #2D2D2D);
	border-radius: 3.4em;
}

.switch-shadow {
	width: 100%;
	height: 100%;
	position: absolute;
	top: 0;
	left: 0;
	z-index: 2;
	border-radius: 3.4em;
	-webkit-box-shadow: 0 0 2em black inset;
	-moz-box-shadow: 0 0 2em black inset;
	box-shadow: 0 0 2em black inset;
}

.switch-handle-left,
.switch-handle-right {
	content: '';
	display: block;
	width: 3.6em;
	height: 0;
	position: absolute;
	top: 6.6em;
	z-index: 2;
	border-bottom: 4.5em solid #111;
	border-left: 0.7em solid transparent;
	border-right: 0.7em solid transparent;
	border-radius: 0;
}

.switch-handle-left {
	left: 0.8em;
}

.switch-handle-right {
	right: 0.8em;
}

.switch-handle {
	width: 3.6em;
	height: 4.5em;
	position: absolute;
	top: 6.6em;
	left: 1.5em;
	z-index: 3;
	background: #333;
	background-image: -webkit-gradient(linear, left top, right top, from(#111), color-stop(0.4, #777), color-stop(0.5, #888), color-stop(0.6, #777), to(#111));
	background-image: -webkit-linear-gradient(left, #111, #777 40%, #888, #777 60%, #111);
	background-image: -moz-linear-gradient(left, #111, #777 40%, #888, #777 60%, #111);
	background-image: -ms-linear-gradient(left, #111, #777 40%, #888, #777 60%, #111);
	background-image: -o-linear-gradient(left, #111, #777 40%, #888, #777 60%, #111);
	background-image: linear-gradient(to right, #111, #777 40%, #888, #777 60%, #111);
	border-radius: 0;
}

.switch-handle-top {
	width: 5em;
	height: 5em;
	position: absolute;
	top: 8.5em;
	left: 0.8em;
	z-index: 4;
	background-color: #555;
	background-image: -webkit-gradient(linear, left top, right top, from(#5F5F5F), to(#878787));
	background-image: -webkit-linear-gradient(left, #5F5F5F, #878787);
	background-image: -moz-linear-gradient(left, #5F5F5F, #878787);
	background-image: -ms-linear-gradient(left, #5F5F5F, #878787);
	background-image: -o-linear-gradient(left, #5F5F5F, #878787);
	background-image: linear-gradient(to right, #5F5F5F, #878787);
	border-top: 0.2em solid #AEB2B3;
	border-radius: 2.5em;
}

.switch-handle-bottom {
	width: 3.6em;
	height: 3.6em;
	position: absolute;
	top: 4.7em;
	left: 1.5em;
	z-index: 3;
	background: #333;
	background-image: -webkit-gradient(linear, left top, right top, from(#111), color-stop(0.4, #777), color-stop(0.5, #888), color-stop(0.6, #777), to(#111));
	background-image: -webkit-linear-gradient(left, #111, #777 40%, #888, #777 60%, #111);
	background-image: -moz-linear-gradient(left, #111, #777 40%, #888, #777 60%, #111);
	background-image: -ms-linear-gradient(left, #111, #777 40%, #888, #777 60%, #111);
	background-image: -o-linear-gradient(left, #111, #777 40%, #888, #777 60%, #111);
	background-image: linear-gradient(to right, #111, #777 40%, #888, #777 60%, #111);
	border-top: 0.2em solid #141414;
	border-radius: 1.8em;
}

.switch-handle-base {
	width: 4.2em;
	height: 4.2em;
	position: absolute;
	top: 3.8em;
	left: 1.2em;
	z-index: 2;
	border-top: 0.2em solid rgba(255,255,255,0.35);
	border-radius: 2.1em;
	-webkit-box-shadow: 0 0 0.5em rgba(0,0,0,0.8) inset;
	-moz-box-shadow: 0 0 0.5em rgba(0,0,0,0.8) inset;
	box-shadow: 0 0 0.5em rgba(0,0,0,0.8) inset;
}

.switch-led {
	position: absolute;
	left: 2em;
	border-radius: 1.4em;
}

.switch-led-border {
	border: 0.2em solid black;
	border-radius: 1.3em;
}

.switch-led-light {
	border-radius: 1.1em;
	-webkit-box-shadow: 0 0 0.5em rgba(255,255,255,0.5) inset;
	-moz-box-shadow: 0 0 0.5em rgba(255,255,255,0.5) inset;
	box-shadow: 0 0 0.5em rgba(255,255,255,0.5) inset;
}

.switch-led-glow {
	width: 2em;
	height: 2em;
	position: relative;
	border-radius: 1em;
}

.switch-led-glow:before {
	content: '';
	display: block;
	width: 0.6em;
	height: 0.6em;
	position: absolute;
	top: 0.3em;
	left: 0.7em;
	background: rgba(255,255,255,0.2);
	border-radius: 0.3em;
	-webkit-box-shadow: 0 0 1em rgba(255,255,255,0.75);
	-moz-box-shadow: 0 0 1em rgba(255,255,255,0.75);
	box-shadow: 0 0 1em rgba(255,255,255,0.75);
}

.switch-led-glow:after {
	content: '';
	display: block;
	width: 0;
	height: 0;
	position: absolute;
	top: 0;
	left: 0;
	opacity: 0.2;
	filter: alpha(opacity=20);
	border: 1em solid #fff;
	border-color: transparent #fff transparent #fff;
	border-radius: 1em;
	-webkit-transform: rotate(45deg);
	-moz-transform: rotate(45deg);
	-ms-transform: rotate(45deg);
	-o-transform: rotate(45deg);
	transform: rotate(45deg);
}

.switch-led:after {
	display: block;
	width: 100%;
	position: absolute;
	left: 0;
	color: #666;
	font-family: arial, verdana, sans-serif;
	font-weight: bold;
	text-align: center;
	text-shadow: 0 0.1em rgba(0,0,0,0.7);
}

.switch-led-green:after {
	content: 'ON';
	top: -1.8em;
}

.switch-led-red:after {
	content: 'OFF';
	bottom: -1.8em;
}

.switch-led-green {
	top: -5em;
	border-top: 0.1em solid rgba(0,161,75,0.5);
	border-bottom: 0.1em solid rgba(255,255,255,0.25);
}

.switch-led-green .switch-led-light {
	background: rgb(0,161,75);
	border: 0.1em solid rgb(0,104,56);
}

.switch-led-red {
	bottom: -5em;
	border-top: 0.1em solid rgba(237,28,36,0.2);
	border-bottom: 0.1em solid rgba(255,255,255,0.25);
	-webkit-box-shadow: 0 0 3em rgb(237,28,36);
	-moz-box-shadow: 0 0 3em rgb(237,28,36);
	box-shadow: 0 0 3em rgb(237,28,36);
}

.switch-led-red .switch-led-light {
	background: rgb(237,28,36);
	border: 0.1em solid rgb(161,30,45);
}

.switch-led-red .switch-led-glow {
	background: #fff;
	background: rgba(255, 255, 255, 0.3);
	filter: alpha(opacity=30);
}

/* Switch on */

.switch input:checked~.switch-handle-left, .switch input:checked~.switch-handle-right {
	top: 1.5em;
	border-bottom: 0;
	border-top: 4.5em solid #111;
}

.switch input:checked~.switch-handle {
	top: 1.5em;
}

.switch input:checked~.switch-handle-top  {
	top: -1em;
	border-top: 0;
	border-bottom: 0.2em solid #AEB2B3;
}

.switch input:checked~.switch-handle-bottom {
	top: 4.2em;
	border-top: 0;
	border-bottom: 0.2em solid #141414;
}

.switch input:checked~.switch-handle-base {
	top: 4.5em;
	border-top: 0;
	border-bottom: 0.2em solid rgba(255,255,255,0.35);
}

.switch input:checked~.switch-led-green {
	-webkit-box-shadow: 0 0 3em rgb(0,161,75);
	-moz-box-shadow: 0 0 3em rgb(0,161,75);
	box-shadow: 0 0 3em rgb(0,161,75);
}

.switch input:checked~.switch-led-green .switch-led-glow {
	background: #fff;
	background: rgba(255, 255, 255, 0.4);
	filter: alpha(opacity=40);
}

.switch input:checked~.switch-led-red {
	-webkit-box-shadow: none;
	-moz-box-shadow: none;
	box-shadow: none;
}

.switch input:checked~.switch-led-red .switch-led-glow {
	background: rgba(255, 255, 255, 0);
	filter: alpha(opacity=0);
}

Credits

Nurgaliyev Shakhizat

Nurgaliyev Shakhizat

70 projects • 168 followers
I am a hardcore robotics and IoT enthusiast. Email: shahizat005@gmail.com

Comments