//sudeldeckdudel3
#include <Servo.h>   //servo library
#include "Arduino.h"   //Arduino library
#include "DFRobotDFPlayerMini.h"   //Arduino library
#include "Wire.h" // For I2C (2 Draht Display z.b.)
#include "LCD.h" // For LCD
#include "LiquidCrystal_I2C.h" // für Display ansich die 2 Draht logic






// ----------------------------------------
// Ab hier ändern möglich :)
// ----------------------------------------

int trigPin = 5;    //Hallsensor TRIG Pin
int echoPin = 6;    //Hallsensor ECHO Pin
int servoPin = 7;   //Servo Steuer Pin
int led_orange= 9;    // ZU Status LED wenn verzögerung
int led_red= 10;    // ZU Status LED wenn AUF
int led_green= 11;    // AUF Status LED wenn ZU
int mp3_rx= 12;    // GRÜN 
int mp3_tx= 13;    // GELB

int startaufzustand=0; // wie ist der Zustand beim Arduinostart
int max_auf_zustand=150;// wie ist der offen Winkel
int max_zu_zustand=0;// wie ist der zu Winkel ( normal 0 )
int entfernungsparameter=50;// anspechabstand fürs davorstehen
int pause_vor_zumachen = 5000;//wie lange soll ich warten vor "ZU"
int sound_volume=30;  //Set volume value. From 0 to 30

int DFPLAYER_PLUGGEDIN = 0; // ist der DFPlayer angeschlossen ?

// ----------------------------------------
// Ab hier nichts mehr ändern
// ----------------------------------------
/* Display */
LiquidCrystal_I2C lcd(0x27, 20, 4);
int randNumber = random(1, 99);


//Serial.println(randNumber);
//Set the pins on the I2C chip used for LCD connections
//ADDR,EN,R/W,RS,D4,D5,D6,D7
//LiquidCrystal_I2C lcd(0x27,2,1,0,4,5,6,7); // 0x27 is the default I2C bus address of the backpack-see article


Servo servo;
#if (defined(ARDUINO_AVR_UNO) || defined(ESP8266))   // Using a soft serial port
  #include <SoftwareSerial.h>
  SoftwareSerial softSerial(/*rx =*/mp3_rx, /*tx =*/mp3_tx);
  #define FPSerial softSerial
#else
  #define FPSerial Serial1
#endif
DFRobotDFPlayerMini myDFPlayer;
void printDetail(uint8_t type, int value);

long duration, dist, average;   
long aver[3];   //array for average
void measure() {
  // der eigentliche Messvorgang, welcher in der Variable dist den Abstand zurückgibt
    digitalWrite(trigPin, LOW);
    delayMicroseconds(5);
    digitalWrite(trigPin, HIGH);
    delayMicroseconds(15);
    digitalWrite(trigPin, LOW);
    pinMode(echoPin, INPUT);
    duration = pulseIn(echoPin, HIGH);
    dist = (duration/2) / 29.1;    //ungefähre Entfernung, da diese aber einen "hin und rückweg" hat, wird sie durch 2 geteilt ;)
}

void loop() { 

if ( DFPLAYER_PLUGGEDIN=1 ) {//wenn Entfernung < entfernungsparameter dann auf, sonst zu
      if (myDFPlayer.available()) {
    
      }else{      
          
      }
  }else{      
      
  }
  













  for (int i=0;i<=2;i++) {   //ermittlung der durchschnittlichen Entfernung bei 2 Messungen
    measure();               
    aver[i]=dist;            // die Werte werden im Array zwischengespeichert
    delay(10);              //kurze 10 Millisekunden wartezeit
  }
  dist=(aver[0]+aver[1]+aver[2])/3;// wert der 3 Messungen wird addiert und durch 3 geteilt um Durchschnitt zu bekommen
  if ( dist<entfernungsparameter ) {//wenn Entfernung < entfernungsparameter dann auf, sonst zu
      servo_auf();
  }else{      
      servo_zu();
  }
  static unsigned long timer = millis();
    if (millis() - timer > 3000) {
      timer = millis();
    Serial.println(F("play warten."));
      myDFPlayer.playMp3Folder(99); //play specific mp3 in SD:/MP3/0001.mp3; File Name(0~65535)
      delay(1000);
      Serial.println(F("fertig mit warten"));
    }
    if (myDFPlayer.available()) {
      printDetail(myDFPlayer.readType(), myDFPlayer.read()); 
      //Print the detail message from DFPlayer to handle different errors and states.
    }



}








void servo_auf(){
  //was soll gemacht werden, wenn servo auf geht
  digitalWrite(led_orange,LOW);
  digitalWrite(led_red,HIGH);
  digitalWrite(led_green,LOW);
  servo.attach(servoPin);
  delay(1);
  servo.write(max_auf_zustand);
  delay(500);
  servo.detach();
  //Serial.print("auf -- Distanz: ");
  //Serial.print(dist);
  //Serial.print(" -- Klappenwinkel : ");
  //Serial.print(max_auf_zustand);
  //Serial.println();

  //---------SOUND AUF START
Serial.println(F("play offen."));
  myDFPlayer.playMp3Folder(1); //play specific mp3 in SD:/MP3/0001.mp3; File Name(0~65535)
  delay(1000);

Serial.println(F("fertig mit offen"));
//offen ist 1
//zu ist 2
//warten ist 99

  //---------SOUND AUF ENDE
}

void servo_zu(){
  //was soll gemacht werden, wenn servo zu geht
  digitalWrite(led_orange,HIGH);
  digitalWrite(led_red,LOW);
  digitalWrite(led_green,LOW);
  
  delay(pause_vor_zumachen);
  digitalWrite(led_green,HIGH);
  digitalWrite(led_orange,LOW);
  servo.attach(servoPin);
  delay(1);
  servo.write(max_zu_zustand);
  delay(500);
  servo.detach();
  //Serial.print("zu -- Distanz: ");
  //Serial.print(dist);
  //Serial.print(" -- Klappenwinkel : ");
  //Serial.print(max_zu_zustand);
  //Serial.println(); 

  //---------SOUND ZU START
Serial.println(F("play ZU."));
  myDFPlayer.playMp3Folder(2); //play specific mp3 in SD:/MP3/0001.mp3; File Name(0~65535)
  delay(1000);

Serial.println(F("fertig mit ZU"));
//offen ist 1
//zu ist 2
//warten ist 99

  //---------SOUND ZU ENDE
}

void setup() {



lcd.init(); //Im Setup wird der LCD gestartet
lcd.backlight(); //Hintergrundbeleuchtung einschalten (0 schaltet die Beleuchtung aus).
uint8_t bell[8]  = {0x4, 0xe, 0xe, 0xe, 0x1f, 0x0, 0x4};
uint8_t note[8]  = {0x2, 0x3, 0x2, 0xe, 0x1e, 0xc, 0x0};
uint8_t clock[8] = {0x0, 0xe, 0x15, 0x17, 0x11, 0xe, 0x0};
uint8_t heart[8] = {0x0, 0xa, 0x1f, 0x1f, 0xe, 0x4, 0x0};
uint8_t duck[8]  = {0x0, 0xc, 0x1d, 0xf, 0xf, 0x6, 0x0};
uint8_t check[8] = {0x0, 0x1 ,0x3, 0x16, 0x1c, 0x8, 0x0};
uint8_t cross[8] = {0x0, 0x1b, 0xe, 0x4, 0xe, 0x1b, 0x0};
uint8_t retarrow[8] = {	0x1, 0x1, 0x5, 0x9, 0x1f, 0x8, 0x4};
lcd.createChar(0, bell);
	lcd.createChar(1, note);
	lcd.createChar(2, clock);
	lcd.createChar(3, heart);
	lcd.createChar(4, duck);
	lcd.createChar(5, check);
	lcd.createChar(6, cross);
	lcd.createChar(7, retarrow);
	lcd.home();
	








// Set off LCD module
  //lcd.begin (20,4); // 16 x 2 LCD module
  //lcd.setBacklightPin(3,POSITIVE); // BL, BL_POL
  //lcd.setBacklight(HIGH);
  //lcd.print("Hello, World!");
  //lcd.createChar(0, Heart);
  //lcd.createChar(1, Bell);
  //lcd.setCursor(0,0);lcd.createChar(0, Heart);
  //lcd.print("12345678901234567890");
  //lcd.setCursor(0,1);lcd.print("23456789012345678901");
  //lcd.setCursor(0,2);lcd.print("34567890123456789012");
  //lcd.setCursor(0,3);lcd.print("45678901234567890123");


	

	
	lcd.setCursor(0, 0);
	lcd.print("Hello ...");
  lcd.setCursor(0, 1);
  lcd.write(0);lcd.write(1);lcd.write(2);
  lcd.setCursor(0, 0);
  //randNumber = random(0, 7);

  //randNumber = random(1, 99);
//Serial.println(randNumber);

	//lcd.write(randNumber);
	//lcd.print(" Lea! ");
	delay(5000);
	//displayKeyCodes();




























  //---------SOUNDDEFINITION START
  
  #if (defined ESP32)
  FPSerial.begin(9600, SERIAL_8N1, /*rx =*/D3, /*tx =*/D2);
#else
  FPSerial.begin(9600);
#endif

  Serial.begin(115200);


lcd.setCursor(0, 3);
clearLine(3);
lcd.print("Starte DFPlayer");

  Serial.println();
  Serial.println(F("DFPlayer 0.1"));
  Serial.println(F("Initializing DFPlayer ... (it take 3~5 seconds)"));

  if (!myDFPlayer.begin(FPSerial, /*isACK = */true, /*doReset = */true)) {  //Use serial to communicate with mp3.
    lcd.setCursor(0, 2);
    clearLine(2);
    lcd.print("insert SD card!");

lcd.setCursor(0, 3);
    clearLine(3);
    lcd.print("check conn. player");




    Serial.println(F("Unable to begin:"));
    Serial.println(F("1.Please recheck the connection!"));
    Serial.println(F("2.Please insert the SD card!"));
    while(true){
      delay(0); // Code to compatible with ESP8266 watch dog.
    }
  }else{
    delay(0); // Code to compatible with ESP8266 watch dog.
    clearLine(3);
    lcd.print("DFPlayer RDY.");
    Serial.println(F("DFPlayer RDY."));
  }
  











//------------
//lcd.clear();


//if (myDFPlayer.available()) {
 //     lcd.print("1");
//}else{
 //   lcd.print("0");
//}


//if (!myDFPlayer.begin(mySoftwareSerial)) {  //Use softwareSerial to communicate with mp3.

 // Serial.println("ONLINE");
 // }else{
 //Serial.println("OFFLINE");
//}
//if (myDFPlayer.available()) {
//printDetail(myDFPlayer.readType(), myDFPlayer.read()); 
//Serial.print(F("CURRENT VOLUME: ")); //read current volume
//Serial.println(myDFPlayer.readVolume()); //read current volume 
//int fileCounts = 0;
//myDFPlayer.readFileCounts();
//fileCounts = myDFPlayer.readFileCountsInFolder(0);
//Serial.println(fileCounts);
//lcd.write(1);
//lcd.print("Vol:");
//lcd.print(sound_volume);



//**************















  myDFPlayer.volume(sound_volume);  //Set volume value. From 0 to 30
  

 //---------SOUNDDEFINITION ENDE


  digitalWrite(led_orange,LOW);
  digitalWrite(led_red,LOW);
  digitalWrite(led_green,LOW);
  
  servo.attach(servoPin);  
  pinMode(trigPin, OUTPUT);  
  pinMode(echoPin, INPUT);  
  servo.write(0);
  delay(100);
  servo.detach();
  //Serial.print("zu Distanz: ");
  //Serial.print(dist);
  //Serial.print(" Klappenwinkel : ");
  //Serial.print(0);
  //Serial.println(); 
}


void clearLine(int line)
{
  lcd.setCursor(0, line);
  lcd.print(F("                    "));  //nicht abgezählt
  lcd.setCursor(0, line);
}

void displayKeyCodes(void) {
	uint8_t i = 0;

	while (1) {
		lcd.clear();
		lcd.print("Codes 0x");
		lcd.print(i, HEX);
		lcd.print("-0x");
		lcd.print(i + 16, HEX);
		lcd.setCursor(0, 1);

		for (int j = 0; j < 16; j++) {
			lcd.write(i + j);
		}
		i += 16;

		delay(4000);
	}
}


void printDetail(uint8_t type, int value){
  switch (type) {
    case TimeOut:
      Serial.println(F("Time Out!"));
      break;
    case WrongStack:
      Serial.println(F("Stack Wrong!"));
      break;
    case DFPlayerCardInserted:
      Serial.println(F("Card Inserted!"));
      break;
    case DFPlayerCardRemoved:
      Serial.println(F("Card Removed!"));
      break;
    case DFPlayerCardOnline:
      Serial.println(F("Card Online!"));
      break;
    case DFPlayerUSBInserted:
      Serial.println("USB Inserted!");
      break;
    case DFPlayerUSBRemoved:
      Serial.println("USB Removed!");
      break;
    case DFPlayerPlayFinished:
      Serial.print(F("Number:"));
      Serial.print(value);
      Serial.println(F(" Play Finished!"));
      break;
    case DFPlayerError:
      Serial.print(F("DFPlayerError:"));
      switch (value) {
        case Busy:
          Serial.println(F("Card not found"));
          break;
        case Sleeping:
          Serial.println(F("Sleeping"));
          break;
        case SerialWrongStack:
          Serial.println(F("Get Wrong Stack"));
          break;
        case CheckSumNotMatch:
          Serial.println(F("Check Sum Not Match"));
          break;
        case FileIndexOut:
          Serial.println(F("File Index Out of Bound"));
          break;
        case FileMismatch:
          Serial.println(F("Cannot Find File"));
          break;
        case Advertise:
          Serial.println(F("In Advertise"));
          break;
        default:
          break;
      }
      break;
    default:
      break;
  }

}