← Back to list

IoT Project VII : Web Server

Semangat Pagi! — Pagi, Pagi, Pagi! Kembali lagi ke percobaan selanjutnya, yaitu pembuatan web server. Ketika mendengar istilah web server…

Samuel Simanjuntak · 2025-05-03 15:08 · 0 claps · 11.4 min read
#esp32 #web-server #esp32-tutorial #esp32-programming #web-server-monitoring
Open on Medium ↗
Wiki topics: 💻 · Programming 📟 · Gadgets & IoT 🖊️ · Illustration & Drawing

IoT Project VII : Web Server

Semangat Pagi! — Pagi, Pagi, Pagi! Kembali lagi ke percobaan selanjutnya, yaitu pembuatan web server. Ketika mendengar istilah web server, pasti yang muncul di benak kita adalah sesuatu yang kompleks, infrastrukturnya rumit, tidak praktis, ataupun butuh resource yang banyak. Kenyataannya adalah ESP23 pun bisa menjadi web server karena dia sudah dilengkapi dengan Wi-Fi built in dan mendukung berbagai library di Arduino IDE. Tanpa berlama-lama, MARKICOB!!

PERKENALAN

Untuk membuktikan ESP32 bisa menjadi web server, kita akan menggunakan kode program yang akan di-upload melalui Arduino IDE. Web server ini dapat digunakan untuk mengontrol perangkat, menampilkan data sensor, atau membuat antarmuka atau interface sederhana yang bisa diakses pengguna melalui browser. Dengan ESP32 menjadi web server, terdapat beberapa keuntungan:

  1. Wi-Fi built-in memungkinkan ESP32 bertindak sebagai Station (STA)
  2. Menangani beberapa client atau request HTTP dalam waktu bersamaan, artinya website bisa diakses oleh beberapa device dalam kurun waktu yang sama
  3. Mendukung protokol HTTP

ESP32 Web Server Concept

ESP32 Web Server Concept

ALAT & BAHAN

  1. ESP32
  2. Arduino IDE
  3. LED 5mm — jumlah disesuaikan
  4. Resistor +- 330 Ohm — jumlah disesuaikan dengan LED yang digunakan
  5. Kabel jumper — male-to-male sudah cukup
  6. Device lain, seperti handphone

WIRING DIAGRAM

Seperti biasa, biasakan membuat wiring diagram agar percobaan kita berjalan lancar dan efisien. Berikut wiring diagram-nya:

Wiring Diagram

Wiring Diagram

Implementation of Wiring Diagram

Implementation of Wiring Diagram

KODE PROGRAM

Untuk kode program yang digunakan, saya mengacu ke website *randomnerdtutorials*, sebagai berikut:

/*********
  Rui Santos
  Complete project details at https://randomnerdtutorials.com  
*********/

// Load Wi-Fi library
#include <WiFi.h>

// Replace with your network credentials
const char* ssid = "KOZI 2.0 TENGAH - 2G";
const char* password = "negaraKORUPSI";

// Set web server port number to 80
WiFiServer server(80);

// Variable to store the HTTP request
String header;

// Auxiliar variables to store the current output state
String output26State = "off";
String output27State = "off";

// Assign output variables to GPIO pins
const int output26 = 26;
const int output27 = 27;

// Current time
unsigned long currentTime = millis();
// Previous time
unsigned long previousTime = 0; 
// Define timeout time in milliseconds (example: 2000ms = 2s)
const long timeoutTime = 2000;

void setup() {
  Serial.begin(115200);
  // Initialize the output variables as outputs
  pinMode(output26, OUTPUT);
  pinMode(output27, OUTPUT);
  // Set outputs to LOW
  digitalWrite(output26, LOW);
  digitalWrite(output27, LOW);

  // Connect to Wi-Fi network with SSID and password
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  // Print local IP address and start web server
  Serial.println("");
  Serial.println("WiFi connected.");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
  server.begin();
}

void loop(){
  WiFiClient client = server.available();   // Listen for incoming clients

  if (client) {                             // If a new client connects,
    currentTime = millis();
    previousTime = currentTime;
    Serial.println("New Client.");          // print a message out in the serial port
    String currentLine = "";                // make a String to hold incoming data from the client
    while (client.connected() && currentTime - previousTime <= timeoutTime) {  // loop while the client's connected
      currentTime = millis();
      if (client.available()) {             // if there's bytes to read from the client,
        char c = client.read();             // read a byte, then
        Serial.write(c);                    // print it out the serial monitor
        header += c;
        if (c == '\n') {                    // if the byte is a newline character
          // if the current line is blank, you got two newline characters in a row.
          // that's the end of the client HTTP request, so send a response:
          if (currentLine.length() == 0) {
            // HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
            // and a content-type so the client knows what's coming, then a blank line:
            client.println("HTTP/1.1 200 OK");
            client.println("Content-type:text/html");
            client.println("Connection: close");
            client.println();

            // turns the GPIOs on and off
            if (header.indexOf("GET /26/on") >= 0) {
              Serial.println("GPIO 26 on");
              output26State = "on";
              digitalWrite(output26, HIGH);
            } else if (header.indexOf("GET /26/off") >= 0) {
              Serial.println("GPIO 26 off");
              output26State = "off";
              digitalWrite(output26, LOW);
            } else if (header.indexOf("GET /27/on") >= 0) {
              Serial.println("GPIO 27 on");
              output27State = "on";
              digitalWrite(output27, HIGH);
            } else if (header.indexOf("GET /27/off") >= 0) {
              Serial.println("GPIO 27 off");
              output27State = "off";
              digitalWrite(output27, LOW);
            }

            // Display the HTML web page
            client.println("<!DOCTYPE html><html>");
            client.println("<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">");
            client.println("<link rel=\"icon\" href=\"data:,\">");
            // CSS to style the on/off buttons 
            // Feel free to change the background-color and font-size attributes to fit your preferences
            client.println("<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}");
            client.println(".button { background-color: #4CAF50; border: none; color: white; padding: 16px 40px;");
            client.println("text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer;}");
            client.println(".button2 {background-color: #555555;}</style></head>");

            // Web Page Heading
            client.println("<body><h1>ESP32 Web Server</h1>");

            // Display current state, and ON/OFF buttons for GPIO 26  
            client.println("<p>GPIO 26 - State " + output26State + "</p>");
            // If the output26State is off, it displays the ON button       
            if (output26State=="off") {
              client.println("<p><a href=\"/26/on\"><button class=\"button\">ON</button></a></p>");
            } else {
              client.println("<p><a href=\"/26/off\"><button class=\"button button2\">OFF</button></a></p>");
            } 

            // Display current state, and ON/OFF buttons for GPIO 27  
            client.println("<p>GPIO 27 - State " + output27State + "</p>");
            // If the output27State is off, it displays the ON button       
            if (output27State=="off") {
              client.println("<p><a href=\"/27/on\"><button class=\"button\">ON</button></a></p>");
            } else {
              client.println("<p><a href=\"/27/off\"><button class=\"button button2\">OFF</button></a></p>");
            }
            client.println("</body></html>");

            // The HTTP response ends with another blank line
            client.println();
            // Break out of the while loop
            break;
          } else { // if you got a newline, then clear currentLine
            currentLine = "";
          }
        } else if (c != '\r') {  // if you got anything else but a carriage return character,
          currentLine += c;      // add it to the end of the currentLine
        }
      }
    }
    // Clear the header variable
    header = "";
    // Close the connection
    client.stop();
    Serial.println("Client disconnected.");
    Serial.println("");
  }
}

Pada bagian network credential,

// Replace with your network credentials
const char* ssid = "KOZI 2.0 TENGAH - 2G";
const char* password = "negaraKORUPSI";
  • SSID digantikan dengan Wi-Fi yang ingin digunakan
  • Password digantikan dengan kata sandi yang digunakan untuk konektivitas Wi-Fi yang digunakan

ALUR KERJA PROGRAM

Secara sederhana, kode program ini memanfaatkan library Wifi untuk konektivitas ESP32 sebagai web server sehingga membutuhkan SSID dan password yang digunakan. Selain itu, port HTTP yang digunakan adalah 80.

// Set web server port number to 80
WiFiServer server(80);

Selanjutnya, kita harus melakukan inisialisasi variabel untuk header dari HTTP request dan variabel lain untuk menyimpan status dari output dimana nilai awalnya adalah “off”.

// Variable to store the HTTP request
String header;

// Auxiliar variables to store the current output state
String output26State = "off";
String output27State = "off";

Output26 dan Output27 mengacu ke GPIO port yang digunakan, dimana harus diinisialisasikan juga di awal.

// Assign output variables to GPIO pins
const int output26 = 26;
const int output27 = 27;

Pada bagian Setup(), kita akan menggunakan Serial Monitor pada baud-rate 115200 untuk melakukan debugging (Contoh: Apabila ESP32 gagal melakukan koneksi Wifi) dan juga memberikan local IP Address untuk membuka website. Selanjutnya, kita harus mendefinisikan port GPIO sebagai output dan set status awalnya sebagai LOW.

Serial.begin(115200);
  // Initialize the output variables as outputs
  pinMode(output26, OUTPUT);
  pinMode(output27, OUTPUT);
  // Set outputs to LOW
  digitalWrite(output26, LOW);
  digitalWrite(output27, LOW);

Berikut contoh debugging-nya:

// Connect to Wi-Fi network with SSID and password
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  // Print local IP address and start web server
  Serial.println("");
  Serial.println("WiFi connected.");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
  server.begin();

Pada proses loop(), ESP32 sebagai web server selalu menunggu adanya requestHTTP dari klien melalui:

  WiFiClient client = server.available();   // Listen for incoming clients

Ketika menerima requestHTTP dari klien, kode akan menerima data yang masuk dan diproses untuk memberikan output yang sesuai melalui kode:

  if (client) {                             // If a new client connects,
    currentTime = millis();
    previousTime = currentTime;
    Serial.println("New Client.");          // print a message out in the serial port
    String currentLine = "";                // make a String to hold incoming data from the client
    while (client.connected() && currentTime - previousTime <= timeoutTime) {  // loop while the client's connected
      currentTime = millis();
      if (client.available()) {             // if there's bytes to read from the client,
        char c = client.read();             // read a byte, then
        Serial.write(c);                    // print it out the serial monitor
        header += c;
        if (c == '\n') {                    // if the byte is a newline character
          // if the current line is blank, you got two newline characters in a row.
          // that's the end of the client HTTP request, so send a response:
          if (currentLine.length() == 0) {
            // HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
            // and a content-type so the client knows what's coming, then a blank line:
            client.println("HTTP/1.1 200 OK");
            client.println("Content-type:text/html");
            client.println("Connection: close");
            client.println();

Selanjutnya, kode akan memproses input dari klien berupa tombol apa yang dipencet pada website dan memberikan output yang diinginkan, seperti menghidupkan atau mematikan lampu LED dan memberikan status terkini dari LED yang sama melalui kode:

            // turns the GPIOs on and off
            if (header.indexOf("GET /26/on") >= 0) {
              Serial.println("GPIO 26 on");
              output26State = "on";
              digitalWrite(output26, HIGH);
            } else if (header.indexOf("GET /26/off") >= 0) {
              Serial.println("GPIO 26 off");
              output26State = "off";
              digitalWrite(output26, LOW);
            } else if (header.indexOf("GET /27/on") >= 0) {
              Serial.println("GPIO 27 on");
              output27State = "on";
              digitalWrite(output27, HIGH);
            } else if (header.indexOf("GET /27/off") >= 0) {
              Serial.println("GPIO 27 off");
              output27State = "off";
              digitalWrite(output27, LOW);

Untuk pembuatan interface bagi pengguna, kita harus membuat web page yang menggunakan HTML melalui kode program, yaitu:

                       // Display the HTML web page
            client.println("<!DOCTYPE html><html>");
            client.println("<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">");
            client.println("<link rel=\"icon\" href=\"data:,\">");
            // CSS to style the on/off buttons 
            // Feel free to change the background-color and font-size attributes to fit your preferences
            client.println("<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}");
            client.println(".button { background-color: #4CAF50; border: none; color: white; padding: 16px 40px;");
            client.println("text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer;}");
            client.println(".button2 {background-color: #555555;}</style></head>");

            // Web Page Heading
            client.println("<body><h1>ESP32 Web Server</h1>");

            // Display current state, and ON/OFF buttons for GPIO 26  
            client.println("<p>GPIO 26 - State " + output26State + "</p>");
            // If the output26State is off, it displays the ON button       
            if (output26State=="off") {
              client.println("<p><a href=\"/26/on\"><button class=\"button\">ON</button></a></p>");
            } else {
              client.println("<p><a href=\"/26/off\"><button class=\"button button2\">OFF</button></a></p>");
            } 

            // Display current state, and ON/OFF buttons for GPIO 27  
            client.println("<p>GPIO 27 - State " + output27State + "</p>");
            // If the output27State is off, it displays the ON button       
            if (output27State=="off") {
              client.println("<p><a href=\"/27/on\"><button class=\"button\">ON</button></a></p>");
            } else {
              client.println("<p><a href=\"/27/off\"><button class=\"button button2\">OFF</button></a></p>");
            }
            client.println("</body></html>");

            // The HTTP response ends with another blank line
            client.println();
            // Break out of the while loop
            break;
          } else { // if you got a newline, then clear currentLine
            currentLine = "";
          }
        } else if (c != '\r') {  // if you got anything else but a carriage return character,
          currentLine += c;      // add it to the end of the currentLine
        }
      }
    }

Ketika respon sudah selesai, variabel header dikosongkan dan koneksi klien akan di-stop dengan kode:

    // Clear the header variable
    header = "";
    // Close the connection
    client.stop();
    Serial.println("Client disconnected.");
    Serial.println("");

DEMONSTRASI

Both LED Works!

Both LED Works!

Dapat dilihat bahwa setiap LED berhasil dikontrol melalui website yang disediakan oleh ESP32 sebagai web server. Website telah dicoba untuk diakses melalui laptop dan handphone, keduanya berhasil untuk mendapatkan kontrol ke semua LED.

MENAMPILKAN HASIL SENSOR MELALUI WEB SERVER

Dengan struktur kode program yang hampir sama, kita bisa menggunakan sebuah sensor eksternal, seperti BME280, BMP280, MPU6050, dll untuk ditampilkan di website melalui ESP32 sebagai web server-nya. Rencana awal yang ingin dilakukan adalah membuat sebuah mini weather system dengan memanfaatkan sensor BME280 yang bisa membaca temperatur, kelembapan, dan tekanan. Akan tetapi, sensor yang saya miliki mengalami kerusakan karena hasil solder yang buruk — rookie mistake! — sehingga saya harus menggunakan sensor lain, yaitu MPU6050.

Digital Dashboad

Sensor MPU6050 bisa melacak percepatan dan kecepatan sudut dari suatu objek — penjelasan lebih detail cek **IoT Project III : Penggunaan Sensor Built-In dan Eksternal pada ESP32 — *sehingga bisa dimanfaatkan untuk menampilkan orientasi dari objek tersebut secara real-time melalui website. Hal ini bisa disebut juga sebuah digital dashboard yang bisa digunakan pada drone, RC, robot*, atau komponen bergerak lainnya. Dengan begitu, kita bisa mengetahui posisi atau orientasi dari objek dan mendapatkan kontrol untuk menggerakkannya.

ALAT & BAHAN

  1. ESP32
  2. Arduino IDE
  3. Sensor MPU6050
  4. Kabel jumper — male-to-male sudah cukup
  5. Device lain, seperti handphone

WIRING DIAGRAM

Seperti biasa, kita harus membuat wiring diagram terlebh dahulu agar percobaan berjalan dengan lancar dan lebih efisien. Pada dasarnya, wiring diagram ini mirip dengan percobaan sebelumnya untuk menyambungkan sensor eksternal ke ESP32. Pastikan SCL ke *port GPIO 22* dan SDA ke **port GPIO 21!

Wiring Diagram

Wiring Diagram

Berikut adalah kode programnya:

#include <WiFi.h>
#include <Wire.h>
#include <Adafruit_MPU6050.h>
#include <Adafruit_Sensor.h>

Adafruit_MPU6050 mpu;

// Ganti dengan SSID dan password WiFi kamu
const char* ssid = "Gdc-v9-7_EXT";
const char* password = "12345678";

WiFiServer server(80);

String header;

unsigned long currentTime = millis();
unsigned long previousTime = 0;
const long timeoutTime = 2000;

void setup() {
  Serial.begin(115200);
  while (!Serial);

  if (!mpu.begin()) {
    Serial.println("MPU6050 tidak terdeteksi!");
    while (1) delay(10);
  }

  Serial.println("MPU6050 berhasil terhubung!");

  WiFi.begin(ssid, password);
  Serial.print("Menghubungkan ke WiFi");
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("\nWiFi terhubung!");
  Serial.println("Alamat IP: ");
  Serial.println(WiFi.localIP());

  server.begin();
}

void loop() {
  WiFiClient client = server.available();

  if (client) {
    currentTime = millis();
    previousTime = currentTime;
    String currentLine = "";
    Serial.println("Client baru terkoneksi.");

    while (client.connected() && currentTime - previousTime <= timeoutTime) {
      currentTime = millis();
      if (client.available()) {
        char c = client.read();
        header += c;

        if (c == '\n') {
          if (currentLine.length() == 0) {
            sensors_event_t a, g, temp;
            mpu.getEvent(&a, &g, &temp);

            // Header HTTP
            client.println("HTTP/1.1 200 OK");
            client.println("Content-type:text/html");
            client.println("Connection: close");
            client.println();

            // Halaman HTML
            client.println("<!DOCTYPE html><html><head><meta charset='UTF-8'>");
            client.println("<title>ESP32 MPU6050</title>");
            client.println("<style>body{font-family:Arial;text-align:center;}</style></head><body>");
            client.println("<h1>MPU6050 Sensor Readings</h1>");
            client.println("<p><strong>Temperature:</strong> " + String(temp.temperature) + " &deg;C</p>");
            client.println("<p><strong>Accel X:</strong> " + String(a.acceleration.x) + " m/s²</p>");
            client.println("<p><strong>Accel Y:</strong> " + String(a.acceleration.y) + " m/s²</p>");
            client.println("<p><strong>Accel Z:</strong> " + String(a.acceleration.z) + " m/s²</p>");
            client.println("<p><strong>Gyro X:</strong> " + String(g.gyro.x) + " rad/s</p>");
            client.println("<p><strong>Gyro Y:</strong> " + String(g.gyro.y) + " rad/s</p>");
            client.println("<p><strong>Gyro Z:</strong> " + String(g.gyro.z) + " rad/s</p>");
            client.println("</body></html>");

            break;
          } else {
            currentLine = "";
          }
        } else if (c != '\r') {
          currentLine += c;
        }
      }
    }

    header = "";
    client.stop();
    Serial.println("Client terputus.\n");
  }
}

Pada dasarnya, kode program mirip dengan percobaan sebelumnya. Kode program ini akan dmemanfaatkan library Wifi untuk konektivitas ESP32 sebagai web server sehingga membutuhkan SSID dan password yang digunakan. Pada bagian Setup(), kita akan menggunakan Serial Monitor pada baud-rate 115200 untuk melakukan debugging (Contoh: Apabila ESP32 gagal melakukan koneksi Wifi) dan juga memberikan local IP Address untuk membuka website. Setelah itu, hasil pembacaan dari sensor akan ditampilkan dengan format HTML yang diinginkan, termasuk CSS apabila membutuhkan visual yang lebih jelas dan user-friendly.

DEMONSTRASI

Digital Dashboard Works!

Digital Dashboard Works!

Dapat dilihat bahwa hasil pembacaan sensor ditampilkan di website secara real-time setiap kali website di-refresh. Dengan demikian, kita bisa meletakkan sensor ini di suatu objek dan kita bisa mengetahui state atau orientasi dari objek tersebut.

APAKAH KLIEN HARUS MENGGUNAKAN WIFI YANG SAMA DENGAN ESP32 UNTUK MENGAKSES WEBSITE?

Tentu saja tidak, tergantung dari konfigurasi yang terdapat di dalam kode program. Akan tetapi, untuk kode program yang kita gunakan mengharuskan client melakukan koneksi ke Wi-Fi yang sama dengan ESP32. Mengapa demikian?

  • Ketika ESP32 terhubung ke jaringan Wi-Fi, router memberikan alamat IP lokal kepada ESP32, seperti 192.168.1.1XX.
  • Alamat IP ini hanya valid di dalam jaringan lokal (LAN) yang dikelola oleh router.
  • Perangkat klienharus berada di jaringan yang sama untuk dapat mengakses web server melalui alamat IP tersebut.
  • Dalam kode yang kita gunakan, ESP32 menjalankan:
WiFiServer server(80)

Artinya ini dalam Station Mode, yang mendengarkan request HTTP pada alamat IP lokalnya.

KESIMPULAN

Kita telah berhasil memanfaatkan ESP32 sebagai web server, dimana ini akan digunakan lebih lanjut untuk menampilkan website yang bisa digunakan sebagai kontrol jarak jauh, ataupun menyediakan interface yang bisa menampilkan hasil pembacaan parameter tertentu melalui sensor eksternal. Melalui percobaan ini, kita telah memahami konsep ESP32 membuat web server menggunakan jaringan WiFi lokal sehingga cocok untuk skala kecil. Oleh karena itu, kita sudah mengerti pengimplementasian dari ESP32 sebagai web server dan bisa dikembangkan menjadi projek yang lebih besar canggih!

PENUTUP

Untuk troubleshooting, bisa membuka website:

Terima Kasih! Semoga bermanfaat yaa..

Jangan lupa bahagia~~


메타데이터
post_id
cba0da0f0b28
slug
iot-project-vii-web-server-cba0da0f0b28
url
https://medium.com/@samuelchrismichael16/iot-project-vii-web-server-cba0da0f0b28
canonical_url
https://medium.com/@samuelchrismichael16/iot-project-vii-web-server-cba0da0f0b28
author_url
https://medium.com/@samuelchrismichael16
status
ok
fetched_at
2026-08-28 07:53:33