// Memanggil pustaka-pustaka yang diperlukan:
#include <WiFi.h>          // Untuk menghubungkan ESP32 ke jaringan Wi-Fi
#include <WiFiClient.h>    // Untuk membuat koneksi TCP/IP
#include <WebServer.h>     // Untuk membuat server web pada ESP32
#include <ESPmDNS.h>       // Untuk mDNS (Multicast DNS), memudahkan akses server dengan nama
#include <DHT.h>           // Untuk berinteraksi dengan sensor DHT

// Menyimpan nama dan kata sandi jaringan Wi-Fi:
const char *ssid = "asadprab";
const char *password = "87654321";

// Membuat objek server web yang mendengarkan pada port 80:
WebServer server(80);

// Membuat objek sensor DHT yang terhubung ke pin 26, berjenis DHT22:
DHT dht(26, DHT22);

// Fungsi untuk menangani permintaan ke halaman utama (root) server web
void handleRoot() {
  // Buat buffer untuk menyimpan teks HTML
  char msg[1500];

  // Buat teks HTML dengan bacaan suhu dan kelembaban
  snprintf(msg, 1500,
           "<html>\
<head>\
  <meta http-equiv='refresh' content='1'/>\
  <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'>\
  <title>ESP32 DHT Server</title>\
  <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:#ca3517;'></i>\
    <span class='dht-labels'>Temperature</span>\
    <span>%.2f</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>%.2f</span>\
    <sup class='units'>&percnt;</sup>\
  </p>\
</body>\
</html>",
           readDHTTemperature(), readDHTHumidity() // Masukkan nilai suhu dan kelembaban
          );

  // Kirim respons HTML ke klien
  server.send(200, "text/html", msg);
}

// Fungsi yang dijalankan sekali saat program dimulai
void setup(void) {
  // Inisialisasi komunikasi serial untuk debugging
  Serial.begin(115200);

  // Inisialisasi sensor DHT
  dht.begin();

  // Hubungkan ke jaringan Wi-Fi sebagai stasiun (bukan access point)
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  Serial.println("");  // Cetak baris kosong untuk pemisah

  // Tunggu hingga terkoneksi ke Wi-Fi
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);  // Jeda sebentar
    Serial.print(".");  // Cetak titik untuk menunjukkan proses koneksi
  }

  // Cetak informasi koneksi Wi-Fi
  Serial.println("");
  Serial.print("Connected to ");
  Serial.println(ssid);
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());

  // Mulai layanan mDNS untuk kemudahan akses server dengan nama
  if (MDNS.begin("esp32")) {
    Serial.println("MDNS responder started");
  }

  // Setel server web untuk menangani permintaan root dengan fungsi handleRoot
  server.on("/", handleRoot);

  // Mulai server web
  server.begin();
  Serial.println("HTTP server started");
}

// Fungsi yang dijalankan berulang-ulang setelah setup()
void loop(void) {
  // Tangani permintaan yang masuk ke server web
  server.handleClient();

  // Delay singkat untuk memungkinkan tugas lain berjalan
  delay(2);  // Jeda 2 milidetik
}
// Fungsi untuk membaca suhu dari sensor DHT
float readDHTTemperature() {
  // Sensor readings may also be up to 2 seconds  // Mengingatkan bahwa pembacaan sensor bisa memakan waktu hingga 2 detik
  // Read temperature as Celsius (the default)  // Membaca suhu dalam derajat Celsius (default)
  float t = dht.readTemperature();               // Membaca suhu dari sensor DHT dan menyimpannya dalam variabel 't'
  
  if (isnan(t)) {                                // Memeriksa apakah pembacaan suhu gagal (nilai NaN)
    Serial.println("Failed to read from DHT sensor!");  // Mencetak pesan kesalahan jika gagal
    return -1;                                  // Mengembalikan nilai -1 jika gagal
  } else {
    Serial.println(t);                           // Mencetak nilai suhu ke serial monitor jika berhasil
    return t;                                     // Mengembalikan nilai suhu yang dibaca
  }
}

// Fungsi untuk membaca kelembaban dari sensor DHT
float readDHTHumidity() {
  // Sensor readings may also be up to 2 seconds  // Mengingatkan bahwa pembacaan sensor bisa memakan waktu hingga 2 detik
  float h = dht.readHumidity();                 // Membaca kelembaban dari sensor DHT dan menyimpannya dalam variabel 'h'
  
  if (isnan(h)) {                                // Memeriksa apakah pembacaan kelembaban gagal (nilai NaN)
    Serial.println("Failed to read from DHT sensor!");  // Mencetak pesan kesalahan jika gagal
    return -1;                                  // Mengembalikan nilai -1 jika gagal
  } else {
    Serial.println(h);                           // Mencetak nilai kelembaban ke serial monitor jika berhasil
    return h;                                     // Mengembalikan nilai kelembaban yang dibaca
  }
}