스마트 디바이스 실습 14.1주차

ESP32를 웹서버로 구동하기

한세대학교 컴퓨터공학과 22학번 김선영


웹 서버란?

Responsive image

  1. Hyper Text Transfer Protocol 또는 간단히 HTTP는 클라이언트와 서버 간의 통신을 담당하는 프로토콜.
  2. 페이지의 정보는 HTML 문서, 이미지, 비디오, 응용 프로그램 등의 형식의 텍스트와 같은 모든 형식.[초보자를 위한 ESP32 프로젝트]
  3. 웹 클라이언트에 대해 말하자면, 노트북과 휴대폰의 웹 브라우저는 가장 간단한 유형의 웹 클라이언트 중 하나.
  4. 웹 서버와 웹 클라이언트 간의 통신은 종종 클라이언트-서버 통신 모델이라고 함.

웹-클라이언트-서버-모델

  1. Hyper Text Transfer Protocol 또는 간단히 HTTP는 클라이언트와 서버 간의 통신을 담당하는 프로토콜.
  2. 이러한 유형의 통신에서 웹 클라이언트는 HTTP를 사용하여 서버에서 정보를 요청.
  3. 항상 요청을 대기(수신)하는 웹 서버는 클라이언트의 요청에 적절한 웹 페이지로 응답.
  4. 요청한 페이지를 찾을 수 없으면 서버는 HTTP 404 오류로 응답.

ESP32의 Wi-Fi 작동 모드

ESP32에서 Wi-Fi의 작동 모드
  1. 스테이션 모드(STA)
  2. 소프트 액세스 포인트 모드(AP)
  3. 스테이션 + 소프트 AP 모드

스테이션 모드에서 ESP32 모듈은 휴대폰 및 노트북과 마찬가지로 무선 라우터에 의해 설정된 기존 WiFi 네트워크에 연결.

ESP32 Wi-Fi 모듈은 라우터의 SSID 및 암호를 사용하여 라우터의 Wi-Fi 네트워크에 연결하고 라우터는 ESP32용 로컬 IP 주소를 할당.

ESP32-STA-모드
Responsive image

  1. 액세스 포인트 모드로 전환하면 ESP32 모듈은 무선 라우터와 같은 자체 WiFi 네트워크를 생성


  2. 휴대폰, 노트북 및 기타 ESP32 모듈(STA 모드)과 같은 다른 스테이션이 해당 네트워크에 연결.


ESP32-AP 모드
Responsive image

  1. ESP32에는 유선 이더넷이 인터넷에 연결되어 있지 않기 때문에 이 AP 모드를 소프트 AP 모드라고 함.


  2. AP 모드에서 ESP32를 구성하는 동안 다른 장치가 해당 자격 증명을 사용하여 해당 네트워크에 연결할 수 있도록 네트워크의 SSID 및 비밀번호를 설정해야 함.


  3. 스테이션 + 소프트 AP는 스테이션 모드와 소프트 AP 모드의 조합.


  4. 여기에서 ESP32는 스테이션과 액세스 포인트의 역할을 모두 수행함.



실습 : DHT 센서에서 온도 및 습도를 읽고 웹 서버로 구축하기

순서
  1. ESPAsyncWebServer, AsyncTCP 라이브러리를 다운로드하여 비동기 웹 서버를 구축함.
  2. 압축 해제 후 Arduino 라이브러리에 붙여넣기 \Documents\Arduino\libraries
  3. 웹 페이지를 새로 고칠 필요 없이 자동으로 센서 판독값을 업데이트함.
구성도
Responsive image
Responsive image

DHT 연결

Responsive image

웹 서버 구동 성공!

코드

                            

    > 라이브러리 가져오기
    ```
    /*********
        Rui Santos
        Complete project details at https://randomnerdtutorials.com  
    *********/
    
    // Import required libraries
    #include "WiFi.h"
    #include "ESPAsyncWebServer.h"
    #include 
    #include 
    ```
    
    > 네트워크 자격 증명 설정
    ```
    // Replace with your network credentials
    const char* ssid = "REPLACE_WITH_YOUR_SSID";
    const char* password = "REPLACE_WITH_YOUR_PASSWORD";
    ```
    
    > 변수 정의
    ```
    #define DHTPIN 27     // ESP32의 27번 핀에 연결
    
    // Uncomment the type of sensor in use:
    #define DHTTYPE    DHT11     // DHT 11
    
    DHT dht(DHTPIN, DHTTYPE);
    
    // Create AsyncWebServer object on port 80
    AsyncWebServer server(80);
    ```
    
    > 온도 및 습도 함수 읽기
    ```
    String readDHTTemperature() {
        // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
        // Read temperature as Celsius (the default)
        float t = dht.readTemperature();
        // Read temperature as Fahrenheit (isFahrenheit = true)
        //float t = dht.readTemperature(true);
        // Check if any reads failed and exit early (to try again).
        if (isnan(t)) {    
        Serial.println("Failed to read from DHT sensor!");
        return "--";
        }
        else {
        Serial.println(t);
        return String(t);
        }
    }
    
    String readDHTHumidity() {
        // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
        float h = dht.readHumidity();
        if (isnan(h)) {
        Serial.println("Failed to read from DHT sensor!");
        return "--";
        }
        else {
        Serial.println(h);
        return String(h);
        }
    }
    
    const char index_html[] PROGMEM = R"rawliteral(
    ```
    
    > 웹 페이지 구축

<!DOCTYPE HTML>
    <head>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.2/css/all.css" integrity="sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr" crossorigin="anonymous">
    <style>
        html {
            font-family: Arial;
            display: inline-block;
            margin: 0px auto;
            text-align: center;
        }
        h2 { font-size: 3.0rem; }
        p { font-size: 3.0rem; }
        .units { font-size: 1.2rem; }
        .dht-labels{
            font-size: 1.5rem;
            vertical-align:middle;
            padding-bottom: 15px;
        }
    </style>
    </head>
    <body>
    <h2>ESP32 DHT Server</h2>
    <p>
    <i class="fas fa-thermometer-half" style="color:#059e8a;"></i> 
    <span class="dht-labels">Temperature</span> 
    <span id="temperature">%TEMPERATURE%</span>
    <sup class="units">°C</sup>
    </p>
    <p>
    <i class="fas fa-tint" style="color:#00add6;"></i> 
    <span class="dht-labels">Humidity</span>
    <span id="humidity">%HUMIDITY%</span>
    <sup class="units">%</sup>
    </p>
    </body>
    <script>
    setInterval(function ( ) {
        var xhttp = new XMLHttpRequest();
        xhttp.onreadystatechange = function() {
        if (this.readyState == 4 && this.status == 200) {
            document.getElementById("temperature").innerHTML = this.responseText;
        }
        };
        xhttp.open("GET", "/temperature", true);
        xhttp.send();
    }, 10000 ) ;
    
    setInterval(function ( ) {
        var xhttp = new XMLHttpRequest();
        xhttp.onreadystatechange = function() {
        if (this.readyState == 4 && this.status == 200) {
            document.getElementById("humidity").innerHTML = this.responseText;
        }
        };
        xhttp.open("GET", "/humidity", true);
        xhttp.send();
    }, 10000 ) ;
    </script>
    </html>)rawliteral";
    
    // Replaces placeholder with DHT values
    String processor(const String& var){
        //Serial.println(var);
        if(var == "TEMPERATURE"){
        return readDHTTemperature();
        }
        else if(var == "HUMIDITY"){
        return readDHTHumidity();
        }
        return String();
    }
    
    void setup(){
        // Serial port for debugging purposes
        Serial.begin(115200);
    
        dht.begin();
        
        // 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());
    
        // Route for root / web page
        server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
        request->send_P(200, "text/html", index_html, processor);
        });
        server.on("/temperature", HTTP_GET, [](AsyncWebServerRequest *request){
        request->send_P(200, "text/plain", readDHTTemperature().c_str());
        });
        server.on("/humidity", HTTP_GET, [](AsyncWebServerRequest *request){
        request->send_P(200, "text/plain", readDHTHumidity().c_str());
        });
    
        // Start server
        server.begin();
    }
        
    void loop(){
        
    }
                            

실습을 통해 느낀점

  1. 웹 서버와 웹 클라이언트 간의 관계와 통신 모델에 대해 배움.
  2. 웹 서버는 웹 페이지를 제공하고, 웹 클라이언트는 웹 서버에 정보를 요청하는 역할을 수행함을 알게 됨.
  3. ESP32는 Wi-Fi 연결을 위해 다양한 모드를 지원. STA 모드로 무선 라우터에 연결하거나, AP 모드로 ESP32 자체의 Wi-Fi 네트워크를 생성할 수 있음을 알게 됨.
  4. 또한 STA+AP 모드로 두 가지 모드를 동시에 사용할 수도 있음을 알게 됨. ESP32 웹 서버를 통해 센서 데이터를 실시간으로 모니터링할 수 있다는 점이 기억에 남음.

Previous   /   Next