06.01(14주차) Web Server - rlarlqor0513/smart-device GitHub Wiki
동기 서버 (Synchronous Server):
- 동기 서버는 클라이언트 요청을 순차적으로 처리합니다.
- 요청이 도착하면 해당 요청을 처리하는 동안 다른 요청은 차단됩니다.
- 요청에 대한 응답을 완료하기 전까지는 다음 요청을 처리할 수 없습니다.
- 간단하고 직관적인 코드 작성이 가능하며, 동기적인 특성으로 인해 로직의 순서와 흐름을 이해하기 쉽습니다.
- 단일 쓰레드나 제한된 쓰레드 풀을 사용하여 동작하므로, 동시에 처리할 수 있는 요청 수가 제한적일 수 있습니다.
- 입출력 작업이 많거나 처리 시간이 긴 작업이 있을 경우, 다른 요청들이 블록되어 성능 저하가 발생할 수 있습니다.
비동기 서버 (Asynchronous Server):
- 비동기 서버는 클라이언트 요청을 차단하지 않고 비동기적으로 처리합니다. 요청이 도착하면 해당 요청을 처리하는 동안 다른 요청을 계속해서 처리할 수 있습니다.
- 요청에 대한 응답을 기다리지 않고 다음 요청을 처리하기 때문에, 여러 요청을 동시에 처리할 수 있습니다.
- 비동기적인 특성으로 인해 비동기 코드의 작성이 복잡할 수 있으며, 로직의 순서와 흐름을 파악하기 어려울 수 있습니다.
- 다중 쓰레드 또는 이벤트 기반의 비동기 I/O 모델을 사용하여 동작하므로, 동시에 처리할 수 있는 요청 수가 많아집니다.
- 입출력 작업이 많거나 처리 시간이 긴 작업을 비동기적으로 처리할 수 있어서, 다른 작업을 블록하지 않고 성능을 향상시킬 수 있습니다.
https://github.com/me-no-dev/ESPAsyncWebServer
https://github.com/me-no-dev/AsyncTCP
위 깃허브에서 각각 코드를 다운로드 해주고 아두이노 라이브러리에 설치해준다.
#include <Wire.h>
#include "DHT.h"
#include <WiFi.h>
#include "ESPAsyncWebServer.h"
// Replace with your network credentials
const char* ssid = "Enter Your WiFi Name";
const char* password = "Enter your WiFi Password";
// Uncomment one of the lines below for whatever DHT sensor type you're using!
//#define DHTTYPE DHT11 // DHT 11
//#define DHTTYPE DHT21 // DHT 21 (AM2301)
#define DHTTYPE DHT22 // DHT 22 (AM2302), AM2321
//DHT Sensor;
uint8_t DHTPin = 4;
DHT dht(DHTPin, DHTTYPE);
float temperature_Celsius;
float temperature_Fahrenheit;
float Humidity;
AsyncWebServer server(80);
AsyncEventSource events("/events");
unsigned long lastTime = 0;
unsigned long timerDelay = 30000; // send readings timer
void getDHTReadings(){
Humidity = dht.readHumidity();
// Read temperature as Celsius (the default)
temperature_Celsius = dht.readTemperature();
// Read temperature as Fahrenheit (isFahrenheit = true)
temperature_Fahrenheit= dht.readTemperature(true);
}
String processor(const String& var){
getDHTReadings();
//Serial.println(var);
if(var == "TEMPERATURE_C"){
return String(temperature_Celsius);
}
else if(var == "TEMPERATURE_F"){
return String(temperature_Fahrenheit);
}
else if(var == "HUMIDITY"){
return String(Humidity);
}
}
const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML><html>
<head>
<title>DHT Web Server</title>
<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">
<link rel="icon" href="data:,">
<style>
html {font-family: Arial; display: inline-block; text-align: center;}
p { font-size: 1.2rem;}
body { margin: 0;}
.topnav { overflow: hidden; background-color: #4B1D3F; color: white; font-size: 1.7rem; }
.content { padding: 20px; }
.card { background-color: white; box-shadow: 2px 2px 12px 1px rgba(140,140,140,.5); }
.cards { max-width: 700px; margin: 0 auto; display: grid; grid-gap: 2rem; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); }
.reading { font-size: 2.8rem; }
.card.temperature { color: #0e7c7b; }
.card.humidity { color: #17bebb; }
</style>
</head>
<body>
<div class="topnav">
<h3>DHT WEB SERVER</h3>
</div>
<div class="content">
<div class="cards">
<div class="card temperature">
<h4><i class="fas fa-thermometer-half"></i> TEMPERATURE</h4><p><span class="reading"><span id="temp_celcius">%TEMPERATURE_C%</span> °C</span></p>
</div>
<div class="card temperature">
<h4><i class="fas fa-thermometer-half"></i> TEMPERATURE</h4><p><span class="reading"><span id="temp_fahrenheit">%TEMPERATURE_F%</span> °F</span></p>
</div>
<div class="card humidity">
<h4><i class="fas fa-tint"></i> HUMIDITY</h4><p><span class="reading"><span id="hum">%HUMIDITY%</span> %</span></p>
</div>
</div>
</div>
<script>
if (!!window.EventSource) {
var source = new EventSource('/events');
source.addEventListener('open', function(e) {
console.log("Events Connected");
}, false);
source.addEventListener('error', function(e) {
if (e.target.readyState != EventSource.OPEN) {
console.log("Events Disconnected");
}
}, false);
source.addEventListener('message', function(e) {
console.log("message", e.data);
}, false);
source.addEventListener('temperature_Celsius', function(e) {
console.log("temperature", e.data);
document.getElementById("temp_celcius").innerHTML = e.data;
}, false);
source.addEventListener('temperature_Fahrenheit', function(e) {
console.log("temperature", e.data);
document.getElementById("temp_fahrenheit").innerHTML = e.data;
}, false);
source.addEventListener('humidity', function(e) {
console.log("humidity", e.data);
document.getElementById("hum").innerHTML = e.data;
}, false);
}
</script>
</body>
</html>)rawliteral";
void setup() {
Serial.begin(115200);
pinMode(DHTPin, INPUT);
dht.begin();
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Setting as a Wi-Fi Station..");
}
Serial.print("Station IP Address: ");
Serial.println(WiFi.localIP());
Serial.println();
// Handle Web Server
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/html", index_html, processor);
});
// Handle Web Server Events
events.onConnect([](AsyncEventSourceClient *client){
if(client->lastId()){
Serial.printf("Client reconnected! Last message ID that it got is: %u\n", client->lastId());
}
// send event with message "hello!", id current millis
// and set reconnect delay to 1 second
client->send("hello!", NULL, millis(), 10000);
});
server.addHandler(&events);
server.begin();
}
void loop() {
if ((millis() - lastTime) > timerDelay) {
getDHTReadings();
Serial.printf("Temperature = %.2f ºC \n", temperature_Celsius);
Serial.printf("Temperature = %.2f ºF \n", temperature_Fahrenheit);
Serial.printf("Humidity= %f %\n", Humidity);
Serial.println();
// Send Events to the Web Server with the Sensor Readings
events.send("ping",NULL,millis());
events.send(String(temperature_Celsius).c_str(),"temperature_Celsius",millis());
events.send(String(temperature_Fahrenheit).c_str(),"temperature_Fahrenheit",millis());
events.send(String(Humidity).c_str(),"humidity",millis());
lastTime = millis();
}
}
시리얼 모니터에서 IP 확인 후 접속