////////////////////////////////////////////////////
// Temperaturmessung mit dem Arduino (Version App)//
////////////////////////////////////////////////////

// Integration der erforderlichen Bibliotheken
#include <OneWire.h>                                 // Einbinden der Bibliothek zur Kommunikation mit Ein-Kabel-Sensoren.
#include <DallasTemperature.h>                       // Einbinden der Bibliothek für den Temperatursensor.
#include <SPI.h>                                     // Einbinden der Bibliothek für SPI-Geräte.
#include <SdFat.h>                                   // Einbinden der Bibliothek für den SD-Card-Reader.
SdFat SD;                                            // Objekt SD erstellen
#define SD_CS_PIN SS                                  

// Variablen, mit denen die Messung über die Bluetooth-Kommunikation angepasst wird.
unsigned long Messdauer = 10000;                      // Definition der Messdauer in Millisekunden
unsigned long Messpause_messung = 1000;               // Pause zwischen zwei Messungen während der Messung in Millisekunden
unsigned long Messpause_idle = 2000;                  // Pause zwischen zwei Messungen außerhalb der Messung in Millisekunden

// Konfiguration der Temperatursensoren
const int tmpPin1 = 7;                                // Definition des Datenpins für den ersten Temperatursensor
const int tmpPin2 = 6;                                // Definition des Datenpins für den zweiten Temperatursensor
OneWire oneWire1(tmpPin1);                            // Zuweisen des Datenpins zur oneWire-Kommunikation
OneWire oneWire2(tmpPin2);                            // Zuweisen des Datenpins zur oneWire-Kommunikation
DallasTemperature sensors1(&oneWire1);                // Definiton der oneWire-Kommunikation als Temperatursensor
DallasTemperature sensors2(&oneWire2);                // Definiton der oneWire-Kommunikation als Temperatursensor

// Konfiguration des LED-Pins
const int LEDPin = 8;                                  // Definition des Pins, an den die LED angeschlossen ist

// Arduinointerne Variablen, die nicht per Bluetooth oder SD-Card ausgegeben werden
unsigned long currentmillis = 0;                      // Variable zur Abspeicherung der aktuellen Systemzeit
unsigned long starttime;                              // Variable zur Speicherung der Systemzeit zu Beginn der Messung
unsigned long endtime;                                // Variable zur Speicherung der Endzeit der Messung
String usr_input;                                     // Variable zum Auslesen des seriellen Monitors
int positio1;                                         // Variable zur Speicherung der Position des ersten Doppelpunkts im Eingabestring
int positio2;                                         // Variable zur Speicherung der Position des zweiten Doppelpunkts im Eingabestring
int positio3;                                         // Variable zur Speicherung der Position des dritten Doppelpunkts im Eingabestring
int positio4;                                         // Variable zur Speicherung der Position des dritten Doppelpunkts im Eingabestring
int Messpause_Einheit = 1;                            // Variable zur Speicherung der Einheit der Messpause. 1: Sekunden ; 2: Minuten ; 3: Stunden
unsigned long lastmillis_idle = 0;                    // Variable zur Speicherung der Systemzeit, zu der die letzte idle-Messung durchgeführt wurde
long lastmillis_messung = 0;                          // Variable zur Speicherung der Systemzeit, zu der die letzte geloggte-Messung durchgeführt wurde
unsigned long LEDpause = 470;                         // Pause zwischen der Änderung des LED-Zustands (an/aus)
unsigned long lastmillis_LED = 0;                     // Variable zur Speicherunkg der Systemzeit, zu der die letzte Änderung des LED-Status durchgeführt wurde
int LED_Status = 0;                                   // Variable zur Speicherung des LED-Status

// Variablen für die Ausgabe auf die SD-Card
String filename_temp;                                 // Hilfsvariable zur Erzeugung des Dateinamens der Messung
char filename [13];                                   // Hilfsvariable zur Benennung der Messung auf der SD-Card
String Uhrzeit_SD_Dateiname;                          // Variable zur Benennung der Messung auf der SD-Card
String ausgabe_SD;                                    // Variable zur Zusammenführung des Ausgabestrings für die SD-Card
String Messpause_Einheit_Text;

// Variablen für die Bluetooth-Ausgabe
unsigned long time_since_s;                           // Variable für Zeit seit Messbeginn
float temperatur1;                                    // Variable für die erste Temperatur
float temperatur2;                                    // Variable für die zweite Temperatur
int Messstatus = 0;                                   // Variable für den Messstatus. 0: Idle ; 1:Messung läuft
String ausgabe_BT;                                    // Variable zur Zusammenführung des Ausgabestrings für die Bluetooth-Ausgabe

void setup()
{
  Serial.begin(9600);                                 // Die serielle Kommunikation wird gestartet.
  sensors1.begin();                                   // Starten der Sensoren.
  sensors2.begin();                                   // Starten der Sensoren.
  sensors1.setWaitForConversion(false);               // Ersten Temperatursensor asynchron schalten, um Messdelay zu verringern
  pinMode(LEDPin, OUTPUT);                            // Definition des LED-Pins als Output
}
void loop() {
  currentmillis = millis();                                                         // Zuweisen der aktuellen Systemzeit zur Variable currentmillis

    if (Serial.available() > 0) {                                                     // Überprüfung, ob Text im seriellen Monitor verfügbar ist

    usr_input = Serial.readString();                                                // Abspeichern der Texteingabe
    usr_input.trim();                                                               // Entfernung von Leerzeichen aus dem String

    positio1 = usr_input.indexOf(":");                                              // Bestimmung der Position des ersten Doppelpunkts
    Messstatus = usr_input.substring(0, positio1).toInt();                          // Abtrennen des ersten Teils des Strings (Befehl)

    if (Messstatus == 1) {                                                          // Überprüfen, ob der Messstatus auf 1 geändert wurde
      SD.begin(SD_CS_PIN);                                                          // Initialisierung der SD-Karte
      positio2 = usr_input.indexOf(":", positio1 + 1);                              // Bestimmung der Position des zweiten Doppelpunkts
      positio3 = usr_input.indexOf(":", positio2 + 1);                              // Bestimmung der Position des dritten Doppelpunkts
      positio4 = usr_input.indexOf(":", positio3 + 1);                              // Bestimmung der Position des vierten Doppelpunkts

      Messdauer = usr_input.substring(positio1 + 1, positio2).toInt() * 1000L;            // Abtrennen des zweiten Teils des Stings (Messdauer)
      Messpause_messung = usr_input.substring(positio2 + 1, positio3).toInt() * 1000L;    // Abtrennen des dritten Teils des Strings (Messpause_messung)
      Messpause_Einheit = usr_input.substring(positio3 + 1, positio4).toInt();      // Abtrennen des vierten Teils des Strings (Messpause_Einheit)
      Uhrzeit_SD_Dateiname = usr_input.substring(positio4 + 1);                     // Abtrennen des fünften Teils des Strings (Uhrzeit_SD_Dateiname)

      if (Messpause_Einheit == 1) {
        Messpause_Einheit_Text = "Sekunden";
      }
      else if (Messpause_Einheit == 2) {
        Messpause_Einheit_Text = "Minuten";
      }
      else if (Messpause_Einheit == 3) {
        Messpause_Einheit_Text = "Stunden";
      }
      //filename_temp = "aaaaaaaaaaaaaaaa.csv";                                // Hinzufügen der Dateiendung
      filename_temp = Uhrzeit_SD_Dateiname + ".csv";                                // Hinzufügen der Dateiendung
      filename_temp.toCharArray(filename, sizeof(filename));                        // Umwandlung des Strings filname_temp in den Charakterarray filename
      File dataFile = SD.open(filename, FILE_WRITE);                                // öffnen der Ausgabedatei auf der SD-Card
      dataFile.println("Zeit [" + Messpause_Einheit_Text + "]" + "; Temperatur 1 [Grad Celsius]; Temperatur 2 [Grad Celsius]"); // Speichern der Kopfzeile auf der SD-Card.
      dataFile.close();                                                             // Schließen der Ausgabedatei auf der SD-Card.

      currentmillis = millis();                                                     // Aktualisierung der Systemzeit, um die Startzeit der Messung bei etwa 0 ms zu haben
      starttime = currentmillis;                                                    // Zuweisung der aktuellen Systemzeit zur Startzeit der Messung in ms.
      endtime = Messdauer + starttime;                                              // Berechnung des Endzeitpunkts aus der Startzeit und der Messdauer.
      lastmillis_messung = -1*Messpause_messung;                                    // Setzen des letzten Messzeitpunkts, damit beim Start der Messung direkt der erste Messwert aufgenommen wird.
      digitalWrite(LEDPin, HIGH);                                                   // Einschalten der LED
    }
    //    else if ((Messstatus == 0)) {
    //    LEDpause = 1000;                                          // Setzen der LED-Blinkpause
    // }
  }

  if ((Messstatus == 1) && (currentmillis >= endtime)) {      // Überprüfen, ob bei aktiver Messung die aktuelle Zeit größer als die Endzeit ist.
    Messstatus = 0;                                           // Falls wahr, beende die Messung, indem der Messstatus geändert wird.
    //   LEDpause = 1000;                                     // Setzen der LED-Blinkpause
  }

  else if ((Messstatus == 0) && (currentmillis - lastmillis_idle >= Messpause_idle)) {      // Überprüfe, ob bei inaktiver Messung (idle) die Zeit zwischen letzter Ausgabe der Temperatur und der aktuellen Zeit größer als die vorgegebene Messpause im idle-Zustand ist.
    lastmillis_idle = currentmillis;                          // Falls wahr, weise der Variable lastmillis_idle die aktuelle Systemzeit zu
    sensors1.requestTemperatures();                           // Frag die Temperatur des ersten Temperatursensors an (asynchron)
    sensors2.requestTemperatures();                           // Frag die Temperatur des zweiten Temperatursensors an (synchron)
    temperatur2 = sensors2.getTempCByIndex(0);                // Abfrage der Temperatur und Speicherung unter der Variable temperatur.
    temperatur1 = sensors1.getTempCByIndex(0);                // Anfrage der Temperatur und Speicherung unter der Variable temperatur.
    ausgabe_BT = String(Messstatus) + ";" + String(Messdauer) + ";" + String(Messpause_Einheit) + ";" + String("_") + ";" + String(temperatur1) + ";" + String(temperatur2); // Zusammensetzen des Ausgabestrings für die Bluetooth-Ausgabe
    Serial.println(ausgabe_BT);                               // Ausgabe des Ausgabestrings über den seriellen Monitor.
    if (LED_Status == 0) {
      digitalWrite(LEDPin, HIGH);
      LED_Status = 1;
    }

    else {
      digitalWrite(LEDPin, LOW);
      LED_Status = 0;
    }  
  }

  else if ((Messstatus == 1) && (currentmillis - lastmillis_messung >= Messpause_messung)) {    // Überprüfe, ob bei aktiver Messung die Zeit zwischen letzter Ausgabe der Temperatur und der aktuellen Zeit größer als die vorgegebene Messpause im Mess-Zustand ist.
    lastmillis_messung = currentmillis;                       // Falls wahr, weise der Variable lastmillis_idle die aktuelle Systemzeit zu
    time_since_s = currentmillis - starttime;                 // Zeit seit Start der Messung.
    sensors1.requestTemperatures();                           // Frag die Temperatur des ersten Temperatursensors an (asynchron)
    sensors2.requestTemperatures();                           // Frag die Temperatur des zweiten Temperatursensors an (synchron)
    temperatur2 = sensors2.getTempCByIndex(0);                // Abfrage der Temperatur und Speicherung unter der Variable temperatur.
    temperatur1 = sensors1.getTempCByIndex(0);                // Anfrage der Temperatur und Speicherung unter der Variable temperatur.

    if (Messpause_Einheit == 1) {
      time_since_s = time_since_s / 1000L;
    }
    else if (Messpause_Einheit == 2) {
      time_since_s = time_since_s / 60000L;
    }
    else if (Messpause_Einheit == 3) {
      time_since_s = time_since_s / 3600000L;
    }

    ausgabe_SD = String(time_since_s) + ";" + String(temperatur1) + ";" + String(temperatur2);                                // Zusammensetzen des Ausgabestrings für die SD-Card-Ausgabe
    ausgabe_BT = String(Messstatus) + ";" + String(Messdauer) + ";" + String(Messpause_Einheit) + ";" + String(ausgabe_SD);   // Zusammensetzen des Ausgabestrings für die Bluetooth-Ausgabe
    Serial.println(ausgabe_BT);                               // Ausgabe des Ausgabestrings über den seriellen Monitor.
    File dataFile = SD.open(filename, FILE_WRITE);            // öffnen der Ausgabedatei auf der SD-Card
    dataFile.println(ausgabe_SD);                             // Speichern eines Wertepaares auf die SD-Card.
    dataFile.close();                                         // Schließen der Ausgabedatei auf der SD-Card.
  }

//  if ((Messstatus == 0) && (currentmillis - lastmillis_LED >= LEDpause)) {
//    lastmillis_LED = currentmillis;
//
//    if (LED_Status == 0) {
//      digitalWrite(LEDPin, HIGH);
//      LED_Status = 1;
//    }
//
//    else {
//      digitalWrite(LEDPin, LOW);
//      LED_Status = 0;
//    }
//
//  }
}
