#include #include "RTClib.h" #include #include #include #include #include RTC_DS3231 rtc; // Pin relay const int relayPin = 15; // Waktu untuk mematikan relay const int relayOffHour[2] = {8, 16}; const int relayOffMinute[2] = {0, 0}; int relayDuration = 10; bool relayTriggered[2] = {false, false}; // Definisikan NTP Client untuk sinkronisasi waktu WiFiUDP ntpUDP; NTPClient timeClient(ntpUDP, "pool.ntp.org", 7 * 3600); // Pin untuk sensor kelembaban tanah const int soilMoisturePin = 34; // Pin untuk sensor water level const int waterLevelPin = 32; // Kalibrasi sensor kelembaban tanah const int airValue = 4095; const int waterValue = 600; // Kalibrasi sensor water level const int emptyLevelValue = 420; // Nilai analog ketika tangki kosong (sesuaikan dengan pengukuran) const int fullLevelValue = 1260; // Nilai analog ketika tangki penuh (sesuaikan dengan pengukuran) // Inisialisasi objek bot Telegram #define BOT_TOKEN "7384958342:AAH6j5ozS6bZ3YL2iZ9RLpwU-wOe3jjBpjc" #define CHAT_ID "1351963764" WiFiClientSecure client; UniversalTelegramBot bot(BOT_TOKEN, client); unsigned long lastTimeBotRan; unsigned long lastRelayCheck = 0; bool relayState = HIGH; bool manualRelayRequest = false; unsigned long manualRelayStartTime = 0; int manualRelayDuration = 0; void sendTelegramMessage(String message) { bot.sendMessage(CHAT_ID, message, ""); } // Fungsi untuk membaca kelembaban tanah int readSoilMoisture() { int soilMoistureValue = analogRead(soilMoisturePin); int moisturePercentage = map(soilMoistureValue, airValue, waterValue, 0, 100); moisturePercentage = constrain(moisturePercentage, 0, 100); return moisturePercentage; } // Fungsi untuk membaca level air int readWaterLevel() { int waterLevelValue = analogRead(waterLevelPin); // Kalibrasi nilai level air jika diperlukan int levelPercentage = map(waterLevelValue, emptyLevelValue, fullLevelValue, 0, 100); levelPercentage = constrain(levelPercentage, 0, 100); return levelPercentage; } void setup() { Serial.begin(115200); pinMode(relayPin, OUTPUT); digitalWrite(relayPin, HIGH); pinMode(soilMoisturePin, INPUT); pinMode(waterLevelPin, INPUT); if (!rtc.begin()) { Serial.println("RTC tidak ditemukan!"); while (1); } if (rtc.lostPower()) { Serial.println("RTC kehilangan daya, mengatur ulang waktu!"); } // Hubungkan ke WiFi WiFi.begin("GenZ", "12345678"); while (WiFi.status() != WL_CONNECTED) { delay(1000); Serial.println("Connecting to WiFi..."); } Serial.println("Connected to WiFi"); // Mulai NTP client dan sinkronisasi waktu timeClient.begin(); while (!timeClient.update()) { timeClient.forceUpdate(); } rtc.adjust(DateTime(timeClient.getEpochTime())); client.setCACert(TELEGRAM_CERTIFICATE_ROOT); // Add root certificate for api.telegram.org lastTimeBotRan = millis(); } void handleNewMessages(int numNewMessages) { for (int i = 0; i < numNewMessages; i++) { String chat_id = String(bot.messages[i].chat_id); String text = bot.messages[i].text; String from_name = bot.messages[i].from_name; if (text == "/start") { String welcome = "Selamat datang, " + from_name + ".\n"; welcome += "Gunakan perintah berikut untuk mendapatkan nilai sensor atau mengatur durasi relay:\n"; welcome += "/waterlevel - untuk mendapatkan nilai sensor level air\n"; welcome += "/soilmoisture - untuk mendapatkan nilai sensor kelembaban tanah\n"; welcome += "/set10s - untuk mengatur durasi relay menjadi 10 detik\n"; welcome += "/set15s - untuk mengatur durasi relay menjadi 15 detik\n"; welcome += "/set20s - untuk mengatur durasi relay menjadi 20 detik\n"; welcome += "/manualon - untuk menyalakan relay secara manual\n"; welcome += "/manualoff - untuk mematikan relay secara manual\n"; bot.sendMessage(chat_id, welcome, ""); } else if (text == "/waterlevel") { int levelPercentage = readWaterLevel(); String message; if (levelPercentage < 20) { message = "Peringatan! Level air sangat rendah: " + String(levelPercentage) + "%. Segera isi ulang!"; } else if (levelPercentage < 50) { message = "Level air rendah: " + String(levelPercentage) + "%. ketinggian air sedang."; } else if (levelPercentage < 80) { message = "Level air cukup: " + String(levelPercentage) + "%. ketinggian air aman."; } else { message = "Level air tinggi: " + String(levelPercentage) + "%. Tidak perlu tindakan."; } bot.sendMessage(chat_id, message, ""); } else if (text == "/soilmoisture") { int moisturePercentage = readSoilMoisture(); String message; if (moisturePercentage < 20) { message = "Peringatan! Kelembaban tanah sangat rendah: " + String(moisturePercentage) + "%. Segera siram!"; } else if (moisturePercentage < 50) { message = "Kelembaban tanah rendah: " + String(moisturePercentage) + "%. Periksa ketersediaan air."; } else if (moisturePercentage < 80) { message = "Kelembaban tanah cukup: " + String(moisturePercentage) + "%. Kondisi baik."; } else { message = "Kelembaban tanah tinggi: " + String(moisturePercentage) + "%. Tidak perlu tindakan."; } bot.sendMessage(chat_id, message, ""); } else if (text == "/set10s") { relayDuration = 10; bot.sendMessage(chat_id, "Durasi relay telah diatur menjadi 10 detik", ""); } else if (text == "/set15s") { relayDuration = 15; bot.sendMessage(chat_id, "Durasi relay telah diatur menjadi 15 detik", ""); } else if (text == "/set20s") { relayDuration = 20; bot.sendMessage(chat_id, "Durasi relay telah diatur menjadi 20 detik", ""); } else if (text == "/manualon") { manualRelayRequest = true; manualRelayDuration = relayDuration; // Gunakan durasi yang sudah ditentukan manualRelayStartTime = millis(); bot.sendMessage(chat_id, "Relay telah dinyalakan secara manual selama " + String(manualRelayDuration) + " detik", ""); } else if (text == "/manualoff") { digitalWrite(relayPin, HIGH); relayState = HIGH; manualRelayRequest = false; bot.sendMessage(chat_id, "Relay telah dimatikan secara manual", ""); } else { String message = "Perintah tidak dikenal. Gunakan /start untuk melihat perintah yang tersedia."; bot.sendMessage(chat_id, message, ""); } } } void loop() { DateTime now = rtc.now(); Serial.print("Waktu sekarang: "); Serial.print(now.hour()); Serial.print(':'); Serial.print(now.minute()); Serial.print(':'); Serial.println(now.second()); int moisturePercentage = readSoilMoisture(); Serial.print("Kelembaban Tanah: "); Serial.print(moisturePercentage); Serial.println("%"); int levelPercentage = readWaterLevel(); Serial.print("Level Air: "); Serial.print(levelPercentage); Serial.println("%"); if (manualRelayRequest) { if (millis() - manualRelayStartTime < manualRelayDuration * 1000) { digitalWrite(relayPin, LOW); relayState = LOW; } else { digitalWrite(relayPin, HIGH); relayState = HIGH; manualRelayRequest = false; } } else { if (millis() - lastRelayCheck >= 1000) { // Periksa relay setiap detik for (int i = 0; i < 2; i++) { if (now.hour() == relayOffHour[i] && now.minute() == relayOffMinute[i] && !relayTriggered[i]) { Serial.println("Mematikan relay..."); digitalWrite(relayPin, LOW); relayState = LOW; relayTriggered[i] = true; // Set relay as triggered for this time slot lastRelayCheck = millis(); } } if (relayState == LOW && (millis() - lastRelayCheck >= relayDuration * 1000)) { Serial.println("Menyalakan relay..."); digitalWrite(relayPin, HIGH); relayState = HIGH; } } } // Periksa pesan baru dari bot Telegram setiap 1 detik if (millis() - lastTimeBotRan > 1000) { int numNewMessages = bot.getUpdates(bot.last_message_received + 1); while (numNewMessages) { handleNewMessages(numNewMessages); numNewMessages = bot.getUpdates(bot.last_message_received + 1); } lastTimeBotRan = millis(); } }