#include <WiFi.h>
#include <WebServer.h>
#include <DHT.h>
#include <PubSubClient.h>
#include <Preferences.h> // Untuk menyimpan SSID dan password
// Konfigurasi DHT Sensor
#define DHTPIN 32 // Pin yang digunakan untuk DHT
#define DHTTYPE DHT22 // Tipe DHT yang digunakan
DHT dht(DHTPIN, DHTTYPE);
// Buffer untuk pesan MQTT
#define MSG_BUFFER_SIZE (150)
char msg[MSG_BUFFER_SIZE];
char pesan[150];
// Konfigurasi WiFi dan MQTT
const char* ssid_default = "ESP32-AP"; // SSID default untuk AP mode
const char* password_default = ""; // Password default untuk AP mode
const char* mqtt_server = "mqtt.telkomiot.id"; // Server MQTT
const char* topik = "v2.0/pubs/APP66de57f07db0a88801/DEV6703996c5099b52781"; // Topik MQTT
String AccessKey = "192660c7259ee9ff"; // Access Key MQTT
String AccessToken = "192660c7261c7eac"; // Access Token MQTT
String Devicename = "Suhu kelembapan";
WebServer server(80); // Membuat server web di port 80
WiFiClient espClient; // Client WiFi untuk MQTT
PubSubClient client(espClient); // Client MQTT
Preferences preferences; // Untuk menyimpan data WiFi
String ssidNew = "", passNew = "", lokasi = "";
// Timer untuk AP mode
unsigned long apStartTime = 0;
const unsigned long apDuration = 120000; // Durasi AP mode (2 menit)
// Fungsi untuk menampilkan halaman form konfigurasi Wi-Fi dan lokasi dengan tampilan rapi
void handleRoot() {
String html = "<html><head>";
html += "<link rel='stylesheet' href='https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css'>";
html += "<style>body {background-color: #f8f9fa;} .container {margin-top: 50px;} h1 {margin-bottom: 40px;} .form-group {margin-bottom: 15px;}</style>";
html += "</head><body>";
html += "<div class='container'><div class='row justify-content-center'><div class='col-md-6'><h1 class='text-center'>Konfigurasi Wi-Fi dan Lokasi</h1>";
html += "<form action=\"/action_page\" method=\"POST\">";
html += "<div class='form-group'><label for='ssid'>SSID:</label><input type='text' class='form-control' id='ssid' name='ssidNew' placeholder='Masukkan SSID'></div>";
html += "<div class='form-group'><label for='password'>Password:</label><input type='password' class='form-control' id='password' name='passNew' placeholder='Masukkan Password'></div>";
html += "<div class='form-group'><label for='lokasi'>Lokasi:</label><input type='text' class='form-control' id='lokasi' name='lokasi' placeholder='Masukkan Lokasi'></div>";
html += "<div class='text-center'><input type='submit' value='Submit' class='btn btn-primary'></div>";
html += "</form></div></div></div>";
html += "</body></html>";
server.send(200, "text/html", html);
}
// Fungsi untuk menangani form yang dikirimkan
void handleForm() {
ssidNew = server.arg("ssidNew");
passNew = server.arg("passNew");
lokasi = server.arg("lokasi");
// Menyimpan SSID dan Password ke Preferences (NVS)
preferences.begin("wifi", false);
preferences.putString("ssid", ssidNew);
preferences.putString("password", passNew);
preferences.end();
// Menampilkan halaman berhasil
String html = "<html><head>";
html += "<link rel='stylesheet' href='https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css'>";
html += "<style>body {background-color: #f8f9fa;} .container {margin-top: 50px;} h1 {margin-bottom: 20px;} .alert {margin-top: 20px;}</style>";
html += "</head><body>";
html += "<div class='container'><div class='row justify-content-center'><div class='col-md-6'><h1 class='text-center'>Konfigurasi Berhasil!</h1>";
html += "<div class='alert alert-success' role='alert'>Konfigurasi Wi-Fi telah berhasil disimpan!</div>";
html += "<p><strong>SSID:</strong> " + ssidNew + "</p>";
html += "<p><strong>Password:</strong> " + passNew + "</p>";
html += "<p><strong>Lokasi:</strong> " + lokasi + "</p>";
html += "<p>Data sensor tersedia di <a href=\"/data\">/192.168.4.1/data</a>.</p>";
html += "</div></div></div>";
html += "</body></html>";
server.send(200, "text/html", html);
}
// Fungsi untuk menampilkan data suhu dan kelembapan dalam format JSON
void handleData() {
float h = dht.readHumidity();
float t = dht.readTemperature();
if (isnan(h) || isnan(t)) {
server.send(500, "text/plain", "Sensor tidak terbaca");
return;
}
// Menggunakan Bootstrap untuk menampilkan data dalam tampilan yang lebih rapi
String html = "<html><head>";
html += "<link rel='stylesheet' href='https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css'>";
html += "<style>body {background-color: #f8f9fa;} .container {margin-top: 50px;} .display-4 {font-size: 2.5rem;} .data-value {font-weight: bold; font-size: 3rem;}</style>";
html += "</head><body>";
html += "<div class='container'><h1 class='text-center'>HASIL MONITORING</h1>";
html += "<div class='row'><div class='col-md-6 text-center'><h2>SUHU</h2>";
html += "<p class='data-value'>" + String(t) + " ℃</p></div>"; // Increased font size and bold styling
html += "<div class='col-md-6 text-center'><h2>KELEMBAPAN</h2>";
html += "<p class='data-value'>" + String(h) + " %</p></div></div>"; // Increased font size and bold styling
html += "<div class='row'><div class='col-md-12 text-center'><h2>LOKASI</h2>";
html += "<p class='data-value'>" + String(lokasi) + "</p></div></div>"; // Increased font size and bold styling
html += "<div class='text-center mt-4'><a href='/' class='btn btn-primary btn-lg'>Kembali</a></div>"; // Larger button for better accessibility
html += "</div></body></html>";
server.send(200, "text/html", html);
}
// Fungsi untuk mencoba reconnect ke MQTT
void reconnect() {
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
if (client.connect(Devicename.c_str(), AccessKey.c_str(), AccessToken.c_str())) {
Serial.println("connected");
client.publish(topik, "terkoneksi"); // Publish status terkoneksi
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
delay(5000);
}
}
}
// Fungsi setup() untuk inisialisasi
void setup() {
Serial.begin(115200);
// Cek apakah ada data WiFi yang tersimpan
preferences.begin("wifi", true);
ssidNew = preferences.getString("ssid", "");
passNew = preferences.getString("password", "");
preferences.end();
// Memulai dalam AP mode
WiFi.mode(WIFI_AP);
WiFi.softAP(ssid_default, password_default);
IPAddress IP = WiFi.softAPIP();
Serial.print("AP Mode IP Address: ");
Serial.println(IP);
// Mulai server web
server.on("/", handleRoot); // Form Wi-Fi dan lokasi konfigurasi
server.on("/action_page", handleForm); // Handle form
server.on("/data", handleData); // Halaman menampilkan data JSON
server.begin(); // Memulai server web
Serial.println("Server started");
// Mulai hitung waktu untuk AP mode
apStartTime = millis();
dht.begin(); // Memulai DHT sensor
// Konfigurasi MQTT
client.setServer(mqtt_server, 1883);
}
// Fungsi loop() yang berjalan berulang
void loop() {
unsigned long currentTime = millis();
// Jalankan server web untuk menangani permintaan selama AP mode
server.handleClient();
// Cek apakah waktu 2 menit untuk AP mode telah berlalu
if (currentTime - apStartTime >= apDuration) {
Serial.println("2 menit berlalu, beralih ke STA mode");
// Beralih ke mode station dan hubungkan ke Wi-Fi yang baru
WiFi.softAPdisconnect(true);
WiFi.mode(WIFI_STA);
WiFi.begin(ssidNew.c_str(), passNew.c_str());
// Tunggu sampai terhubung ke jaringan Wi-Fi
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("Terhubung ke Jaringan");
Serial.print("IP Address: ");
Serial.println(WiFi.localIP()); // Cetak IP Address
// Mulai kirim data ke MQTT setelah berhasil terhubung
while (true) {
if (!client.connected()) {
reconnect();
}
client.loop();
// Membaca data suhu dan kelembapan
float h = dht.readHumidity();
float t = dht.readTemperature();
// Kirim data ke topik MQTT
sprintf(pesan, "{\"lokasi\":\"%s\",\"t\":\"%.2f\",\"h\":\"%.2f\"}", lokasi.c_str(), t, h);
Serial.print("Publish message: ");
Serial.println(pesan);
client.publish(topik, pesan);
delay(3000); // Mengirimkan data setiap 3 detik
}
}
}