// import all the libraries we will need and download them if you don't have them downloaded on your pc
#include <Wire.h>
#include <ESP32Servo.h> //Library to control the servo motor
#include <LiquidCrystal_I2C.h>  //Library for LCD 
LiquidCrystal_I2C lcd(0x27, 20, 4); 
#include "RTClib.h"


Servo myservo;  // create servo object to control a servo
int pos = 0; 

RTC_DS3231 rtc;

byte customChar[8] = {
  0b00000,
  0b01010,
  0b11111,
  0b11111,
  0b01110,
  0b00100,
  0b00000,
  0b00000
};

char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};

int luce;
const int Pin_fotoresistenza = 34;

int LED_blu = 2;
int LED_viola = 19;

const int Buzzer = 4;
int freq = 2000;
int channel = 4;
int resolution = 8;
  
const int BUTTON_PIN = 27;       // the number of the pushbutton pin


int lastState = LOW;  // the previous state from the input pin
int currentState; 

void setup(){
  Serial.begin(57600);
  myservo.setPeriodHertz(50);    // standard 50 hz servo
  myservo.attach(14);

  ledcSetup(channel, freq, resolution);
  ledcAttachPin(Buzzer, channel);
  
    pinMode(BUTTON_PIN, INPUT_PULLUP);
    pinMode(LED_blu, OUTPUT);
    pinMode(LED_viola, OUTPUT);
    digitalWrite(LED_blu, LOW);
    digitalWrite(LED_viola, HIGH);
  
 
  #ifndef ESP8266
  while (!Serial); // wait for serial port to connect. Needed for native USB
  #endif

  pinMode(Pin_fotoresistenza, INPUT);  
  lcd.begin(20,4);
  lcd.init();             // initialize LCD
  lcd.backlight();        // active lighting
  lcd.setCursor(5, 0);
  lcd.print("Benvenuto! ");
 
  lcd.setCursor(8,1);
  lcd.print("sono");
 
  lcd.setCursor(6,2);
  lcd.print("Billiot");
  
  lcd.createChar(0, customChar); // create a new custom character
  lcd.setCursor(14, 2); // move cursor to (2, 0)
  lcd.write((byte)0);  // print the custom char at (2, 0)
  
  delay(6000);
  lcd.clear();
   if (! rtc.begin()) {
    Serial.println("Couldn't find RTC");
    Serial.flush();
    while (1) delay(10);
  }

  if (rtc.lostPower()) {
    Serial.println("RTC lost power, let's set the time!");
    // When time needs to be set on a new device, or after a power loss, the
    // following line sets the RTC to the date & time this sketch was compiled
    //rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
    // This line sets the RTC with an explicit date & time, for example to set
    // Marzo 18, 2022 at 16:27:00 pm you would call:
    //rtc.adjust(DateTime(2022, 3, 18, 16, 30, 0));
  }

}

void loop(){
  
  DateTime now = rtc.now();
  
  digitalWrite(LED_blu, LOW);
  digitalWrite(LED_viola, HIGH);
  currentState = digitalRead(BUTTON_PIN);

  if(currentState == HIGH){
    Serial.println("Tasto premuto");
    lcd.setCursor(5, 2);
    lcd.print("Promemoria");
    lcd.setCursor(6, 3);
    lcd.print("attivato");
    delay(2000);
      digitalWrite(LED_blu, LOW);
      ledcWriteTone(channel, 2000);
      delay(500); 
      digitalWrite(LED_blu, HIGH);   
      ledcWriteTone(channel, 3000);
      delay(1000);
      
      digitalWrite(LED_blu, HIGH);
      digitalWrite(LED_blu, LOW);
      ledcWriteTone(channel, 0);
      delay(1000); 
      
      erogazione();
    }
    
  
  luce = analogRead(Pin_fotoresistenza);
  if (luce < 1200){
    Serial.println("Bicchiere inserito");    
    lcd.clear();}

    
    while(luce > 1300){ 
      lcd.clear();
      luce = analogRead(Pin_fotoresistenza);
      lcd.setCursor(6, 1);
      lcd.print("Inserisci"); 
      lcd.setCursor(6,2);
      lcd.print("bicchiere");
      ledcWriteTone(channel, 2000);
      delay(500);    
      ledcWriteTone(channel, 3000);
      delay(250);
      ledcWriteTone(channel, 0);
      delay(500);       
    }
    
    

    Serial.print(now.year(), DEC);    
    lcd.setCursor(0, 0);
    lcd.print(now.year(), DEC); 
    
    Serial.print('/');
    lcd.setCursor(4, 0);
    lcd.print('/');
    
    Serial.print(now.month(), DEC);    
    lcd.setCursor(5, 0);
    lcd.print(now.month(), DEC);
    
    Serial.print('/');    
    lcd.setCursor(7, 0);
    lcd.print('/');
    
    Serial.print(now.day(), DEC);

    lcd.setCursor(8, 0);
    lcd.print(now.day(), DEC);
    
    Serial.print(" (");
    Serial.print(daysOfTheWeek[now.dayOfTheWeek()]);
    Serial.print(") ");
    lcd.setCursor(11, 0);
    lcd.print(daysOfTheWeek[now.dayOfTheWeek()]);

    
    Serial.print(now.hour(), DEC);
    lcd.setCursor(1, 1);
    lcd.print(now.hour(), DEC);
    
    Serial.print(':');
    lcd.setCursor(3, 1);
    lcd.print(':');
    
    Serial.print(now.minute(), DEC);
    if((now.minute()) <= 9){
    lcd.setCursor(4, 1);
    lcd.print('0');    
    lcd.print(now.minute(), DEC);
    }else{
    lcd.setCursor(4, 1);   
    lcd.print(now.minute(), DEC);
     }
    Serial.print(':');
    lcd.setCursor(6, 1);
    lcd.print(':');
    
    Serial.print(now.second(), DEC);
    lcd.setCursor(7, 1);
    lcd.print(now.second(), DEC);
    
    Serial.println();
    Serial.print("Temperature: ");
    lcd.setCursor(11, 1);
    lcd.print("T="); 
    Serial.print(rtc.getTemperature());
    lcd.print(rtc.getTemperature());
    lcd.print(" C"); 
    Serial.println(" C");

    Serial.println();
    delay(500);
  
}

void erogazione(){
  myservo.setPeriodHertz(50);
  delay(5000);  
  digitalWrite(LED_blu, HIGH);
  digitalWrite(LED_viola, LOW);
  //85 degrees -> pill falls 180 degrees instead -> pill in the holder
   
   delay(1000);            
   myservo.write(85);
   delay(1000);
   myservo.write(180); 
   delay(500);
  
    lcd.clear();
    lcd.setCursor(6, 1);
    lcd.print("Pillola");
    lcd.setCursor(6, 2);
    lcd.print("erogata");
    ledcWriteTone(channel, 2000);
    delay(500);    
    ledcWriteTone(channel, 1500);
    delay(250);
    ledcWriteTone(channel, 0);        
    delay(4000);
    
}
