#include <Arduino.h>
#include <WiFi.h>
#include <AsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include <Adafruit_Sensor.h>
#include <DHT.h>

const char *ssid = "XXXXXX";        //设置WiFi账号 Set up WiFi account
const char *password = "XXXXXXXX";  //设置WiFi密码 Set WiFi password

#define DHTPIN 19          // 19引脚连接到DHT传感器  The 19 pins are connected to the DHT sensor
#define DHTTYPE DHT11      // 定义传感器类型为DHT11  The sensor type is defined as DHT11
DHT dht(DHTPIN, DHTTYPE);  // 创建一个DHT对象，使用指定的引脚和传感器类型  Creates a DHT object with the specified pin and sensor types
// 创建 AsyncWebServer 对象
AsyncWebServer server(80);

float t = 0.0;  // 定义一个浮点型变量t，用于存储温度值  Define a floating-point variable t to store the temperature
float h = 0.0;  // 定义一个浮点型变量h，用于存储湿度值  Define a floating point variable h to store the humidity value
unsigned long previousMillis = 0;  // 将存储上次DHT更新的时间 The time of the last DHT update is stored
const long interval = 10000;       // 每10秒更新DHT读数 The DHT readings are updated every 10 seconds

// 生成网页的 HTML 代码 Generates the HTML code for the web page
const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML><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">&deg;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";

String processor(const String &var) {
  if (var == "TEMPERATURE") {      // 如果请求的变量是"TEMPERATURE"  If the request variable is "TEMPERATURE"
    return String(t);              // 返回当前温度值的字符串形式  Returns the current temperature as a string
  } else if (var == "HUMIDITY") {  // 如果请求的变量是"HUMIDITY"  If the requested variable is "HUMIDITY"
    return String(h);              // 返回当前湿度值的字符串形式  Returns the current humidity value as a string
  }
  return String();  // 如果请求的变量不是"TEMPERATURE"或"HUMIDITY"，则返回空字符串 If the requested variable is not "TEMPERATURE" or "HUMIDITY", an empty string is returned
}

void setup() {
  Serial.begin(9600);
  dht.begin();         // 初始化DHT11 Initialize DHT11

  // 设置 WiFi 连接  Setting up WiFi connection
  WiFi.begin(ssid, password);
  Serial.println("Connecting to WiFi");
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println(".");
  }

  Serial.println(WiFi.localIP());  //打印IP地址  Printing IP addresses

  server.on("/", HTTP_GET, [](AsyncWebServerRequest *request) {
    request->send_P(200, "text/html", index_html, processor);
  });
  server.on("/temperature", HTTP_GET, [](AsyncWebServerRequest *request) {
    float newT = dht.readTemperature();
    if (isnan(newT)) {
      request->send(500, "text/plain", "Failed to read temperature from DHT sensor!");
    } else {
      request->send_P(200, "text/plain", String(newT).c_str());
    }
  });
  server.on("/humidity", HTTP_GET, [](AsyncWebServerRequest *request) {
    float newH = dht.readHumidity();
    if (isnan(newH)) {
      request->send(500, "text/plain", "Failed to read humidity from DHT sensor!");
    } else {
      request->send_P(200, "text/plain", String(newH).c_str());
    }
  });

  // 启动服务器
  server.begin();
}

void loop() {
  unsigned long currentMillis = millis();            //获取当前的毫秒数，用于记录当前时间。  Gets the current number of milliseconds, which is used to record the current time.
  if (currentMillis - previousMillis >= interval) {  //检查是否已经到达了指定的时间间隔，如果是则执行下面的代码。  Check to see if the specified interval has been reached, and if so execute the following code:
    previousMillis = currentMillis;                  //更新上一次执行的时间，以便下一次判断时间间隔。  Update the time of the last execution so that the next time interval is determined.
    float newT = dht.readTemperature();              //读取温度传感器的数据，并将读取到的值存储在newT变量中。  The data of the temperature sensor is read and the value read is stored in the newT variable.
    if (isnan(newT)) {                               //检查读取的温度值是否为非数字（NaN），如果是则输出错误信息。  Check if the temperature is not a number (NaN) and print an error if it is.
      Serial.println("Failed to read temperature from DHT sensor!");
    } else {
      t = newT;           //将读取到的温度值赋给t变量  Assign the temperature to the t variable
      Serial.println(t);  //打印输出温度  Print output temperature
    }
    float newH = dht.readHumidity();  //读取湿度传感器的数据，并将读取到的值存储在newH变量中  Read the humidity sensor data and store the read value in the newH variable
    if (isnan(newH)) {                //检查读取的湿度值是否为非数字（NaN），如果是则输出错误信息  Check if the humidity value is not a NaN and print an error if it is
      Serial.println("Failed to read humidity from DHT sensor!");
    } else {
      h = newH;           //将读取到的湿度值赋给h变量 The read humidity value is assigned to the h variable
      Serial.println(h);  //打印输出湿度 Print output humidity
    }
  }
}
