// Includes
#include <Time.h>
#include <Wire.h>
//#include <LiquidCrystal.h>
#include "RTClib.h"
// Konstanten
const int DS1307_ADRESSE = 0x50; // I2C Addresse der Echtzeituhr
const int RELAY_1 = 7;  // I/O-Pin Relais 1 
const int RELAY_2 = 6;  // I/O-Pin Relais 2
const int RELAY_3 = 5;  // I/O-Pin Relais 3
const int RELAY_4 = 4;  // I/O-Pin Relais 4
const int FADER_1 = 9;  // PWM-Pin LED-Modul 1
const int FADER_2 = 10; // PWM-Pin LED-Modul 2
// Alle Zeiten: Sekunden nach Mitternacht (0 - 86399)
const long CO2_START =    21600; // 06:00
const long DAWN_START =   25200; // 07:00
const long SIESTA_START = 46800; // 13:00
const long SIESTA_END =   54000; // 16:00
const long CO2_STOP =     72000; // 20:00
const long DUSK_START =   79200; // 22:00
const long FADE_DUR = 3600; // 60min dimmen
const int DAY_STATE[] = { 255 , 255 };      // 100% PWM Tagmodus
const int SIESTA_STATE[] = { 63 , 63  };  // 25% PWM Mittagspause
const int NIGHT_STATE[] = { 0 , 0 };        // 0% PWM Nacht
// Variablen
long Counter;
int StateChan1, StateChan2;
//LiquidCrystal lcd(8, 11, 13, 12, 3, 2);   // LCD-Pins initialiseren
RTC_DS1307 RTC;   // Alias für Ehctzeituhr                                                                                                                                                                            
void fader(long StartTime, const int StartState[], const int EndState[], int Output[2]) {
  float PerSecondDelta0 = (float) (EndState[0] - StartState[0]) / FADE_DUR;
  float PerSecondDelta1 = (float) (EndState[1] - StartState[1]) / FADE_DUR;
  long Elapsed = Counter-StartTime;
  Output[0] = StartState[0] + PerSecondDelta0 * Elapsed;
  Output[1] = StartState[1] + PerSecondDelta1 * Elapsed;
}
long SecondsSinceMidnight() {
  DateTime now = RTC.now();
  long hr = now.hour();
  long min = now.minute();
  long sec = now.second();
  long Total = hr * 3600 + min * 60 + sec;
  return Total;
}
// PWM-Tastverhaeltnis setzen
void set_state(const int STATE[]) {
  if (STATE[0] >= 0 && STATE[0] <= 255) {
    analogWrite(FADER_1, STATE[0]);
    StateChan1 = STATE[0]; }
  if (STATE[1] >= 0 && STATE[1] <= 255) {
    analogWrite(FADER_2, STATE[1]);
    StateChan2 = STATE[1]; }
}
void determine_state() {
  // CO2 schalten
  if ( Counter >= CO2_START && Counter < CO2_STOP) {
    digitalWrite(RELAY_1, HIGH);
  } else {
    digitalWrite(RELAY_1, LOW);
  }
  if ( Counter >= 0 && Counter < DAWN_START ) { // Nacht
      set_state(NIGHT_STATE);
      Serial.print("STATE 1\n"); //debug
      
  } else if ( Counter >= DAWN_START && Counter < (DAWN_START+FADE_DUR) ) { // Sonnenaufgang
    int State[2];
    fader(DAWN_START, NIGHT_STATE, DAY_STATE, State);
    set_state(State);
    Serial.print("STATE 2\n"); //debug
    
  } else if ( Counter >= (DAWN_START+FADE_DUR) && Counter < SIESTA_START ) { // vor Mittagspause
    set_state(DAY_STATE);
    Serial.print("STATE 3\n"); //debug
  } else if ( Counter >= SIESTA_START && Counter < (SIESTA_START+FADE_DUR) ) { // Dimmen zur Mittagspause
    int State[2];
    fader(SIESTA_START, DAY_STATE, SIESTA_STATE, State);
    set_state(State);
    Serial.print("STATE 4\n"); //debug
  
  } else if ( Counter >= SIESTA_START+FADE_DUR && Counter < (SIESTA_END) ) { // Mittagspause
    set_state(SIESTA_STATE);
    Serial.print("STATE 5\n"); //debug
  } else if ( Counter >= SIESTA_END && Counter < (SIESTA_END+FADE_DUR) ) { // Dimmen von Mittagspause
    int State[2];
    fader(SIESTA_END, SIESTA_STATE, DAY_STATE, State);
    set_state(State);
    Serial.print("STATE 6\n"); //debug
  } else if ( Counter >= (SIESTA_END+FADE_DUR) && Counter < DUSK_START ) { // nach Mittagspause
    set_state(DAY_STATE);
    Serial.print("STATE 7\n"); //debug
  } else if ( Counter >= DUSK_START && Counter < (DUSK_START+FADE_DUR) ) { // Sonnenuntergang
    int State[2];
    Serial.print(State[1]);
    fader(DUSK_START, DAY_STATE, NIGHT_STATE, State);
    set_state(State);
    Serial.print("STATE 8\n"); //debug
  
  } else if ( Counter >= (DUSK_START+FADE_DUR) && Counter < 86400 ) { // Nacht
    set_state(NIGHT_STATE);
    Serial.print("STATE 9\n"); //debug
  
  } else {
    Serial.print("STATE NOT MATCHED"); //debug
    }
}
void digitalClockDisplay() {
   DateTime now = RTC.now(); 
    Serial.print(now.day(), DEC);
    Serial.print('.');
    Serial.print(now.month(), DEC);
    Serial.print('.');
    Serial.print(now.year(), DEC);
    Serial.print(' ');
    Serial.print(now.hour(), DEC);
    Serial.print(':');
    Serial.print(now.minute(), DEC);
    Serial.print(':');
    Serial.print(now.second(), DEC);
    Serial.println();
}
void setup() {
  pinMode(RELAY_1, OUTPUT);
  pinMode(RELAY_2, OUTPUT); 
  pinMode(RELAY_3, OUTPUT); 
  pinMode(RELAY_4, OUTPUT);
  pinMode(FADER_1, OUTPUT);
  pinMode(FADER_2, OUTPUT);
  
  // Serielle Kommunikstion initialisieren
  Serial.begin(9600);
  // I2C initialisieren
  Wire.begin();
  // RTC initialisieren
  RTC.begin();
  // RTC auf compile time des Scetches setzen
  RTC.adjust(DateTime(__DATE__, __TIME__));
}
void loop() {
  Counter = SecondsSinceMidnight();
 
  determine_state();
  
  Serial.print("Counter: ");
  Serial.print(Counter);
  Serial.println(); 
  Serial.print("Channel 1, 2: "); 
  Serial.print(StateChan1); 
  Serial.print(", "); 
  Serial.print(StateChan2); 
  Serial.println(); 
  
  digitalClockDisplay();
  
  delay(1000);
}