//this code is not written by us but by 'Krodal' and we edited to make it useable for our greenhouse
// https://www.instructables.com/id/Real-Time-Clock-DS1302/
// http://playground.arduino.cc/Main/DS1302
// DS1302 RTC
// ----------
//
// Open Source / Public Domain
//
// Version 1
//     By arduino.cc user "Krodal".
//     June 2012
//     Using Arduino 1.0.1
// Version 2
//     By arduino.cc user "Krodal"
//     March 2013
//     Using Arduino 1.0.3, 1.5.2
//     The code is no longer compatible with older versions.
//     Added bcd2bin, bin2bcd_h, bin2bcd_l
//     A few minor changes.
//
//
// Documentation: datasheet
// 
// The DS1302 uses a 3-wire interface: 
//    - bidirectional data.
//    - clock
//    - chip select
// It is not I2C, not OneWire, and not SPI.
// So the standard libraries can not be used.
// Even the shiftOut() function is not used, since it
// could be too fast (it might be slow enough, 
// but that's not certain).
//
// I wrote my own interface code according to the datasheet.
// Any three pins of the Arduino can be used.
//   See the first defines below this comment, 
//   to set your own pins.
//
// The "Chip Enable" pin was called "/Reset" before.
//
// The chip has internal pull-down registers.
// This keeps the chip disabled, even if the pins of 
// the Arduino are floating.
//
//
// Range
// -----
//      seconds : 00-59
//      minutes : 00-59
//      hour    : 1-12 or 0-23
//      date    : 1-31
//      month   : 1-12
//      day     : 1-7
//      year    : 00-99
//
//
// Burst mode
// ----------
// In burst mode, all the clock data is read at once.
// This is to prevent a rollover of a digit during reading.
// The read data is from an internal buffer.
//
// The burst registers are commands, rather than addresses.
// Clock Data Read in Burst Mode
//    Start by writing 0xBF (as the address), 
//    after that: read clock data
// Clock Data Write in Burst Mode
//    Start by writing 0xBE (as the address), 
//    after that: write clock data
// Ram Data Read in Burst Mode
//    Start by writing 0xFF (as the address), 
//    after that: read ram data
// Ram Data Write in Burst Mode
//    Start by writing 0xFE (as the address), 
//    after that: write ram data
//
//
// Ram
// ---
// The DS1302 has 31 of ram, which can be used to store data.
// The contents will be lost if the Arduino is off, 
// and the backup battery gets empty.
// It is better to store data in the EEPROM of the Arduino.
// The burst read or burst write for ram is not implemented 
// in this code.
//
//
// Trickle charge
// --------------
// The DS1302 has a build-in trickle charger.
// That can be used for example with a lithium battery 
// or a supercap.
// Using the trickle charger has not been implemented 
// in this code.
//


// Set your own pins with these defines !
#define DS1302_SCLK_PIN   10    // Arduino pin for the Serial Clock
#define DS1302_IO_PIN     9    // Arduino pin for the Data I/O
#define DS1302_CE_PIN     8    // Arduino pin for the Chip Enable


// Macros to convert the bcd values of the registers to normal
// integer variables.
// The code uses separate variables for the high byte and the low byte
// of the bcd, so these macros handle both bytes separately.
#define bcd2bin(h,l)    (((h)*10) + (l))
#define bin2bcd_h(x)   ((x)/10)
#define bin2bcd_l(x)    ((x)%10)


// Register names.
// Since the highest bit is always '1', 
// the registers start at 0x80
// If the register is read, the lowest bit should be '1'.
#define DS1302_SECONDS           0x80
#define DS1302_MINUTES           0x82
#define DS1302_HOURS             0x84
#define DS1302_DATE              0x86
#define DS1302_MONTH             0x88
#define DS1302_DAY               0x8A
#define DS1302_YEAR              0x8C
#define DS1302_ENABLE            0x8E
#define DS1302_TRICKLE           0x90
#define DS1302_CLOCK_BURST       0xBE
#define DS1302_CLOCK_BURST_WRITE 0xBE
#define DS1302_CLOCK_BURST_READ  0xBF
#define DS1302_RAMSTART          0xC0
#define DS1302_RAMEND            0xFC
#define DS1302_RAM_BURST         0xFE
#define DS1302_RAM_BURST_WRITE   0xFE
#define DS1302_RAM_BURST_READ    0xFF



// Defines for the bits, to be able to change 
// between bit number and binary definition.
// By using the bit number, using the DS1302 
// is like programming an AVR microcontroller.
// But instead of using "(1<<X)", or "_BV(X)", 
// the Arduino "bit(X)" is used.
#define DS1302_D0 0
#define DS1302_D1 1
#define DS1302_D2 2
#define DS1302_D3 3
#define DS1302_D4 4
#define DS1302_D5 5
#define DS1302_D6 6
#define DS1302_D7 7


// Bit for reading (bit in address)
#define DS1302_READBIT DS1302_D0 // READBIT=1: read instruction

// Bit for clock (0) or ram (1) area, 
// called R/C-bit (bit in address)
#define DS1302_RC DS1302_D6

// Seconds Register
#define DS1302_CH DS1302_D7   // 1 = Clock Halt, 0 = start

// Hour Register
#define DS1302_AM_PM DS1302_D5 // 0 = AM, 1 = PM
#define DS1302_12_24 DS1302_D7 // 0 = 24 hour, 1 = 12 hour

// Enable Register
#define DS1302_WP DS1302_D7   // 1 = Write Protect, 0 = enabled

// Trickle Register
#define DS1302_ROUT0 DS1302_D0
#define DS1302_ROUT1 DS1302_D1
#define DS1302_DS0   DS1302_D2
#define DS1302_DS1   DS1302_D2
#define DS1302_TCS0  DS1302_D4
#define DS1302_TCS1  DS1302_D5
#define DS1302_TCS2  DS1302_D6
#define DS1302_TCS3  DS1302_D7


// Structure for the first 8 registers.
// These 8 bytes can be read at once with 
// the 'clock burst' command.
// Note that this structure contains an anonymous union.
// It might cause a problem on other compilers.
typedef struct ds1302_struct
{
  uint8_t Seconds:4;      // low decimal digit 0-9
  uint8_t Seconds10:3;    // high decimal digit 0-5
  uint8_t CH:1;           // CH = Clock Halt
  uint8_t Minutes:4;
  uint8_t Minutes10:3;
  uint8_t reserved1:1;
  union
  {
    struct
    {
      uint8_t Hour:4;
      uint8_t Hour10:2;
      uint8_t reserved2:1;
      uint8_t hour_12_24:1; // 0 for 24 hour format
    } h24;
    struct
    {
      uint8_t Hour:4;
      uint8_t Hour10:1;
      uint8_t AM_PM:1;      // 0 for AM, 1 for PM
      uint8_t reserved2:1;
      uint8_t hour_12_24:1; // 1 for 12 hour format
    } h12;
  };
  uint8_t Date:4;           // Day of month, 1 = first day
  uint8_t Date10:2;
  uint8_t reserved3:2;
  uint8_t Month:4;          // Month, 1 = January
  uint8_t Month10:1;
  uint8_t reserved4:3;
  uint8_t Day:3;            // Day of week, 1 = first day (any day)
  uint8_t reserved5:5;
  uint8_t Year:4;           // Year, 0 = year 2000
  uint8_t Year10:4;
  uint8_t reserved6:7;
  uint8_t WP:1;             // WP = Write Protect
};
//---LiquidCrystalDisplay---
#include <LiquidCrystal.h>                                  //include the LCD library
const int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 = 2; //define the pins connections to the arduino
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);                  //declare the pin names for the library 
//---InfraredRemote---
#include "IRLibAll.h"                                       //include IR library for infrared function
IRrecvPCI myReceiver(20);                                   //Create a receiver object to listen on pin 20
IRdecode myDecoder;                                         //Create a decoder obj
//---Servo---
#include <Servo.h>                                  //include the servo library
Servo servo1;                                       //declare the first servo a name
Servo servo2;                                       //declare the second servo a name
const int servoVoltage = 17;                        //power-supply connected to pin 17 of the arduinoboard and pin 1 of the 5v h-bridge
int angle1;                                         //declare a variable for servo 1
int angle2;                                         //declare a variable for servo 2
bool alreadyOpenedWindows = false;                   //boolean to check whether the windows are allready closed or open
bool actuaterIsOn = false;                          //boolean to check whether the actuater is allraedy on of off
bool fanIsOn = false;                               //boolean to check whether the actuater is allraedy on of off
bool ledstripIsOn = false;                          //boolean to check whether the ledstrip is allready on or off
bool heaterIsOn = false;                            //boolean to check whether the heater is allready on or off

//---All-OUTPUT-PINS---
//---5-Volt---
const int pinServo = 17;      //the power pin of the servos
const int pinWaterSensors = 16;      //the power pin of the waterlevel & moisture sernosr
const int pinActuater = 15;   //the pin to activate the actuator
const int pinFan = 14;        //the power pin for the fan behind the heater
//---12-Volt---
const int pinLedstrip = 23;   //the power pin for the ledstrip
const int pinHeater = 24;     //the power pin for the heater
//---All-Sensors-pins/variables--------------------------------------------------------------------
//---moisture---
const int pinSoilMoisture0 = A10;                   //declare wich pin on the arduino board
const int pinSoilMoisture1 = A11;                   //declare wich pin on the arduino board
//---leakage---
const int pinWaterdrop = A12;                       //declare wich pin on the arduino board
//---temperature---
const int pinHeaterTemp = A8;                       //NTC sensorpin 5v --> 10k ohm --> A_ & NTC --> GND
const int pinHouseTemp = A9;                        //NTC sensorpin 5v --> 10k ohm --> A_ & NTC --> GND
//---light---
const int ldr0 = A5;                                // goes between GND-->10k resistor-->A12<--ldr<--5v
const int ldr1 = A6;                                // goes between GND-->10k resistor-->A12<--ldr<--5v
int lightIndex;                                     //the light index ([0=Dark],[1=Dim],[2=Light],[3=Bright],[4=Very Bright])
//---waterlevel---
const int pinWaterlevel[5] = {A0, A1, A2, A3, A4};  //declare the pins to read the watertank

//---Time---variables------------------------------------------------------------------------------
int timeSettingsMenu = 4;       //this value is for the settings menu controled by IR
int setValueTime = 0;           //this value is used to show edited value of the time controled by IR
//---clock---
int fiveMinHeater = 0;
int previousHour = 25;              //this varible[integer] is used to check if there passed an hour by making it 25 it will run for the first time.
int previousQuarter = 0;            //this varible[integer] is used to check if there passed a quarter
//---TimeSettings---
int Ssec = 0;               //this varible[integer] is for the seconds  
int Smin = 1;              //this varible[integer] is for the minutes
int Shour = 1;             //this varible[integer] is for the hours
int Sdayofweek = 1;         //this varible[integer] is for the day of the week
int Sdate = 1;              //this varible[integer] is for the date
int Smonth = 1;            //this varible[integer] is for the month
int Syear = 2018;           //this varible[integer] is for the year

//---WIFI---------------------------------------------------------------------
String dataFromESP;       //is used to store the tabel for the ESP

//---Memory-------------------------------------------------------------------
int MRsoilmoisture;
int MRminute;
int MRmenu;
//---Symbols------------------------
byte charHeater[8] = {    //symbol of the heater
  B01001,
  B10010,
  B01001,
  B10010,
  B00000,
  B00000,
  B11111,
  B10101
  };
byte charWatertank[8] = { //symbol of the watertank
  B11111,
  B10001,
  B10001,
  B10001,
  B11111,
  B11111,
  B11111,
  B01110
};
byte charTemperature[8] = { //symbol of the temperature
  B01110,
  B01010,
  B01010,
  B01010,
  B01110,
  B11111,
  B11111,
  B01110
};
byte charSoilmoisture[] = { //symbol of the soilmoisture
  B00100,
  B00100,
  B01010,
  B01010,
  B10001,
  B10001,
  B10001,
  B01110
};

void setup()  {

  //XXX-------------------------------------------------------------------------------------------------------move lcd and serial etc.... to an function and cal that function
  lcd.begin(20,4);              //define that the display has 4 rows and 20 digits
  Serial.begin(9600);           //define the baundrate for serial comunication with the laptop
  Serial1.begin(115200);        //define the baundrate for serial comunication with the ESP
  sensorSetup();                //run a function to declare al input/output pins
  myReceiver.enableIRIn();      //open the IR port
  SerialTime();                 //send the time on the greenhouse to the laptop by serial comunication                            ---optional not necessery 
}

void sensorSetup()  {
  pinMode(pinHeaterTemp, INPUT);      //declare NTC sensor pin as input for temperature
  pinMode(pinHouseTemp, INPUT);       //declare NTC sensor pin as input for temperature
  pinMode(ldr0,INPUT);                //declare LDR sensor pin as input for light-index 
  pinMode(ldr1,INPUT);                //declare LDR sensor pin as input for light-index
  pinMode(pinSoilMoisture0,INPUT);    //declare moisture sensor pin as input for soil-moisture
  pinMode(pinSoilMoisture1,INPUT);    //declare moisture sensor pin as input for soil-moisture
  pinMode(pinWaterdrop, INPUT);       //declare waterdrop sensor pin as input for leakage
  for (int i=0; i<5; i++)  {          //run a for loop 5 times to declare all the five pins
    pinMode(pinWaterlevel[i],INPUT);  //declare waterlevel sensor pins as input for waterlevel in the watertank
  }
  pinMode(pinServo,OUTPUT);           //declare the servo pin as output
  pinMode(pinWaterSensors,OUTPUT);    //declare the waterSensors pin as output
  pinMode(pinActuater,OUTPUT);        //declare the Actuator pin as output
  pinMode(pinFan,OUTPUT);             //declare the Fan pin as output
  pinMode(pinHeater,OUTPUT);          //declare the Heater pin as output
  pinMode(pinLedstrip,OUTPUT);        //declare the Ledstrip pin as output
  digitalWrite(pinHeater, HIGH);      // trun heater off otherwise the heater would automatically trun on
  digitalWrite(pinLedstrip, HIGH);    // trun ledstrip off otherwise the ledstrip would automatically trun on
  servo1.attach(28);                  //servo 1 connected to pin 28
  servo2.attach (29);                 //servo 2 connected to pin 29
  openWindows(true);                  //close the windows
  previousQuarter = MINUTE() - 15;    //set the Quarter correctly
  lcd.createChar(1, charTemperature); //temperature symbol
  lcd.createChar(2, charHeater);      //heater symbol
  lcd.createChar(3, charSoilmoisture);//water drop symbol
  lcd.createChar(4, charWatertank);   //watertank symbol
  MRsoilmoisture = soilMoisture();    //read soilmostur for the first time
}

void loop() {
    if (MRmenu != timeSettingsMenu || MRminute != MINUTE()) {   //check if the display needs to be refresed
      showMenuTimeSettings();         //show menu
      sendESP();                      //update the webserver
      MRmenu = timeSettingsMenu;      //reset memory
      MRminute = MINUTE();            //reset memory
    }
    settingsMenuTime();       //change menu & value of edited time
    calulator();              //optimize conditions
    delay(10);                //a tiny delay for proper use
    
}


// make an function that callculate if the ledstip, heater, etc... should trun on or off
void calulator()  {
  if (heaterIsOn) {
    if (fiveMinHeater + 5 < MINUTE()) { //check for 5 minutes
      fiveMinHeater == MINUTE();    //reset 5 minutes
      turnOnFan(true);    //turn fan on every 5 minutes
      delay(5000);        //wait 5 seconds
      turnOnFan(false);   //turn fan off
    }
    else if (fiveMinHeater > 54 && MINUTE() > 59){
      fiveMinHeater == MINUTE();    //reset five minutes
      turnOnFan(true);    //turn fan on every 5 minutes
      delay(5000);        //wait 5 seconds
      turnOnFan(false);   //turn fan off
    }
  }
  
  if (checkHour()) {          //check if we passed an hour
    MRsoilmoisture = soilMoisture();    //read soilMoisture only ones in a hour
    int Gsoil      = MRsoilmoisture;    //declare soilmoisture for actuater
    if (Gsoil < 65) {    //check if moisture if below 65%
      //give some water
      if (!Leakage())  {        //give only water if there is no leakage
        turnOnActuater(true);   //turn actuater on(give water)
        delay(30000);           //wait for 30 seconds
        turnOnActuater(false);  //turn actuater off(stop water)
      }
    }
  }
  if (checkQuarter()) {       //check if we passed a quarter
    Serial.println("quarter");
    int   Glight    = lightSensor();
    float Gtemp     = Temperature("house");
    bool  GLeakage  = Leakage();
    //---Temperature---
    if (Temperature("house") < 18) {
      turnOnHeater(true);  //turn heater on
      openWindows(false);   //close the windows
    }
    else if (Temperature("house") < 25)  {
      turnOnHeater(false);  //turn heater off
      openWindows(false);   //close the windows
    }
    else {
      turnOnHeater(false);  //turn heater off
      openWindows(true);  //open the windows
    }
    //---Light---
    if (HOUR() > 8 && HOUR() < 21)  {   //check if it is day 
      if (Glight < 2) { //below averagedaylight
        turnOnHeater(false);  //turn heater off
        turnOnLedstrip(true); //turn ledstrip on
      }
      else  {  //its daylight
        turnOnLedstrip(false); //trun off
      }
    }
    else  {  //its night
        turnOnLedstrip(false); //trun off
      }
    sendESP();                //send tabel to esp
  }
}

// --------------------------------------------------------
// DS1302_clock_burst_read
//
// This function reads 8 bytes clock data in burst mode
// from the DS1302.
//
// This function may be called as the first function, 
// also the pinMode is set.
//
void DS1302_clock_burst_read( uint8_t *p)
{
  int i;
  _DS1302_start();
  // Instead of the address, 
  // the CLOCK_BURST_READ command is issued
  // the I/O-line is released for the data
  _DS1302_togglewrite( DS1302_CLOCK_BURST_READ, true);  

  for( i=0; i<8; i++)  {
    *p++ = _DS1302_toggleread();
  }
  _DS1302_stop();
}


// --------------------------------------------------------
// DS1302_clock_burst_write
//
// This function writes 8 bytes clock data in burst mode
// to the DS1302.
//
// This function may be called as the first function, 
// also the pinMode is set.
//
void DS1302_clock_burst_write( uint8_t *p)
{
  int i;
  _DS1302_start();

  // Instead of the address, 
  // the CLOCK_BURST_WRITE command is issued.
  // the I/O-line is not released
  _DS1302_togglewrite( DS1302_CLOCK_BURST_WRITE, false);  

  for( i=0; i<8; i++)  {
    // the I/O-line is not released
    _DS1302_togglewrite( *p++, false);  
  }
  _DS1302_stop();
}


// --------------------------------------------------------
// DS1302_read
//
// This function reads a byte from the DS1302 
// (clock or ram).
//
// The address could be like "0x80" or "0x81", 
// the lowest bit is set anyway.
//
// This function may be called as the first function, 
// also the pinMode is set.
//
uint8_t DS1302_read(int address)
{
  uint8_t data;

  // set lowest bit (read bit) in address
  bitSet( address, DS1302_READBIT);  

  _DS1302_start();
  // the I/O-line is released for the data
  _DS1302_togglewrite( address, true);  
  data = _DS1302_toggleread();
  _DS1302_stop();

  return (data);
}


// --------------------------------------------------------
// DS1302_write
//
// This function writes a byte to the DS1302 (clock or ram).
//
// The address could be like "0x80" or "0x81", 
// the lowest bit is cleared anyway.
//
// This function may be called as the first function, 
// also the pinMode is set.
//

void DS1302_write( int address, uint8_t data) {
  // clear lowest bit (read bit) in address
  bitClear( address, DS1302_READBIT);   

  _DS1302_start();
  // don't release the I/O-line
  _DS1302_togglewrite( address, false);
  // don't release the I/O-line
  _DS1302_togglewrite( data, false);
  _DS1302_stop();  
}


// --------------------------------------------------------
// _DS1302_start
//
// A helper function to setup the start condition.
//
// An 'init' function is not used.
// But now the pinMode is set every time.
// That's not a big deal, and it's valid.
// At startup, the pins of the Arduino are high impedance.
// Since the DS1302 has pull-down resistors, 
// the signals are low (inactive) until the DS1302 is used.

void _DS1302_start( void) {
  digitalWrite( DS1302_CE_PIN, LOW); // default, not enabled
  pinMode( DS1302_CE_PIN, OUTPUT);  
  digitalWrite( DS1302_SCLK_PIN, LOW); // default, clock low
  pinMode( DS1302_SCLK_PIN, OUTPUT);
  pinMode( DS1302_IO_PIN, OUTPUT);
  digitalWrite( DS1302_CE_PIN, HIGH); // start the session
  delayMicroseconds( 4);           // tCC = 4us
}

// --------------------------------------------------------
// _DS1302_stop
//
// A helper function to finish the communication.
//
void _DS1302_stop(void)
{
  // Set CE low
  digitalWrite( DS1302_CE_PIN, LOW);
  delayMicroseconds( 4);           // tCWH = 4us
}


// --------------------------------------------------------
// _DS1302_toggleread
//
// A helper function for reading a byte with bit toggle
//
// This function assumes that the SCLK is still high.
//
uint8_t _DS1302_toggleread( void)
{
  uint8_t i, data;

  data = 0;
  for( i = 0; i <= 7; i++)
  {
    // Issue a clock pulse for the next databit.
    // If the 'togglewrite' function was used before 
    // this function, the SCLK is already high.
    digitalWrite( DS1302_SCLK_PIN, HIGH);
    delayMicroseconds( 1);

    // Clock down, data is ready after some time.
    digitalWrite( DS1302_SCLK_PIN, LOW);
    delayMicroseconds( 1);        // tCL=1000ns, tCDD=800ns

    // read bit, and set it in place in 'data' variable
    bitWrite( data, i, digitalRead( DS1302_IO_PIN));
  }
  return( data);
}


// --------------------------------------------------------
// _DS1302_togglewrite
//
// A helper function for writing a byte with bit toggle
//
// The 'release' parameter is for a read after this write.
// It will release the I/O-line and will keep the SCLK high.
//
void _DS1302_togglewrite( uint8_t data, uint8_t release)
{
  int i;

  for( i = 0; i <= 7; i++)
  {
    // set a bit of the data on the I/O-line
    digitalWrite( DS1302_IO_PIN, bitRead(data, i));  
    delayMicroseconds( 1);     // tDC = 200ns

    // clock up, data is read by DS1302
    digitalWrite( DS1302_SCLK_PIN, HIGH);     
    delayMicroseconds( 1);     // tCH = 1000ns, tCDH = 800ns

    if( release && i == 7)
    {
      // If this write is followed by a read, 
      // the I/O-line should be released after 
      // the last bit, before the clock line is made low.
      // This is according the datasheet.
      // I have seen other programs that don't release 
      // the I/O-line at this moment,
      // and that could cause a shortcut spike 
      // on the I/O-line.
      pinMode( DS1302_IO_PIN, INPUT);

      // For Arduino 1.0.3, removing the pull-up is no longer needed.
      // Setting the pin as 'INPUT' will already remove the pull-up.
      // digitalWrite (DS1302_IO, LOW); // remove any pull-up  
    }
    else
    {
      digitalWrite( DS1302_SCLK_PIN, LOW);
      delayMicroseconds( 1);       // tCL=1000ns, tCDD=800ns
    }
  }
}

// -----------------------------------------------------
int WEEKDAY() {                                         //this function will give you the daynuber of the week
  ds1302_struct rtc;                                    //give it the name rtc
  char buffer[80];                                      //buffer s where all the time data will be loaded
  DS1302_clock_burst_read( (uint8_t *) &rtc);           //read all time data
  sprintf( buffer, "%02d",  (rtc.Day));                 //take only the dayofweek data
  int day = atoi(buffer);                               //store data in: "int day"
  return day;                                           //return the data
}
// -----------------------------------------------------
int YEAR() {                                            //this function will give you the year
  ds1302_struct rtc;                                    //give it the name rtc
  char buffer[80];                                      //buffer s where all the time data will be loaded
  DS1302_clock_burst_read( (uint8_t *) &rtc);           //read all time data
  sprintf( buffer, "%02d",  2000 + bcd2bin( rtc.Year10, rtc.Year));//take only the year data
  int year = atoi(buffer);                              //store data in: "int year"
  return year;                                          //return the data
}
// -----------------------------------------------------
int MONTH() {                                           //this function will give you the month
  ds1302_struct rtc;                                    //give it the name rtc
  char buffer[80];                                      //buffer s where all the time data will be loaded
  DS1302_clock_burst_read( (uint8_t *) &rtc);           //read all time data
  sprintf( buffer, "%02d",  bcd2bin( rtc.Month10, rtc.Month));//take only the month data
  int month = atoi(buffer);                             //store data in: "int month"
  return month;                                         //return the data
}
// -----------------------------------------------------
int DATE() {                                            //this function will give you the date
  ds1302_struct rtc;                                    //give it the name rtc
  char buffer[80];                                      //buffer s where all the time data will be loaded
  DS1302_clock_burst_read( (uint8_t *) &rtc);           //read all time data
  sprintf( buffer, "%02d",  bcd2bin( rtc.Date10, rtc.Date));//take only the date data
  int date = atoi(buffer);                              //store data in: "int date"
  return date;                                          //return the data
}
// -----------------------------------------------------
int HOUR() {                                            //this function will give you the hour
  ds1302_struct rtc;                                    //give it the name rtc
  char buffer[80];                                      //buffer s where all the time data will be loaded
  DS1302_clock_burst_read( (uint8_t *) &rtc);           //read all time data
  sprintf( buffer, "%02d",  bcd2bin( rtc.h24.Hour10, rtc.h24.Hour));//take only the hour data
  int hour = atoi(buffer);                              //store data in: "int hour"
  return hour;                                          //return the data
}
// -----------------------------------------------------
int MINUTE() {                                          //this function will give you the minute
  ds1302_struct rtc;                                    //give it the name rtc
  char buffer[80];                                      //buffer s where all the time data will be loaded
  DS1302_clock_burst_read( (uint8_t *) &rtc);           //read all time data
  sprintf( buffer, "%02d",  bcd2bin( rtc.Minutes10, rtc.Minutes));//take only the minute data
  int minute = atoi(buffer);                            //store data in: "int minute"
  return minute;                                        //return the data
}
// -----------------------------------------------------
int SECOND() {                                          //this function will give you the second
  ds1302_struct rtc;                                    //give it the name rtc
  char buffer[80];                                      //buffer s where all the time data will be loaded
  DS1302_clock_burst_read( (uint8_t *) &rtc);           //read all time data
  sprintf( buffer, "%02d",  bcd2bin( rtc.Seconds10, rtc.Seconds));//take only the seconds data
  int seconds = atoi(buffer);                           //store data in: "int seconds"
  return seconds;                                       //return the data
}
// -----------------------------------------------------
void SerialTime() {                                     //this function will set the all time
  ds1302_struct rtc;                                    //give it the name rtc
  char buffer[80];                                      // the code uses 70 characters.
  DS1302_clock_burst_read( (uint8_t *) &rtc);           // Read all clock data at once (burst mode).

  sprintf( buffer, "Time = %02d:%02d:%02d, ",           //load for print the time on the SerialMonitor
    bcd2bin( rtc.h24.Hour10, rtc.h24.Hour),             //load for print hours
    bcd2bin( rtc.Minutes10, rtc.Minutes),               //load for print minutes
    bcd2bin( rtc.Seconds10, rtc.Seconds));              //load for print seconds
  Serial.print(buffer);                                 //print the time

  sprintf(buffer, "Date(day of month) = %d, Month = %d, " //load for print the date on the SerialMonitor
    "Day(day of week) = %d, Year = %d",                 //load for print the date on the SerialMonitor
    bcd2bin( rtc.Date10, rtc.Date),                     //load for print date
    bcd2bin( rtc.Month10, rtc.Month),                   //load for print month
    rtc.Day,                                            //load for print day of week
    2000 + bcd2bin( rtc.Year10, rtc.Year));             //load for print month
  Serial.println( buffer);                              //print the date

}
// -----------------------------------------------------
void LoadTime() {                                       //this function will load the time to the time in stettings for Reset
  //[S] before variable means settings
  Ssec = SECOND();                                      //run void[second] to set seconds
  Smin = MINUTE();                                      //run void[minute] to set minutes
  Shour = HOUR();                                       //run void[hour] to set hour
  Sdayofweek = WEEKDAY();                               //run void[weekday] to set day of week
  Sdate = DATE();                                       //run void[date] to set date
  Smonth = MONTH();                                     //run void[month] to set month
  Syear = YEAR();                                       //run void[year] to set year
}
// -----------------------------------------------------
void SetTime(int second, int minute, int hour)  {       //this function will set[hour|minute|second]
  LoadTime();                                           //run void[LoadTime] set the time of now in the settings
  //[S] before variable means settings
  Ssec = second;                                        //set variable seconds
  Smin = minute;                                        //set variable minutes
  Shour = hour;                                         //set variable hours
  TimeReset(Ssec,Smin,Shour,Sdayofweek,Sdate,Smonth,Syear);//run the void[Time Setup] to set the time
}
// -----------------------------------------------------
void SetDate(int day, int date, int month, int year)  { //this function will set[year|month|date|dayofweek]
  LoadTime();                                           //run void[LoadTime] to avoid wrong time
  //[S] before variable means settings
  Sdayofweek = day;                                     //set variable dayofweek
  Sdate = date;                                         //set variable date
  Smonth = month;                                       //set variable month
  Syear = year;                                         //set variable year
  TimeReset(Ssec,Smin,Shour,Sdayofweek,Sdate,Smonth,Syear);//run the void[Time Setup] to set the time
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void TimeReset(int Qsec,int Qmin,int Qhour,int Qday,int Qdate,int Qmonth, int Qyear)  {
  ds1302_struct rtc;

  Serial.println(F("DS1302 Real Time Clock"));
  Serial.println(F("Version 1, March 2018"));
  Serial.println(F("Edited by Ximoo"));

  // Start by clearing the Write Protect bit
  // Otherwise the clock data cannot be written
  // The whole register is written, 
  // but the WP-bit is the only bit in that register.
  DS1302_write (DS1302_ENABLE, 0);

  // Disable Trickle Charger.
  DS1302_write (DS1302_TRICKLE, 0x00);

// Remove the next define, 
// after the right date and time are set.
#define SET_DATE_TIME_JUST_ONCE
#ifdef SET_DATE_TIME_JUST_ONCE  

  // Fill these variables with the date and time.
  int seconds, minutes, hours, dayofweek, dayofmonth, month, year;

  // Example for april 15, 2013, 10:08, monday is 2nd day of Week.
  // Set your own time and date in these variables.
  //[S] before variable means settings
  seconds    = Qsec;                                              
  minutes    = Qmin;
  hours      = Qhour;
  dayofweek  = Qday;  // Day of week, any day can be first, counts 1...7
  dayofmonth = Qdate; // Day of month, 1...31
  month      = Qmonth;  // month 1...12
  year       = Qyear;


  // Set a time and date
  // This also clears the CH (Clock Halt) bit, 
  // to start the clock.

  // Fill the structure with zeros to make 
  // any unused bits zero
  memset ((char *) &rtc, 0, sizeof(rtc));

  rtc.Seconds    = bin2bcd_l( seconds);
  rtc.Seconds10  = bin2bcd_h( seconds);
  rtc.CH         = 0;      // 1 for Clock Halt, 0 to run;
  rtc.Minutes    = bin2bcd_l( minutes);
  rtc.Minutes10  = bin2bcd_h( minutes);
  // To use the 12 hour format,
  // use it like these four lines:
  //    rtc.h12.Hour   = bin2bcd_l( hours);
  //    rtc.h12.Hour10 = bin2bcd_h( hours);
  //    rtc.h12.AM_PM  = 0;     // AM = 0
  //    rtc.h12.hour_12_24 = 1; // 1 for 24 hour format
  rtc.h24.Hour   = bin2bcd_l( hours);
  rtc.h24.Hour10 = bin2bcd_h( hours);
  rtc.h24.hour_12_24 = 0; // 0 for 24 hour format
  rtc.Date       = bin2bcd_l( dayofmonth);
  rtc.Date10     = bin2bcd_h( dayofmonth);
  rtc.Month      = bin2bcd_l( month);
  rtc.Month10    = bin2bcd_h( month);
  rtc.Day        = dayofweek;
  rtc.Year       = bin2bcd_l( year - 2000);
  rtc.Year10     = bin2bcd_h( year - 2000);
  rtc.WP = 0;  

  // Write all clock data at once (burst mode).
  DS1302_clock_burst_write( (uint8_t *) &rtc);
#endif
}

bool checkHour()  {       //this function will check if there past a hour (time to read the sensors?)
  if (HOUR() != previousHour) {   //if the hour is diffrent by the previous check
    previousHour = HOUR();        //set the current time for for the next check
    return true;                  //retrun that we are in a new hour  [true]
  }
  else  {                         //if the hour is the same by the previous check
    return false;                 //return that we are in the same hour [false]
  }
}

bool checkQuarter()  {       //this function will check if there past a hour (time to read the sensors?)
  
  if (MINUTE() > previousQuarter) {         //check for a new quarter
    if (previousQuarter < 15) {             //check for a valid quarter
      if (MINUTE() < 45) {                  //it is a new quarter
        previousQuarter = MINUTE() + 15;          //set the current time for for the next check
        if (previousQuarter >= 60)  {       //check if minute is valid below 60
          previousQuarter -= 60;            //if not valid - 60 
        }
        return true;                        //end of function return that we have a new quarter
      }  
      else  {                               //it is not a new quarter
        return false;                       //end ot function return that we dont have a new quarter
      }
    }
    else  {                                 //it is a new quarter
      previousQuarter = MINUTE() + 15;            //set the current time for for the next check
      if (previousQuarter >= 60)  {         //check if minute is valid below 60
        previousQuarter -= 60;              //if not valid - 60 
      }
      return true;                          //end of function return that we have a new quarter
    }    
  }
  else {                                    //it is not a new quarter
    return false;                           //end ot function return that we dont have a new quarter
  }
}

void LCD(int linenumber, int digit, String text){ //new function - declare 3 variables
  lcd.setCursor(digit, linenumber); //set the corsor on the right location
  lcd.print(text); //print the given text
}

String dayOfWeek(int dayNumber)  {    //this function will retrun the day of week in the first 3 letters String[text]
  String daychar;
    switch (dayNumber) {               //calculate wich day it is
    case 1:                            //if day of week is [1]
    daychar = "Sun";                   //day is sunday
    break;
    case 2:                            //if day of week is [2]
    daychar = "Mon";                   //day is monday
    break;
    case 3:                            //if day of week is [3]
    daychar = "Tue";                   //day is tuesday
    break;
    case 4:                            //if day of week is [4]
    daychar = "Wed";                   //day is wednesday
    break;
    case 5:                            //if day of week is [5]
    daychar = "Thu";                   //day is thursday
    break;
    case 6:                            //if day of week is [6]
    daychar = "Fri";                   //day is friday
    break;
    case 7:                            //if day of week is [7]
    daychar = "Sat";                   //day is saterday
    break;
    default:                           //if day of week is not valid
    daychar = "XXX";                   //not a valid day
    break;
  }
  return daychar;
}
void LCDTime()  {                               //function to display the time on the lcd
  String Display;                                     //we use this string to store all the text together before we display it
  String daychar = dayOfWeek(WEEKDAY());              //run function to get day of week in text
  Display = daychar;                                  //preloadLCD day
  Display += " " + zeroCheck(DATE());                 //preloadLCD date
  Display += "-" + zeroCheck(MONTH());                //preloadLCD month
  Display += "-" + String(YEAR());                    //preloadLCD year
  Display += " " + zeroCheck(HOUR());                 //preloadLCD hour
  Display += ":" + zeroCheck(MINUTE());               //preloadLCD minute
  LCD(0,0 ,Display);                                  //set the loaded time on the display
}

String zeroCheck(int value) {             //this function is used to set a 0 before the number so it will always return a two digit number parameter value is the number to check
  String number;                          //create a variable to store the number
  if (value < 10) {                       //check if the number is 1 digit
    number = "0" + String(value);         //add a zero
  }
  else {                                  //allready is a two digit number
    number = String(value);               //make ready for return
  }
  return number;                          //always return a two digit number
}

float Temperature(String which){                        //the parameter which makes claer which temperature sensor you want to measure
  float Vin=5.0;          //[V] the voltage used for the NTC        
  float Rt=10000;         // Resistor t [ohm] the resitor used in this sensor
  float R0=10000;         // value of NTC in T0 [ohm]
  float T0=298.15;        // use T0 in Kelvin [K]
                          // use the datasheet to get this data.
  float T1=273.15;        // [K] in datasheet 0º C
  float T2=373.15;        // [K] in datasheet 100° C
  float RT1=35563;        // [ohms]  resistence in T1
  float RT2=549;          // [ohms]   resistence in T2
                                                            //processing/calculating all data
float  beta=(log(RT1/RT2))/((1/T1)-(1/T2));                      //calc a variable to calculate a variable for the NTC resitor
float  Rinf=R0*exp(-beta/T0);                                    //calc a variable to calculate the resitance in the NTC
float  VoutA=Vin*((float)(analogRead(pinHeaterTemp))/1024.0);    //calc voltage output on the heater NTC
float  VoutB=Vin*((float)(analogRead(pinHouseTemp))/1024.0);     //calc voltage output on the house NTC
float  RoutA=(Rt*VoutA/(Vin-VoutA));                             //calc resistance output on the heater NTC
float  RoutB=(Rt*VoutB/(Vin-VoutB));                             //calc resistance output on the house NTC
float  TempKA=(beta/log(RoutA/Rinf));                            //[K] calc the temperature in the heater NTC
float  TempKB=(beta/log(RoutB/Rinf));                            //[K] calc the temperature in the house NTC
float  TempCA=TempKA-273.15;                                     //[C] convert the temperature of the heater it to Celcius
float  TempCB=TempKB-273.15;                                     //[C] convert it to Celcius
  
  if (which == "house") {           //check wich temperature it needs to return [heater] or [house]
    return TempCB;                  //return the temperatur inside the greenhouse
  }
  else {
    return TempCA;                  //return the temperature around the heater
  }
    
}

int lightSensor() { //return in ([0=Dark],[1=Dim],[2=Light],[3=Bright],[4=Very Bright])
  int lightIndex;                                 // the vaiable for the return ([0=Dark],[1=Dim],[2=Light],[3=Bright],[4=Very Bright])
  int ldr0Value = analogRead(ldr0) - 150;         //the value from the first sensor -150 is a correction cause of sensor failure
  int ldr1Value = analogRead(ldr1);               //the value from the second sensor
  int ldrValue = (ldr0Value + ldr1Value)/2;       //calculate the average of the two sensors
  float resistorValue = 10.0;                     //resitance of the LDR in kilo ohms
  float voltageValue = ldrValue*0.0048828125;   // this calculate the voltage trough the ldr
  int lux0 = 500/(resistorValue*((5-voltageValue)/voltageValue)); // this calculate the lux on the ldr
  if (lux0 < 10) {                              //0-10 is dark
    lightIndex = 0;                             //set lightindex [0=Dark]
  } else if (lux0 < 200) {                      //10-200 = dim
    lightIndex = 1;                             //set lightindex [1=Dim]
  } else if (lux0 < 400) {                      //200-400 = light
    lightIndex = 2;                             //set lightindex [2=Light]
  } else if (lux0 < 700) {                      //400-7000 = bright
    lightIndex = 3;                             //set lightindex [3=Bright]
  } else {                                      //more than 1000 is very bright
    lightIndex = 4;                             //set lightindex [4=Very Bright]
  }
  Serial.print("the light intensity: ");
  Serial.println(lux0);
  return lightIndex; // return ([0=Dark],[1=Dim],[2=Light],[3=Bright],[4=Very Bright])
}

int soilMoisture()  {
  int soilMoistureProcent;          //variable of the soilMoisture in procent
  int soilMoistureAverage;          //variable for the average of the 2 soilmoisture variables
  int soilMoisture0;                // variable for the sensorValue [0],[1]
  int soilMoisture1;                // variable for the sensorValue [0],[1]
  digitalWrite(pinWaterSensors,HIGH);            //turn on the sensor        
  delay(2000);                      //wait two seconds because of start up sensor
  soilMoisture0 = analogRead(pinSoilMoisture0);       //soilMoisture = read the sensorValue --> between 0 - 1023
  soilMoisture1 = analogRead(pinSoilMoisture1);       //soilMoisture = read the sensorValue --> between 0 - 1023
  digitalWrite(pinWaterSensors, LOW);            //turn off the sensor       
  soilMoistureAverage = (soilMoisture0 + soilMoisture1)/2;            //calculate the average the two sensors
  soilMoistureProcent = map(soilMoistureAverage, 0, 1023, 99, 0);     //calculate to moisture procentage
  soilMoistureProcent -= 5;                                          //correction of measurement because of short time period
  return soilMoistureProcent;                                         //return the average procentage of the moisture in the soil
}

bool Leakage()  {                           //this function checks for water leakage and returns a [true] or a [false]
  if (digitalRead(pinWaterdrop)){           //read the waterdrop sensor if there is a leakage
    return true;                            //return that there is no leakage found
  }
  else  {                                   //there is no leakage
    return false;                           //retrun that there is a leakage found
  }
}

int Waterlevel()  {                                                 //this function will measure how many water is la=eft in the tank
  int waterlevel = 0;                                               //create a variable to store the measurement of the sensor
  digitalWrite(pinWaterSensors,HIGH);                               //turn the sensor on                                 
  for (int i=0; i<5; i++)  {                                        //check all levels
    if (analogRead(pinWaterlevel[i]) > 100) {                       //check if we measure water
      waterlevel += 20;                                             //add 20% cause we measured water
    }
  }
  digitalWrite(pinWaterSensors,LOW);                                //turn sensor water off                               
  return waterlevel;                                                //return how much water is in the tank in procentage
}

//---all functions to turn things on or off
void openWindows(bool openWindows){         //this function is used to open and close the windows
  if(!alreadyOpenedWindows && openWindows){        //if windows are closed and has to be open
    digitalWrite(servoVoltage, HIGH);               //give the servo's their power-supply                             
    delay(100);                                     //wait 100 milliseconds                                         
      for (int i = 150; i >= 90; i -= 1){           //close the windows by 1 degree at the time 
        servo1.write(i+33);                       //set servo 1 at the angle of degrees as saved in the variable of servo 1
        servo2.write(i);                       //set servo 2 at the angle of degrees as saved in the variable of servo 2
        delay(25);                                  //wait 25 milliseconds between every added degree
    }                                               //the windows both are closed now
    delay(100);                                     //wait 100 milliseconds                                          
    digitalWrite(servoVoltage, LOW);                //stop the power-supply           
    Serial.println("should be open");                                      
    alreadyOpenedWindows = true;                   //save that we opend the windows
  }
    
  if(alreadyOpenedWindows && !openWindows){        //if the windows are open and has to be closed
    
    digitalWrite(servoVoltage, HIGH);               //give the servo's their power-supply                                                 
    delay(100);                                     //wait 100 milliseconds                                                            
      for (int i = 90; i <= 150; i += 1){           //open the windows by 1 degrees at the time
        servo1.write(i+33);                         //set servo 1 at the angle of degrees as saved in the variable of servo 1
        servo2.write(i);                            //set servo 2 at the angle of degrees as saved in the variable of servo 2
        delay(25);                                  //wait 25 milliseconds between every added degree
      }                                             //the windows both are opened now
    delay(100);                                     //wait 100 milliseconds                                                                  
    digitalWrite(servoVoltage, LOW);                //stop the power-supply 
    
    Serial.println("should be closed");                                          
    alreadyOpenedWindows = false;                    //save that we closed the windows
 }  
}

void turnOnLedstrip(bool trunOn) {  //this function is used to turn the ledstrip on and off
  if (trunOn && !ledstripIsOn) {      //check if the ledstrip is not on and if needs to turn on
    digitalWrite(pinLedstrip,LOW);    //trun ledstrip on
    ledstripIsOn = true;              //remember that the ledstrip is on
  }
  if (!trunOn && ledstripIsOn) {      //check if the ledstrip is on and if needs to turn off
    digitalWrite(pinLedstrip,HIGH);   //trun ledstrip off
    ledstripIsOn = false;             //remember that the ledstrip is off
  }
}

void turnOnHeater(bool trunOn) {  //this function is used to turn the heater on and off
  if (trunOn && !heaterIsOn) {      //check if the heater is not on and if needs to turn on
    digitalWrite(pinHeater,LOW);    //trun heater on
    heaterIsOn = true;              //remember that the heater is on
  }
  if (!trunOn && heaterIsOn) {      //check if the heater is on and if needs to turn off
    digitalWrite(pinHeater,HIGH);   //trun heater off
    heaterIsOn = false;             //remember that the heater is off
  }
}

void turnOnActuater(bool trunOn) {  //this function is used to turn the actuater on and off
  if (trunOn && !actuaterIsOn) {      //check if the actuater is not on and if needs to turn on
    digitalWrite(pinActuater,HIGH);    //trun actuater on
    actuaterIsOn = true;              //remember that the actuater is on
  }
  if (!trunOn && actuaterIsOn) {      //check if the actuater is on and if needs to turn off
    digitalWrite(pinActuater,LOW);   //trun actuater off
    actuaterIsOn = false;             //remember that the actuater is off
  }
}

void turnOnFan(bool trunOn) {  //this function is used to turn the fan on and off
  if (trunOn && !fanIsOn) {      //check if the fan is not on and if needs to turn on
    digitalWrite(pinFan,HIGH);    //trun fan on
    fanIsOn = true;              //remember that the fan is on
  }
  if (!trunOn && fanIsOn) {      //check if the fan is on and if needs to turn off
    digitalWrite(pinFan,LOW);   //trun fan off
    fanIsOn = false;             //remember that the fan is off
  }
}



void settingsMenuTime() {      //this function listens to the IR and will manage trough the menu
  int menu = timeSettingsMenu;      //is used cause of the shorter name
  String IRrecieved = IRRecievedSignal();    //read IR sensor and load the siganl (button)
  if (IRrecieved == "PWR") {  //go to home screen
    timeSettingsMenu =  4;
  }
  
  if (IRrecieved == "*") {    //go to time settings
    timeSettingsMenu = 1;
  }
  
  if (IRrecieved == "DWN") {           //scrol down
    if (menu == 1 || menu == 2 || menu == 10 || menu == 11 || menu == 20 || menu == 21 || menu == 22 || menu == 23 || menu == 100 || menu == 110 || menu == 200 || menu == 210 || menu == 220) {
      timeSettingsMenu++;
    }
  }
  if (IRrecieved == "UP") {           //scrol up
    if (menu == 2 || menu == 3 || menu == 11 || menu == 12 || menu == 21 || menu == 22 || menu == 23 || menu == 24 || menu == 101 || menu == 111 || menu == 201 || menu == 211 || menu == 221) {
      timeSettingsMenu--;
    }
  }
  if (IRrecieved == "SEL"){            
    if (menu == 3) {  //close the settings menu
      //here is shoud close the settings-------------------------------------------------------XX       TO-DO
      timeSettingsMenu = 4;
    }
    
    if (menu == 1 || menu == 2 || menu == 10 || menu == 11 || menu == 20 || menu == 21 || menu == 22 || menu == 23){            //all go forward on the selected sub menu
      timeSettingsMenu *= 10;
    }
    
    if (menu == 12 || menu == 24 || menu == 101 || menu == 111 || menu == 201 || menu == 211 || menu == 221){         //all go back situations
      timeSettingsMenu /= 10;
    }

    if (menu == 100){               //save hour
      setValueTime = constrain(setValueTime, 0 ,60);
      SetTime(SECOND(), MINUTE(), setValueTime);
      timeSettingsMenu = 1;
    }
    if (menu == 110){               //save minute
      setValueTime = constrain(setValueTime, 0 ,60);
      SetTime(0, setValueTime, HOUR());
      timeSettingsMenu = 1;
    }
    if (menu == 200){               //save date
      setValueTime = constrain(setValueTime, 0 ,31);
      SetDate(WEEKDAY(), setValueTime, MONTH(), YEAR());
      timeSettingsMenu = 1;
    }
    if (menu == 210){               //save month
      setValueTime = constrain(setValueTime, 0 ,12);
      SetDate(WEEKDAY(), DATE(), setValueTime, YEAR());
      timeSettingsMenu = 1;
    }
    if (menu == 220){               //save year
      setValueTime = constrain(setValueTime, 0 ,75);
      setValueTime += 2000;
      SetDate(WEEKDAY(), DATE(), MONTH(), setValueTime);
      timeSettingsMenu = 1;
    }
    if (menu == 230){               //save day of week
      setValueTime = constrain(setValueTime, 1 ,7);
      SetDate(setValueTime, DATE(), MONTH(), YEAR());
      timeSettingsMenu = 1;
    }
  setValueTime = 1;
  }
  if (IRrecieved == "PLS") {           //value plus
    if (menu == 100 || menu == 101 || menu == 110 || menu == 111 || menu == 200 || menu == 201 || menu == 210 || menu == 211 || menu == 220 || menu == 221|| menu == 230 || menu == 231) {
      setValueTime++;
      Serial.println("plus");
    }
  }
  if (IRrecieved == "MIN") {           //value plus
    if (menu == 100 || menu == 101 || menu == 110 || menu == 111 || menu == 200 || menu == 201 || menu == 210 || menu == 211 || menu == 220 || menu == 221|| menu == 230 || menu == 231) {
      setValueTime--;
    }
  }  
    
  if (IRrecieved == "MODE") {         //go to home screen
    timeSettingsMenu =  4;
  }
  
  //---Actions---------------------By-IR-remotecontrol---
  //those actions work like an toggle if its on turn it of and if its off turn it off
  if (IRrecieved == "1") {          //check if we recieved the number 1 button of the remotecontrol
    if (alreadyOpenedWindows) {     //check if the windows are open
      openWindows(false);          //close the windows
    }
    else  {                         //the windows are open
      openWindows(true);
    }
  }
  if (IRrecieved == "2") {          //check if we recieved the number 2 button of the remotecontrol  
    if (ledstripIsOn) {             //check if the ledstrip is on
      turnOnLedstrip(false);        //turn it off
    }
    else  {                         //it is not on
      turnOnLedstrip(true);         //turn it on
    }
  }
  if (IRrecieved == "3") {          //check if we recieved the number 3 button of the remotecontrol
    if (fanIsOn) {                  //check if the fan is on
      turnOnFan(false);             //turn it off
    }
    else  {                         //it is not on
      turnOnFan(true);              //turn it on
    }
  }
  if (IRrecieved == "4") {          //check if we recieved the number 4 button of the remotecontrol
    if (heaterIsOn) {               //check if the heater is on
      turnOnHeater(false);          //turn it off
    }
    else  {                         //it is not on
      turnOnHeater(true);           //turn it on
    }
  }
  if (IRrecieved == "5") {          //check if we recieved the number 4 button of the remotecontrol
    sendESP();                      //update the webserver
    showMenuTimeSettings();         //show menu
  }
  
}


void showMenuTimeSettings()  {      //this value is used to switch between the sub menu's of the settings  
  int menu = timeSettingsMenu;  
  String displayYear = String(2000 + setValueTime);
  String value = String(setValueTime); // covert int to string to show on display
  switch(menu)  {
  //-----------------------------------------------//settings menu
  /* example of the display, and how it works. In de following cases, this is all the same!
   *    case Q:
   *      lcd.clear();                  //clear the screen
   *      LCD(X,Y ," Text on row 1");   //print the words "Text on row 1"
   *      LCD(X,Y ,">Text on row 2");   //print the words "Text on row 2" This row is selected
   *      LCD(X,Y ," Text on row 3");   //print the words "Text on row 3" 
   *      LCD(X,Y ," Text on row 4");   //print the words "Text on row 4" 
   *    break;                          //End of this case
   *    
   *    Q stands for which menu has to be displayed on the screen.
   *    X stands for the linenumber the text has to be displayed on.
   *    Y stands for the digit of the linenumber where the text has to be displayed on.
   */
    case 1:
      lcd.clear();              
      LCD(0,0 ," Settings");   
      LCD(1,0 ,">Reset Time");  //selected
      LCD(2,0 ," Reset Date");  
      LCD(3,0 ," Go back");     
    break;                      
  
    case 2:
      lcd.clear();              
      LCD(0,0 ," Settings");    
      LCD(1,0 ," Reset Time");  
      LCD(2,0 ,">Reset Date");  //selected
      LCD(3,0 ," Go back");
    break;
  
    case 3:
      lcd.clear();             
      LCD(0,0 ," Settings");      
      LCD(1,0 ," Reset Time");
      LCD(2,0 ," Reset Date");
      LCD(3,0 ,">Go back");     //selected
    break;

    case 4:                     //home screen
      lcd.clear();
      LCDTime();                //display time
      //lcd.setCursor(digit, linenumber);
      lcd.setCursor(0, 1);   lcd.write(1); //temp
      LCD(1,1," " + String(Temperature("heater")));
      lcd.print((char)223); lcd.print("C");
      lcd.setCursor(10, 1);   lcd.write(2); //heater
      if (heaterIsOn) {  LCD(1,11," ON"); }                      //check if heater is on
      else  { LCD(1,11," OFF"); }
      
      lcd.setCursor(0, 2);   lcd.write(3); //soilmoisture
      LCD(2,1," " + String(MRsoilmoisture) + "%");
      lcd.setCursor(10, 2);   lcd.write(4); //watertank
      LCD(2,11," " + String(Waterlevel()) + "%");
      if (!Leakage()) { LCD(3,0,"Leakage: not found");  }     //check for leakage
      else  { LCD(3,0,"Leakage: WARNING!!!"); }
    break;

  //--------------------------------------Reset time
    case 10:                //sub settings
      lcd.clear();//clear the screen
      LCD(0,0 ," Reset Time");        
      LCD(1,0 ,">Reset Hour");    //selected
      LCD(2,0 ," Reset Minute");
      LCD(3,0 ," Go back");
    break;
  
    case 11:              //sub settings
      lcd.clear();//clear the screen
      LCD(0,0 ," Reset Time");        
      LCD(1,0 ," Reset Hour");
      LCD(2,0 ,">Reset Minute");  //selected
      LCD(3,0 ," Go back");
    break;
  
    case 12:             //sub settings
      lcd.clear();//clear the screen
      LCD(0,0 ," Reset Time");        
      LCD(1,0 ," Reset Hour");
      LCD(2,0 ," Reset Minute");
      LCD(3,0 ,">Go back"); //selected
    break;
  //-----------------------------------//Reset date
    case 20:  //sub settings
      lcd.clear();//clear the screen
      LCD(0,0 ,">Reset Date");  //selected      
      LCD(1,0 ," Reset Month");
      LCD(2,0 ," Reset Year");
      LCD(3,0 ," Reset Day of week");
    break;
  
    case 21:  //sub settings
      lcd.clear();//clear the screen
      LCD(0,0 ," Reset Date");        
      LCD(1,0 ,">Reset Month"); //selected
      LCD(2,0 ," Reset Year");
      LCD(3,0 ," Reset Day of week");
    break;
  
    case 22:  //sub settings
      lcd.clear();//clear the screen
      LCD(0,0 ," Reset Date");        
      LCD(1,0 ," Reset Month");
      LCD(2,0 ,">Reset Year");  //selected
      LCD(3,0 ," Reset Day of week");
    break;
  
    case 23:  //sub settings
      lcd.clear();//clear the screen
      LCD(0,0 ," Reset Date");       
      LCD(1,0 ," Reset Month");
      LCD(2,0 ," Reset Year");
      LCD(3,0 ,">Reset Day of week");   //selected 
    break;
  
    case 24:  //sub settings
      lcd.clear();//clear the screen
      LCD(0,0 ," Reset Month");
      LCD(1,0 ," Reset Year");
      LCD(2,0 ," Reset Day of week");
      LCD(3,0 ,">Go back");   //selected 
    break;
  //-----------------------------------------//change hour
    case 100:  //sub settings           
      lcd.clear();//clear the screen
      LCD(0,0 ," Reset Hour");       
      LCD(1,0 ," Change to: " + value);
      LCD(2,0 ,">Save hour"); //selected 
      LCD(3,0 ," Go back");
    break;
  
    case 101:  //sub settings
      lcd.clear();//clear the screen
      LCD(0,0 ," Reset Hour");        
      LCD(1,0 ," Change to: " + value);
      LCD(2,0 ," Save hour");
      LCD(3,0 ,">Go back"); //selected
    break;
    //------------------------------------//change minute
    case 110:  //sub settings         
      lcd.clear();//clear the screen
      LCD(0,0 ," Reset Minute");      
      LCD(1,0 ," Change to: " + value);
      LCD(2,0 ,">Save minute"); //selected  
      LCD(3,0 ," Go back");
    break;
    
    case 111:  //sub settings
      lcd.clear();//clear the screen
      LCD(0,0 ," Reset Minute");       
      LCD(1,0 ," Change to: " + value);
      LCD(2,0 ," Save minute");
      LCD(3,0 ,">Go back"); //selected
    break;
    
  //--------------------------------------//change date
    case 200:  //sub settings
      lcd.clear();//clear the screen
      LCD(0,0 ," Reset Date");    
      LCD(1,0 ," Change to: " + value);
      LCD(2,0 ,">Save date"); //selected    
      LCD(3,0 ," Go back");
    break;
  
    case 201:  //sub settings
      lcd.clear();//clear the screen
      LCD(0,0 ," Reset Date");    
      LCD(1,0 ," Change to: " + value);
      LCD(2,0 ," Save date");  
      LCD(3,0 ,">Go back"); //selected   
    break;
  //--------------------------------------//change month
    case 210:  //sub settings
      lcd.clear();//clear the screen
      LCD(0,0 ," Reset Month");    
      LCD(1,0 ," Change to: " + value);
      LCD(2,0 ,">Save month"); //selected    
      LCD(3,0 ," Go back");
    break;
  
    case 211:  //sub settings
      lcd.clear();//clear the screen
      LCD(0,0 ," Reset Month");    
      LCD(1,0 ," Change to: " + value);
      LCD(2,0 ," Save month");  
      LCD(3,0 ,">Go back"); //selected   
    break;
  
  //--------------------------------------//change year
  case 220:  //sub settings
      lcd.clear();//clear the screen
      LCD(0,0 ," Reset Year");    
      LCD(1,0 ," Change to: " + displayYear);
      LCD(2,0 ,">Save year"); //selected    
      LCD(3,0 ," Go back");
    break;
  
    case 221:  //sub settings
      lcd.clear();//clear the screen
      LCD(0,0 ," Reset Year");    
      LCD(1,0 ," Change to: " + displayYear);
      LCD(2,0 ," Save year");  
      LCD(3,0 ,">Go back"); //selected   
    break;
  
    //--------------------------------------//change day of week-------------------------------------------------------------------XXX
  case 230:  //sub settings
      lcd.clear();//clear the screen
      LCD(0,0 ," Reset Day");    
      LCD(1,0 ," Change to: " + dayOfWeek(setValueTime));
      LCD(2,0 ,">Save day"); //selected    
      LCD(3,0 ," Go back");
    break;
  
    case 231:  //sub settings
      lcd.clear();//clear the screen
      LCD(0,0 ," Reset Day");    
      LCD(1,0 ," Change to: " + dayOfWeek(setValueTime));
      LCD(2,0 ," Save day");  
      LCD(3,0 ,">Go back"); //selected   
    break;
    //--------------------------------------// if menu went wrong
    default: //if somting went wrong show it on display incl the menu[number]
      lcd.clear();//clear the screen
      LCD(0,0 ," Somthing went wrong");    
      LCD(1,0 ," menu error: " + String(menu));
      LCD(2,0 ," ");  
      LCD(3,0 ," press POWER to exit"); //selected
    break;
  }
}

String IRRecievedSignal() {
  if (myReceiver.getResults()) {                                 //check if there are results
    myDecoder.decode();                                         //Decode it
    String Hexadecimal = "0x" + String(myDecoder.value, HEX);   //converts it to Hexadecimal
    if(Hexadecimal != "0xffffffff" && Hexadecimal != "0x0"){    //don't print these hexadecimal numbers
    Serial.println(IRButtons());                          //print the return
    myReceiver.enableIRIn();
    }
    myReceiver.enableIRIn();
    return IRButtons();
  }
  else {
    return "nothing";
  }
}

String IRButtons(){
  if (myDecoder.protocolNum == NEC) {                           //if NEC-protcol id used
      switch(myDecoder.value) {                                 //look for a match with the recieved code
          case 0x1ce3f00f:                                      //Hexadecimal number of "PWR" button 1
          return "PWR"; break;

          case 0x1ce3b24d:                                      //Hexadecimal number of "AP" button 2
          return "AP"; break;

          case 0x1ce3c837:                                      //Hexadecimal number of "SCN" button 3
          return "SCN"; break;

          case 0x1ce302fd:                                      //Hexadecimal number of "CLK" button 4
          return "CLK"; break;

          case 0x1ce3a857:                                      //Hexadecimal number of "MIN" button 5
          return "MIN"; break;

          case 0x1ce3f20d:                                      //Hexadecimal number of "AF" button 6
          return "AF"; break;

          case 0x1ce308f7:                                      //Hexadecimal number of "DN" button 7
          return "DWN"; break;

          case 0x1ce38877:                                      //Hexadecimal number of "SEL" button 8
          return "SEL"; break;

          case 0x1ce348b7:                                      //Hexadecimal number of "UP" button 9
          return "UP"; break;

          case 0x1ce3728d:                                      //Hexadecimal number of "PLS" button 10
          return "PLS"; break;

          case 0x1ce318e7:                                      //Hexadecimal number of "MODE" button 11
          return "MODE"; break;

          case 0x1ce328d7:                                      //Hexadecimal number of "BND" button 12
          return "BND"; break;

          case 0x1ce3ca35:                                      //Hexadecimal number of "PTY" button 13
          return "PTY"; break;

          case 0x1ce38a75:                                      //Hexadecimal number of "TA" button 14
          return "TA"; break;

          case 0x1ce36897:                                      //Hexadecimal number of "1" button 15
          return "1"; break;

          case 0x1ce3a25d:                                      //Hexadecimal number of "2" button 16
          return "2"; break;

          case 0x1ce36a95:                                      //Hexadecimal number of "3" button 17
          return "3"; break;

          case 0x1ce3ea15:                                      //Hexadecimal number of "4" button 18
          return "4"; break;

          case 0x1ce3708f:                                      //Hexadecimal number of "5" button 19
          return "5"; break;

          case 0x1ce30af5:                                      //Hexadecimal number of "6" button 20
          return "6"; break;

          case 0x1ce3aa55:                                      //Hexadecimal number of "7" button 21
          return "7"; break;

          case 0x1ce34ab5:                                      //Hexadecimal number of "8" button 22
          return "8"; break;

          case 0x1ce3906f:                                      //Hexadecimal number of "*" button 23
          return "*"; break;

          case 0x1ce32ad5:                                      //Hexadecimal number of "9" button 24
          return "9"; break;

          case 0x1ce3e21d:                                      //Hexadecimal number of "0" button 25
          return "0"; break;

          case 0x1ce342bd:                                      //Hexadecimal number of "#" button 26
          return "#"; break;

          case 0x1ce332cd:                                      //Hexadecimal number of "MUTE" button 27
          return "MUTE"; break;

          case 0x1ce310ef:                                      //Hexadecimal number of "TM" button 28
          return "TM"; break;

          case 0x1ce312ed:                                      //Hexadecimal number of "TEL" button 29
          return "TEL"; break;

          case 0x1ce3d22d:                                      //Hexadecimal number of "CLR" button 30
          return "CLR"; break;
          
          case 0x0:                                             //When this hexadecimal number appears, return the word "ERROR"
          return "ERROR of 0"; break;

          case 0xffffffff:
          return "ERROR of fff"; break;
          
          default:
          return "i dont know this one";
          break;
       }
  }
     else {
      return "there is nothing";
     }
}

String stateChecker(bool check) {   //this function reads if a boolean is true and returns if it is on or off in text
  if (check)  {
    return "On";
  }
  else  {
    return "Off";
  }
}

void sendESP()  {  //this function will make a table in HTML and send it to the wifi chip
String txtWindows;      //string for the state of the windows
String txtLeakage;      //string for the state of the leakage sensor
String txtLight;        //string for the state of the light conditions
String txtMoisture = String(MRsoilmoisture);  //here we read the moisture conditions
if (!alreadyOpenedWindows) { //check if windows are closed
  txtWindows = "Closed";
}
else {                       //windows are not closed
  txtWindows = "Open";
}
if (Leakage) {               //check for leakage
  txtLeakage = "Not found";
}
else {                       //leakage found
  txtLeakage = "Found";
}
switch(lightSensor())  {      //calculate the light conditions
  case 0:
  txtLight = "Dark";
  break;
  case 1:
  txtLight = "Dim";
  break;
  case 2:
  txtLight = "Light";
  break;
  case 3:
  txtLight = "Bright";
  break;
  case 4:
  txtLight = "Very bright";
  break;
}
  String ESPtime;                                     //Sting for the time we updated the webserver
  String daychar = dayOfWeek(WEEKDAY());              //run function to get day of week in text
  ESPtime = daychar;                                  //preloadLCD day
  ESPtime += " " + zeroCheck(DATE());                 //preloadLCD date
  ESPtime += "-" + zeroCheck(MONTH());                //preloadLCD month
  ESPtime += "-" + String(YEAR());                    //preloadLCD year
  ESPtime += " " + zeroCheck(HOUR());                 //preloadLCD hour
  ESPtime += ":" + zeroCheck(MINUTE());               //preloadLCD minute

//----upload--the-table-to-the-wifi-chip-----------------------------------------[HTML]
Serial.println("start sending to esp");//to laptop
Serial1.print(" <table class=\"w3-table  w3-bordered\"> ");
Serial1.print(" <thead> ");
Serial1.print(" <tr class=\"w3-theme\"> ");
Serial1.print("   <th>SENSOR</th> ");
Serial1.print("   <th>VALUE</th>  ");
Serial1.print("   <th>FUNCTION</th> ");
Serial1.print("   <th>STATE</th>  ");
Serial1.print(" </tr> ");
Serial1.print(" </thead>  ");
Serial1.print(" <tbody> ");
Serial1.print(" <tr>  ");
Serial1.print("   <td>Temperature</td>  ");
Serial1.print("   <td>" + String(Temperature("heater")) +"&#8451;</td> ");
Serial1.print("   <td>Heater</td> ");
Serial1.print("   <td>" + stateChecker(heaterIsOn) + "</td>  ");
Serial1.print(" </tr> ");
Serial1.print(" <tr > ");
Serial1.print("   <td>Temperature</td>  ");
Serial1.print("   <td>" + String(Temperature("house")) + "&#8451;</td>  ");
Serial1.print("   <td>Windows</td>  ");
Serial1.print("   <td>"+ txtWindows +"</td> ");
Serial1.print(" </tr> ");
Serial1.print(" <tr>  ");
Serial1.print("   <td>Light intensity</td>  ");
Serial1.print("   <td>"+ txtLight +"</td> ");
Serial1.print("   <td>Ledstrip</td> ");
Serial1.print("   <td>" + stateChecker(ledstripIsOn) + "</td>  ");
Serial1.print(" </tr> ");
Serial1.print(" <tr>  ");
Serial1.print("   <td>Soil moisture</td>  ");
Serial1.print("   <td>" + txtMoisture+ "%</td> ");
Serial1.print("   <td>Actuater</td> ");
Serial1.print("   <td>" + stateChecker(actuaterIsOn) + "</td>  ");
Serial1.print(" </tr> ");
Serial1.print(" <tr>  ");
Serial1.print("   <td>Watertank</td>  ");
Serial1.print("   <td>"+ String(Waterlevel()) +"%</td>  ");
Serial1.print("   <td>leakage</td>  ");
Serial1.print("   <td>"+ txtLeakage +"</td>  ");
Serial1.print(" </tr> ");
Serial1.print(" <tr>  ");
Serial1.print("   <td>Last update:</td>  ");
Serial1.print("   <td colspan=\"4\" >" + ESPtime + " </td>  ");
Serial1.print(" </tr> ");
Serial1.print(" </tbody>  ");
Serial1.println(" </table>  ");
delay(1000);            //this delay will make clear of the end of the table
//----done----
}