#include <WiFi.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <DHT.h>
#include <WiFiClientSecure.h>
#include <UniversalTelegramBot.h>
#include <ArduinoJson.h>
#include <time.h>
// === PIN DEFINISI ===
#define IR_PIN 13
#define MQ2_PIN 34
#define DHT_PIN 4
#define BUZZER_PIN 25
#define LED_ALARM 12
#define LED_AC 27
#define LED_BLOWER 14
// === SENSOR & DISPLAY ===
#define DHTTYPE DHT22
DHT dht(DHT_PIN, DHTTYPE);
LiquidCrystal_I2C lcd(0x27, 20, 4);
// === Wi-Fi & TELEGRAM ===
const char* ssid = "POCO M3 Pro 5G";
const char* password = "qwertyuiop12";
#define BOTtoken "7148350230:AAH8pSCsd02LG0VoC079B5SYlSS-lmkrrm8"
#define CHAT_ID "518947846"
WiFiClientSecure client;
UniversalTelegramBot bot(BOTtoken, client);
// === STATUS VARIABEL ===
bool blowerActive = false;
bool doorAlertSent = false, gasAlertSent = false, tempAlertSent = false, normalSent = false;
bool isGasBahaya = false, isTempTinggi = false, isTempSedang = false, pintuTerbuka = false;
float suhu, kelembaban;
int gas;
unsigned long lastLCDUpdate = 0, lastSensorRead = 0;
const unsigned long intervalSensor = 250;
String lastLine1 = "", lastLine2 = "";
// === WAKTU ===
String getJamTanggal() {
struct tm tmInfo;
if (!getLocalTime(&tmInfo)) return "??:??:??-----??:??:????";
char buf[30];
strftime(buf, sizeof(buf), "%H:%M---%d:%m:%Y", &tmInfo);
return String(buf);
}
// === LCD HANDLER ===
void updateLCD(const String& l1, const String& l2) {
if ((millis() - lastLCDUpdate > 1000) || l1 != lastLine1 || l2 != lastLine2) {
lcd.clear();
lcd.setCursor(0, 0); lcd.print(l1);
lcd.setCursor(0, 1); lcd.print(l2);
lcd.setCursor(0, 3); lcd.print(getJamTanggal());
lastLine1 = l1; lastLine2 = l2;
lastLCDUpdate = millis();
}
}
void setBlower(bool st) {
digitalWrite(LED_BLOWER, st ? HIGH : LOW);
blowerActive = st;
}
void kirimPesanTelegram(const String& msg) {
if (WiFi.status() == WL_CONNECTED) {
bot.sendMessage(CHAT_ID, msg, "Markdown");
Serial.println("[Telegram] " + msg);
}
}
void bacaSensor() {
suhu = dht.readTemperature();
kelembaban = dht.readHumidity();
gas = analogRead(MQ2_PIN);
pintuTerbuka = digitalRead(IR_PIN) == HIGH;
// Serial Output
Serial.println("===== Pembacaan Sensor =====");
Serial.print("Suhu: "); Serial.print(suhu); Serial.println(" °C");
Serial.print("Kelembaban: "); Serial.print(kelembaban); Serial.println(" %");
Serial.print("Gas MQ2: "); Serial.println(gas);
Serial.print("Pintu: "); Serial.println(pintuTerbuka ? "TERBUKA" : "TERTUTUP");
Serial.println("============================\n");
}
void updateStatus() {
isGasBahaya = gas > 1300;
isTempTinggi = suhu > 30;
isTempSedang = suhu > 27 && suhu <= 30;
Serial.println("===== Status Sistem =====");
Serial.print("Gas Bahaya: "); Serial.println(isGasBahaya ? "YA" : "TIDAK");
Serial.print("Suhu Tinggi: "); Serial.println(isTempTinggi ? "YA" : "TIDAK");
Serial.print("Suhu Sedang: "); Serial.println(isTempSedang ? "YA" : "TIDAK");
Serial.println("=========================\n");
}
void handleAlarmEffect() {
bool adaAlarm = gasAlertSent || doorAlertSent || tempAlertSent;
if (!adaAlarm) {
noTone(BUZZER_PIN);
digitalWrite(LED_ALARM, LOW);
return;
}
bool faseON = (millis() % 800UL) < 200UL;
if (faseON) tone(BUZZER_PIN, 1000);
else noTone(BUZZER_PIN);
digitalWrite(LED_ALARM, faseON ? HIGH : LOW);
}
void handlePrioritas() {
if (isGasBahaya) {
digitalWrite(LED_AC, LOW);
setBlower(true);
updateLCD("BAHAYA GAS", "BLOWER AKTIF");
Serial.println("[Prioritas] Bahaya Gas - Blower Aktif - AC Mati");
if (!gasAlertSent) {
kirimPesanTelegram("BAHAYA GAS!!! Blower Beroperasi!!!");
gasAlertSent = true; doorAlertSent = tempAlertSent = normalSent = false;
}
} else if (pintuTerbuka && isTempTinggi) {
digitalWrite(LED_AC, LOW);
setBlower(true);
updateLCD("PINTU TERBUKA", "T:" + String(suhu,1) + (char)223 + "C Blower ON");
Serial.println("[Prioritas] Pintu Terbuka + Suhu Tinggi - Blower Aktif - AC Mati");
if (!doorAlertSent) {
kirimPesanTelegram("Pintu Terbuka! Suhu > 32C. Blower aktif.");
doorAlertSent = true; gasAlertSent = tempAlertSent = normalSent = false;
}
} else if (pintuTerbuka && isTempSedang) {
digitalWrite(LED_AC, LOW);
setBlower(true);
updateLCD("PINTU TERBUKA", "Blower ON!");
Serial.println("[Prioritas] Pintu Terbuka + Suhu Sedang - Blower Aktif - AC Mati");
if (!doorAlertSent) {
kirimPesanTelegram("Pintu terbuka, AC dimatikan, Blower ON!");
doorAlertSent = true; gasAlertSent = tempAlertSent = normalSent = false;
}
} else if (!pintuTerbuka && isTempTinggi) {
digitalWrite(LED_AC, LOW);
setBlower(true);
updateLCD("SUHU > 32C", "Blower ON");
Serial.println("[Prioritas] Suhu Tinggi - Rumah Tertutup - Blower Aktif - AC Mati");
if (!tempAlertSent) {
kirimPesanTelegram("Suhu > 32C. AC dimatikan, blower aktif.");
tempAlertSent = true; doorAlertSent = gasAlertSent = normalSent = false;
}
} else if (!pintuTerbuka && isTempSedang) {
digitalWrite(LED_AC, HIGH); // AC ON
setBlower(false); // blower OFF
noTone(BUZZER_PIN); // buzzer OFF
updateLCD("SUHU 27-30C", "AC ON");
Serial.println("[Prioritas] Suhu 27‑30°C - AC ON, Blower OFF");
if (!tempAlertSent) {
kirimPesanTelegram("Suhu 27‑30 °C. AC dinyalakan, blower OFF.");
tempAlertSent = false; doorAlertSent = gasAlertSent = normalSent = false;
}
} else {
digitalWrite(LED_AC, LOW);
setBlower(false);
updateLCD("Rumah Aman!!!", "");
Serial.println("[Prioritas] Rumah Aman - Semua Sistem OFF");
if (!normalSent) {
kirimPesanTelegram("Rumah Aman!!!");
normalSent = true; doorAlertSent = gasAlertSent = tempAlertSent = false;
}
}
Serial.print("AC: "); Serial.println(digitalRead(LED_AC) ? "ON" : "OFF");
Serial.print("Blower: "); Serial.println(blowerActive ? "ON" : "OFF");
Serial.println("==========================================\n");
}
void setup() {
Serial.begin(115200);
pinMode(IR_PIN, INPUT);
pinMode(MQ2_PIN, INPUT);
pinMode(BUZZER_PIN, OUTPUT);
pinMode(LED_ALARM, OUTPUT);
pinMode(LED_AC, OUTPUT);
pinMode(LED_BLOWER, OUTPUT);
dht.begin();
lcd.init();
lcd.backlight();
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500); Serial.print(".");
}
Serial.println("\n[WiFi] Connected to " + String(ssid));
configTime(7 * 3600, 0, "pool.ntp.org", "time.nist.gov");
client.setInsecure();
}
void loop() {
if (millis() - lastSensorRead >= intervalSensor) {
lastSensorRead = millis();
bacaSensor();
updateStatus();
handlePrioritas();
handleAlarmEffect();
}
}