// include the library code:
#include <LiquidCrystal.h> // Library für die LCD Anzeige
#include <WiFi.h> //Library für die Wlan Anbindung
#include <time.h>

// Definitionen
#define WIFI_SSID "Wokwi-GUEST"
#define WIFI_PASSWORD ""

// NTP-Server aus dem Pool
#define Zeitserver "ch.pool.ntp.org"

/*
  Liste der Zeitzonen
  https://github.com/nayarsystems/posix_tz_db/blob/master/zones.csv
  Zeitzone CET = Central European Time -1 -> 1 Stunde zurück
  CEST = Central European Summer Time von
  M3 = März, 5.0 = Sonntag 5. Woche, 02 = 2 Uhr
  bis M10 = Oktober, 5.0 = Sonntag 5. Woche 03 = 3 Uhr
*/
#define Zeitzone "CET-1CEST,M3.5.0/02,M10.5.0/03"

// time_t enthält die Anzahl der Sekunden seit dem 1.1.1970 0 Uhr
time_t aktuelleZeit;

/* 
  Struktur tm
  tm_hour -> Stunde: 0 bis 23
  tm_min -> Minuten: 0 bis 59
  tm_sec -> Sekunden 0 bis 59
  tm_mday -> Tag 1 bis 31
  tm_wday -> Wochentag (0 = Sonntag, 6 = Samstag)
  tm_mon -> Monat: 0 (Januar) bis 11 (Dezember)
  tm_year -> Jahre seit 1900
  tm_yday -> vergangene Tage seit 1. Januar des Jahres
  tm_isdst -> Wert > 0 = Sommerzeit (dst = daylight saving time)
*/
tm Zeit;

// Zeit bis zur nächsten Messung
static unsigned long GesicherteStartZeit = 0;
unsigned long Startzeit;
int Intervall = 10000; // Sekunden Intervall, kann angepasst werden

// Wecker Variabeln
int Close_Std = 20; // temporäre Variable, für wann das fenster geschlossen werden soll
int Close_Min = 32; // temporäre Variable, für wann das fenster geschlossen werden soll
int Aktuelle_Std = -1; // temporäre Variable, für die Berechnungen
int Aktuelle_Min = -1; // temporäre Variable, für die Berechnungen
bool CloseWindowTrigger = false; // Marker, um den Motor nur einmal zu starten


const int RELAIS = 26; // definiere Variable als ESP32 Port GIOP4 Pin26

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(19, 23, 18, 17, 16, 15);


void setup() {
  Serial.begin(115200); // Öffne die serielle Schnittstelle (Baudrate)
  digitalWrite(RELAIS, LOW);
  pinMode(RELAIS, OUTPUT); // Setze den Port für das Relais als Ausgang
  digitalWrite(RELAIS, LOW);

  setup_wifi();

  configTzTime(Zeitzone, Zeitserver); // Parameter für die zu ermittelnde Zeit

}
 
void loop() {
  // Startzeit für Intervalltimer setzen
  Startzeit = millis();

  // wenn das festgelegte Intervall erreicht ist
  if (Startzeit - GesicherteStartZeit > Intervall) // prüfen, ob der Intervall abgelaufen ist
  {
    ZeitAnzeigen();
    if (CloseWindowTrigger==true) Fenster_schliessen();
 
    // Startzeit zurücksetzen
    GesicherteStartZeit = Startzeit;
  }


}

// Programm Hilfs-Funktionen
void setup_wifi() {
  lcd.begin(16, 2);
  lcd.setCursor(0, 0);
  lcd.print("Verbinde ");
  lcd.setCursor(0, 1);
  lcd.print("mit Wlan ");
  delay(2000);

  // Starte Wlan-Anbindung
  WiFi.begin(WIFI_SSID, WIFI_PASSWORD, 6);
  Serial.print("Verbinde mit Wlan: ");
  Serial.print(WIFI_SSID);
  while (WiFi.status() != WL_CONNECTED) {
    delay(250);
    wlan_connect_progress();
  }
  Serial.print("Wlan verbunden");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Wlan verbunden");
  delay(1000);
  lcd.clear();
}

void wlan_connect_progress() {
  static int8_t counter = 0;
  const char* glyphs = "\xa1\xa5\xdb";
  lcd.setCursor(15, 1);
  lcd.print(glyphs[counter++]);
  if (counter == strlen(glyphs)) {
    counter = 0;
  }
}

void ZeitAnzeigen() 
{
  // aktuelle Zeit lesen
  time(&aktuelleZeit);

  // localtime_r -> Zeit in die lokale Zeitzone setzen
  localtime_r(&aktuelleZeit, &Zeit);

  lcd.clear();
  lcd.setCursor(0, 0);
  if (Zeit.tm_mday < 10) lcd.print("0"); // Tag: führende 0 ergänzen
  lcd.print(Zeit.tm_mday);
  lcd.print(".");
  if (Zeit.tm_mon < 10) lcd.print("0"); // Monat: führende 0 ergänzen
  lcd.print(Zeit.tm_mon+1);
  lcd.print(".");
  if (Zeit.tm_year < 10) lcd.print("0"); // Jahr: führende 0 ergänzen
  lcd.print(Zeit.tm_year + 1900);

  lcd.print(" ");

  if (Zeit.tm_hour < 10) lcd.print("0"); // Stunde: führende 0 ergänzen
  lcd.print(Zeit.tm_hour);
  lcd.print(":");

  if (Zeit.tm_min < 10) lcd.print("0"); // Minute: führende 0 ergänzen
  lcd.print(Zeit.tm_min);

  lcd.setCursor(0, 1);
  lcd.print("Schliessen: ");

  lcd.setCursor(11, 1);
  if (Close_Std < 10) lcd.print("0"); // Stunde: führende 0 ergänzen
  lcd.print(Close_Std);
  lcd.print(":");

  if (Close_Min < 10) lcd.print("0"); // Minute: führende 0 ergänzen
  lcd.print(Close_Min);

  // Tag: führende 0 ergänzen
  if (Zeit.tm_mday < 10) Serial.print("0");
  Serial.print(Zeit.tm_mday);
  Serial.print(".");

  // Monat: führende 0 ergänzen
  if (Zeit.tm_mon < 10) Serial.print("0");
  Serial.print(Zeit.tm_mon + 1);
  Serial.print(".");

  // Anzahl Jahre seit 1900
  Serial.print(Zeit.tm_year + 1900);  
  Serial.print(" ");

  if (Zeit.tm_hour < 10) Serial.print("0");
  Serial.print(Zeit.tm_hour);  
  Serial.print(":");

  if (Zeit.tm_min < 10) Serial.print("0");
  Serial.print(Zeit.tm_min);  
  Serial.print(":");
  if (Zeit.tm_sec < 10) Serial.print("0");
  Serial.print(Zeit.tm_sec);  
  Serial.println();
  Serial.print("Tage seit 1. Januar: ");
  Serial.print(Zeit.tm_yday);
  Serial.println();

  // Normalzeit/Sommerzeit
  if(Zeit.tm_isdst > 0) Serial.println("MESZ = Mitteleuropäische Sommerzeit");
  else Serial.println("MEZ = Mitteleuropäische Zeit");
  Serial.println("------------------------");

  // Variabeln für die Berechnung zuweisen
  Aktuelle_Std=Zeit.tm_hour;
  Aktuelle_Min=Zeit.tm_min;

  if (Aktuelle_Std == Close_Std) 
  {
    if (Aktuelle_Min == Close_Min)
    {
      Serial.println("Schliesse fenster");
      CloseWindowTrigger=true;

    }
    else
    {
      CloseWindowTrigger=false; // 
    }
  }
}


void Fenster_schliessen()
{
  Serial.println("Starte Motor");
  lcd.setCursor(0, 1);
  lcd.print("Schliesse Fenster ");
  digitalWrite(RELAIS, HIGH);
  delay(10000);
  digitalWrite(RELAIS, LOW);
  Serial.println("Motor stoppen");
  lcd.setCursor(0, 1);
  lcd.print("Fenster geschlossen");
  delay(60000);

}
NOCOMNCVCCGNDINLED1PWRRelay Module