#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Fonts/FreeSansBold9pt7b.h>
#include <Fonts/Picopixel.h>
#include <DHT.h>

#define DHT_PIN 8
#define DHT_TYPE  DHT22
#define ledBiru 9
#define ledKuning 10
#define ledMerah 11

int buzzerPin = 12;

DHT dht(DHT_PIN, DHT_TYPE);

//OLED define
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  Serial.println("Sistem Monitoring Suhu Kandang Ayam");
  pinMode(ledBiru, OUTPUT);
  pinMode(ledKuning, OUTPUT);
  pinMode(ledMerah, OUTPUT);
  pinMode(buzzerPin, OUTPUT);
  dht.begin();

  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3D for 128x64
  Serial.println(F("SSD1306 allocation failed"));
  for(;;);
  }
  display.display(); //Display logo
  delay(1000); 
  display.clearDisplay();
}

void loop() {
  // put your main code here, to run repeatedly:
  delay(300);
  float h = dht.readHumidity();
  float t = dht.readTemperature();
  float f = dht.readTemperature(true);
  float hic = dht.computeHeatIndex(t, h, false);
  float hif = dht.computeHeatIndex(t, h);

  display.clearDisplay();
  oledDisplayHeader();
 

  oledDisplay(3,5,28,h,"%");
  oledDisplay(2,70,16,t,"C");
  oledDisplay(2,70,44,f,"F");
 
  display.display(); 

  if(isnan(h) || isnan(t) || isnan(f)){
    Serial.println(F("Failed to read sensor DHT!"));
    return;
  }else{

    if(t <= 29){
      nyalaBiru(); // Suhu Dingin
    }else 
    if(t >= 29 && t <= 35){
      nyalaKuning(); // Suhu Normal
    }else 
    if(t >= 35){
      nyalaMerah(); //Suhu Panas, Buzzer Berbunyi
    }
    
    Serial.print("Humadity:");
    Serial.print(h);
    Serial.print("%  ");
    Serial.print("Temperature:");
    Serial.print(t);
    Serial.print("°C / ");
    Serial.print(f);
    Serial.print("°F  ");
    Serial.print("Heat Index:");
    Serial.print(hic);
    Serial.print("°C / ");
    Serial.print(hif);
    Serial.println("°F ");
  }

}

void oledDisplayHeader(){
 display.setTextSize(1);
 display.setTextColor(WHITE);
 display.setCursor(0, 0);
 display.print("Humidity");
 display.setCursor(60, 0);
 display.print("Temperature");
}

void oledDisplay(int size, int x,int y, float value, String unit){
 int charLen=12; //Karakter default
 int xo=x+charLen*3.2; //Menentukan posisi x dari elemen yang akan menampilkan karakter persen (%) di layar
 int xunit=x+charLen*3.6; //Menentukan posisi x elemen yang akan menampilkan uni
 int xval = x; //Variabel xval akan menentukan posisi x elemen yang akan menampilkan nilai numerik
 display.setTextSize(size); //Mengatur ukuran teks pada layar OLED sesuai dengan nilai size
 display.setTextColor(WHITE); //Mengatur warna teks menjadi putih
 
 if (unit=="%"){
   display.setCursor(x, y);
   display.print(value,0);
   display.print(unit);
 } else {
   if (value>99){
    xval=x;
   } else {
    xval=x+charLen; //Kode akan menampilkan nilai numerik, karakter lingkaran (degree symbol), dan unit di posisi yang sesuai
   }
   display.setCursor(xval, y);
   display.print(value,0);
   display.drawCircle(xo, y+2, 2, WHITE);  // print degree symbols (  )
   display.setCursor(xunit, y);
   display.print(unit);
 }
 
}

void nyalaBiru(){
  digitalWrite(ledBiru, HIGH);
  digitalWrite(ledKuning, LOW);
  digitalWrite(ledMerah, LOW);
}

void nyalaKuning(){
  digitalWrite(ledBiru, LOW);
  digitalWrite(ledKuning, HIGH);
  digitalWrite(ledMerah, LOW);
}

void nyalaMerah(){
  digitalWrite(ledBiru, LOW);
  digitalWrite(ledKuning, LOW);
  digitalWrite(ledMerah, HIGH);
  
  tone(buzzerPin, 500);
  delay(1000);
  
  noTone(buzzerPin);
  delay(1000);
  
  tone(buzzerPin, 1000, 1000);
  delay(2000);
}