#define BLYNK_TEMPLATE_ID "TMPL6yAzjdQoO"
#define BLYNK_TEMPLATE_NAME "GSM"
#define BLYNK_AUTH_TOKEN "A7dXsLLBa4N5NDpWis5EEvbvi4Sm83Gi"

#define BLYNK_PRINT Serial

// GSM modül tipi tanımlanıyor
#define TINY_GSM_MODEM_SIM800

#include <TinyGsmClient.h>
#include <BlynkSimpleTinyGSM.h>
#include <DHT.h>

// GSM modülü bağlantı ayarları (Operatör bilgileri)
char apn[]  = "internet";  // APN (Access Point Name)
char user[] = "";          // Kullanıcı adı (genelde boş bırakılır)
char pass[] = "";          // Şifre (genelde boş bırakılır)

#include <SoftwareSerial.h>
SoftwareSerial SerialAT(10, 11); // RX ve TX pinleri GSM modülü için tanımlanıyor
TinyGsm modem(SerialAT);

// Röle çıkış pinleri tanımlanıyor
#define RELAY_2 2
#define RELAY_3 3
#define RELAY_4 4
#define RELAY_5 5

// DHT sensörü tanımları (Sıcaklık ve nem ölçümü için)
#define DHTPIN 6          // DHT sensörünün bağlı olduğu pin
#define DHTTYPE DHT11     // DHT sensör tipi 
DHT dht(DHTPIN, DHTTYPE); // DHT sensör nesnesi oluşturuluyor

// Blynk zamanlayıcısı tanımlanıyor
BlynkTimer timer;

// DHT sensöründen verileri okuyup Blynk'e gönderen fonksiyon
void sendSensorData() {
  float h = dht.readHumidity();    // Nem değerini oku
  float t = dht.readTemperature(); // Sıcaklık değerini oku

  // Eğer sensörden veri alınamıyorsa hata mesajı yazdır
  if (isnan(h) || isnan(t)) {
    Serial.println("DHT sensöründen veri okunamadı!");
    return;
  }

  // Nem ve sıcaklık verilerini Blynk'e gönder
  Blynk.virtualWrite(V5, h); // Nem verisini Blynk uygulamasındaki V5 sanal pinine gönder
  Blynk.virtualWrite(V6, t); // Sıcaklık verisini Blynk uygulamasındaki V6 sanal pinine gönder

  // Seri monitöre verileri yazdır
  Serial.print("Nem: ");
  Serial.print(h);
  Serial.print(" %, Sıcaklık: ");
  Serial.print(t);
  Serial.println(" °C");
}

void setup() {
  // Seri monitör başlatılıyor
  Serial.begin(9600);

  // GSM modülü başlatılıyor
  SerialAT.begin(9600);
  delay(3000); // Modülün başlatılması için bekleme süresi
  Serial.println("Modem başlatılıyor...");
  modem.restart();

  // Blynk sunucusuna bağlanılıyor
  Blynk.begin(BLYNK_AUTH_TOKEN, modem, apn, user, pass);

  // Röle pinleri çıkış olarak ayarlanıyor
  pinMode(RELAY_2, OUTPUT);
  pinMode(RELAY_3, OUTPUT);
  pinMode(RELAY_4, OUTPUT);
  pinMode(RELAY_5, OUTPUT);

  // Röleler başlangıçta kapalı (HIGH) duruma getiriliyor
  digitalWrite(RELAY_2, HIGH);
  digitalWrite(RELAY_3, HIGH);
  digitalWrite(RELAY_4, HIGH);
  digitalWrite(RELAY_5, HIGH);

  // DHT sensörü başlatılıyor
  dht.begin();

  // Sensör verilerinin her 2 saniyede bir gönderilmesi için zamanlayıcı ayarlanıyor
  timer.setInterval(2000L, sendSensorData);

  Serial.println("Sistem başlatıldı. Tüm röleler KAPALI. DHT sensörü hazır.");
}

void loop() {
  Blynk.run();  // Blynk bağlantısını sürekli çalıştırır
  timer.run();  // Zamanlayıcıları sürekli çalıştırır
}

// Blynk uygulamasından V0 sanal piniyle gelen komut, röle 2'yi kontrol eder
BLYNK_WRITE(V0) {
  int value = param.asInt(); // Blynk'ten gelen değer (0 veya 1)
  digitalWrite(RELAY_2, value == 1 ? LOW : HIGH); // Röleyi kontrol et
  Serial.print("RELAY_2: ");
  Serial.println(value == 1 ? "AÇIK" : "KAPALI");
}

// Blynk uygulamasından V1 sanal piniyle gelen komut, röle 3'ü kontrol eder
BLYNK_WRITE(V1) {
  int value = param.asInt(); // Blynk'ten gelen değer (0 veya 1)
  digitalWrite(RELAY_3, value == 1 ? LOW : HIGH); // Röleyi kontrol et
  Serial.print("RELAY_3: ");
  Serial.println(value == 1 ? "AÇIK" : "KAPALI");
}

// Blynk uygulamasından V2 sanal piniyle gelen komut, röle 4'ü kontrol eder
BLYNK_WRITE(V2) {
  int value = param.asInt(); // Blynk'ten gelen değer (0 veya 1)
  digitalWrite(RELAY_4, value == 1 ? LOW : HIGH); // Röleyi kontrol et
  Serial.print("RELAY_4: ");
  Serial.println(value == 1 ? "AÇIK" : "KAPALI");
}

// Blynk uygulamasından V3 sanal piniyle gelen komut, röle 5'i kontrol eder
BLYNK_WRITE(V3) {
  int value = param.asInt(); // Blynk'ten gelen değer (0 veya 1)
  digitalWrite(RELAY_5, value == 1 ? LOW : HIGH); // Röleyi kontrol et
  Serial.print("RELAY_5: ");
  Serial.println(value == 1 ? "AÇIK" : "KAPALI");
}
