#define BLYNK_TEMPLATE_ID "TMPL6AS8AJ7Ir"
#define BLYNK_TEMPLATE_NAME "SmartTrashSystem"
#define BLYNK_AUTH_TOKEN "azK4RWshMGlMM_iL157XmgsgUKMjaWaq"

#include <ESP32Servo.h>
#include <NewPing.h>
#include <WiFi.h>
#include <BlynkSimpleEsp32.h>

char auth[] = BLYNK_AUTH_TOKEN;
char ssid[] = "Wokwi-GUEST";
char pass[] = "";

#define TRIGGER_PIN   13 // Pin yang terhubung ke pin TRIGGER sensor ultrasonik
#define ECHO_PIN      12 // Pin yang terhubung ke pin ECHO sensor ultrasonik
#define PIR_PIN       15 // Pin yang terhubung ke pin sensor PIR
#define SERVO_PIN     2  // Pin yang terhubung ke pin kontrol servo motor
#define DATASTREAM_PIN V3 // Pin virtual yang akan digunakan untuk datastream

NewPing sonar(TRIGGER_PIN, ECHO_PIN, 200);
Servo myservo;

int threshold = 2; // Ambang batas (threshold) 2 cm
bool trashFullNotified = false;
int trashLevel = 0;

BlynkTimer timer;

void setup() {
  Serial.begin(9600);
  Blynk.begin(auth, ssid, pass); // Mulai koneksi Blynk

  myservo.attach(SERVO_PIN);
  pinMode(PIR_PIN, INPUT);

  // Setup pin virtual untuk datastream
  Blynk.virtualWrite(DATASTREAM_PIN, trashLevel); // Menginisialisasi datastream dengan level sampah awal

  // Setup timer untuk memantau status tempat sampah setiap 1 detik
  timer.setInterval(1000L, checkTrashStatus);
}

void loop() {
  Blynk.run(); // Tetapkan agar Blynk berjalan dalam loop
  timer.run(); // Jalankan timer Blynk
}

void checkTrashStatus() {
  int distance = sonar.ping_cm();
  int pirState = digitalRead(PIR_PIN);

  // Menghitung level sampah berdasarkan jarak
  trashLevel = map(distance, 0, threshold, 100, 0); // Map jarak ke level sampah

  // Kirim level sampah ke Blynk Datastream
  Blynk.virtualWrite(DATASTREAM_PIN, trashLevel);

  // Jika jarak kurang dari atau sama dengan ambang batas (2 cm), tempat sampah dianggap penuh
  if (distance <= threshold && !trashFullNotified) {
    Blynk.virtualWrite(V1, "Tempat sampah full!"); // Kirim notifikasi ke widget notifikasi di aplikasi Blynk
    trashFullNotified = true; // Setel status notifikasi telah dikirim
  }
  // Jika jarak lebih besar dari ambang batas (lebih dari 2 cm), tempat sampah dianggap belum penuh
  else if (distance > threshold && trashFullNotified) {
    Blynk.virtualWrite(V1, "Tempat sampah belum full."); // Kirim notifikasi ke widget notifikasi di aplikasi Blynk
    trashFullNotified = false; // Setel status notifikasi telah dikirim
  }


  // Jika jarak kurang dari ambang batas dan sensor IR mendeteksi keberadaan sampah
  if (distance <= threshold && pirState == HIGH) {
    openLid();
    delay(5000);
    closeLid();
  }
}

void openLid() {
  myservo.write(90);
  Blynk.virtualWrite(V2, 1); // Mengirimkan sinyal ke tombol virtual di Blynk
  Blynk.virtualWrite(V3, 1); // Mengirimkan sinyal ke indikator virtual di Blynk
}

void closeLid() {
  myservo.write(0);
  Blynk.virtualWrite(V2, 0); // Mengirimkan sinyal ke tombol virtual di Blynk
  Blynk.virtualWrite(V3, 0); // Mengirimkan sinyal ke indikator virtual di Blynk
}