06주차 ‐ ESP32 Web Server 실습 - gitjs523/SmartDevice2025 GitHub Wiki

1. ESP32 Wi-Fi 모드

ESP32는 강력한 Wi-Fi 기능을 내장하여 무선 네트워크에 연결하거나 자체적으로 Wi-Fi 네트워크를 생성하여 웹서버 기능을 구현할 수 있다. STA 모드(Station 모드)와 AP 모드(Access Point 모드) 두 가지가 있다.

(1) STA 모드 (Station 모드)

개념과 특징

  • ESP32가 Wi-Fi 클라이언트(사용자 기기)로 동작함
  • 집이나 회사에 기존에 있던 Wi-Fi 공유기에 연결됨
  • 연결된 상태에서 인터넷 사용 및 다른 장치들과 네트워크 내 통신 가능
  • 로컬 IP 주소를 공유기로부터 할당받음
  • 인터넷과 연결된 웹서버 구축 시 주로 사용
  • 활용 예: 웹서버, 클라우드 연결

(2) AP 모드 (Access Point 모드)

개념과 특징

  • ESP32가 Wi-Fi 공유기 역할을 수행
  • 스마트폰, 태블릿 등 ESP32가 아닌 다른 기기가 ESP32에 직접 연결
  • 인터넷 없이 작동 가능 (로컬 통신 전용), Wi-Fi 없는 외부 환경에서 ESP32 직접 제어 가능
  • SSID 및 비밀번호 사용자가 직접 설정 가능
  • 연결된 장치는 ESP32에서 제공하는 웹 페이지 및 서비스에 접근 가능
  • 활용 예: 로컬 제어, 오프라인 제어

(3) STA + AP 동시 모드 (혼합 모드)

  • ESP32는 STA + AP 모드 동시 지원이 가능
  • 다른 Wi-Fi에 연결되면서도 자체 네트워크를 열 수 있음
  • ESP32를 중간 다리 역할로 활용할 때 유용함

2. ESP32 웹서버 실습

  • 웹서버는 클라이언트(브라우저)의 요청을 받아 웹페이지를 제공하는 역할을 수행
  • ESP32는 간단한 웹서버를 구동해 다양한 센서 정보 제공 및 제어가 가능

(1) 간단한 웹서버 구축 실습

  • 실습 전 주의사항
    • 스마트폰의 핫스팟을 이용하여 ESP32를 AP에 연결하고 동시에 같은 스마트폰의 브라우저로 ESP32 웹서버에 접속은 안될 수 있다.
    • 노트북, ESP32를 스마트폰으로 실행한 동일한 핫스팟에 연결한다.

사용한 코드

#include <WiFi.h>
#include <WebServer.h>

const char* ssid = "YourSSID";
const char* password = "YourPassword";

WiFiServer server(80);

void setup() {
  Serial.begin(115200);
  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connecting...");
  }

  Serial.println(WiFi.localIP());
  server.begin();
}

void loop() {
  WiFiClient client = server.available();
  if (client) {
    client.println("Hello from ESP32!");
    delay(10);
    client.stop();
  }
}

image

image

(2) 내장 LED를 제어하는 웹서버 실습

  • HTML 파일에 %STATE%, %BUTTON%을 사용해 LED 상태 실시간 표시
  • 상태에 따라 버튼과 텍스트 자동 갱신

사용한 코드

#include <WiFi.h>
#include <AsyncTCP.h>
#include <ESPAsyncWebServer.h>

const char* ssid = "YourSSID";
const char* password = "YourPassword";

String output2State = "off";

const int output2 = 2;

AsyncWebServer server(80);

const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="icon" href="data:,">
  <style>
    html { font-family: Helvetica; display: inline-block; 
            margin: 0px auto; text-align: center; }
    .button { background-color: #4CAF50; border: none; 
              color: white; padding: 16px 40px; text-decoration: none; 
              font-size: 30px; margin: 2px; cursor: pointer; }
    .button2 { background-color: #555555; }
  </style>
</head>
<body>
  <h1>ESP32 웹 서버</h1>
  <p>GPIO 2 - 상태 %STATE%</p>
  %BUTTON%
</body>
</html>
)rawliteral";

String processor(const String& var){
  if(var == "STATE")
  {
    return output2State;
  }
  if(var == "BUTTON"){
    String buttons = "";
    
    if (output2State == "off")
    {
      buttons += "<p><a href=\"/2/on\"> \
                  <button class=\"button\">ON</button></a></p>";
    }
    else
    {
      buttons += "<p><a href=\"/2/off\"> \
                  <button class=\"button button2\">OFF</button></a></p>";
    }
    return buttons;
  }
  return String();
}

void setup(){
  Serial.begin(115200);
  delay(3000);

  pinMode(output2, OUTPUT);
  digitalWrite(output2, LOW);
  
  Serial.print("연결 중: ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("Wi-Fi 연결됨.");
  Serial.println("IP 주소: ");
  Serial.println(WiFi.localIP());
  
  server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send_P(200, "text/html", index_html, processor);
  });

  server.on("/2/on", HTTP_GET, [] (AsyncWebServerRequest *request) {
    Serial.println("GPIO 2 ON");
    output2State = "on";
    digitalWrite(output2, HIGH);
    request->send_P(200, "text/html", index_html, processor);
  });

  server.on("/2/off", HTTP_GET, [] (AsyncWebServerRequest *request) {
    Serial.println("GPIO 2 OFF");
    output2State = "off";
    digitalWrite(output2, LOW);
    request->send_P(200, "text/html", index_html, processor);
  });
  
  server.begin();
}

void loop() {

}
20250413_234424.mp4
⚠️ **GitHub.com Fallback** ⚠️