/*
 * tempsens_13.c
 
 * Heizung: Auswertung der Temperatursensoren
 
 * Kompilierung mit: gcc -Wall -O3 -o Heiztemp tempsens_13.c
 
 * Aufruf: ./Heiztemp & disown
 
 * 14.09.2013 11:19
 
 */

#define _GNU_SOURCE             // wird von getline() benötigt
#define ENTWICKLUNG             // für die bedingte Kompilierung
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <time.h>
#include <unistd.h>

int main(void) {
    // Dateistrukturen (Streams) anlegen
    FILE *w1_slave_dat;         // für die auszulesenden Sensordaten
    
    #ifndef ENTWICKLUNG
    FILE *log_dat;              // für die Datenprotokollierung
    #endif
    
    // Zugriffspfade der einzelnen Sensoren
    char *vl_hk 
    "/sys/bus/w1/devices/w1_bus_master1/28-000004bbeac6/w1_slave"// VL_HK
    char *rl_hk 
    "/sys/bus/w1/devices/w1_bus_master1/28-000004bb38c2/w1_slave"// RL_HK
    char *vl_ww 
    "/sys/bus/w1/devices/w1_bus_master1/28-000004bb6547/w1_slave"// vl_ww
    char *rl_ww 
    "/sys/bus/w1/devices/w1_bus_master1/28-000004bbf459/w1_slave"// rl_ww
    char *vl_so 
    "/sys/bus/w1/devices/w1_bus_master1/28-000004b86ce8/w1_slave"// vl_so
    
    // Anzeigetexte
    char *text_vlhk "VL Heizkreis:\t\t %.2f Grad\n";
    char *text_rlhk "RL Heizkreis:\t\t %.2f Grad\n";
    char *text_vlww "VL Warmwasserspeicher:\t %.2f Grad\n";
    char *text_rlww "RL Warmwasserspeicher:\t %.2f Grad\n";
    char *text_vlso "VL Solarkollektor:\t %.2f Grad\n";
    
    // für die Zeit
    struct tm *zeit;                // Zeitpunktsbeschreibung
    time_t sekunde;                 // Zeitstempel in Sekunden
                                    // ab 1.1.1970, 0:00 Uhr 
    char zeit_string[80];           // der fertige Zeitstempel
    char datei_name[20];            // Name der Protokolldatei
    
    // allgemeine Variablen
    char *tmp_wort;                     // temporärer Zwischenspeicher
    double temp_vl_sotemp_vl_hktemp_rl_hktemp_rl_wwtemp_vl_ww;
    double last_vl_solast_vl_hklast_rl_hklast_rl_wwlast_vl_ww;
    
    // Speicher für die einzulesenden Dateizeilen
    size_t *malloc(0);                      //
    char **gptr malloc(sizeof(char*));        //
    *gptr NULL;                               // NULL-Zeiger
    /* die tatsächliche Größe wird von der Funktion getline() ermittelt.
     * Wird *gptr vor dem Aufruf mit einem NULL-Zeiger initialisiert 
     * und *t auf 0 gesetzt, übernimmt getline() die Bereitstellung des 
     * Speichers für die Zeile vollkommen selbstständig
    */

    // allgemeine Funktionen
    void daten_holen(   char *pfad,         // 
                        double *temperatur//
                        double *last_temp,  //
                        char *anz_text){
    // Datei zum lesen der Temperatur öffnen
    if ( (w1_slave_dat fopen(pfad,"r")) == NULL) {
        fprintf(stderr"\nKonnte Datei %s nicht öffnen!\n"pfad);
        *temperatur 0.0;                      // Wert zu 0 setzen
        }
    else {
        getline(gptrtw1_slave_dat);         // 1. Zeile auslesen, ignor
        getline(gptrtw1_slave_dat);         // 2. Zeile auslesen
        fclosew1_slave_dat );                 // Datei wieder schließen
        // den 2. String (der die Temperatur enthält) zerlegen
        tmp_wort strtok(*gptr"=");          // der vordere Teil
        tmp_wort strtok(NULL"=");           // die Temperatur
        // fehlertolerante Umwandlung
        *temperatur atof(tmp_wort)/1000.0;    // wandeln + umrechnen
        if ( *temperatur 1.0 && *temperatur 100.0 ) {
            *last_temp = *temperatur;           // merken für Fehlerkor.
        }
        else {                                  // sonst: Messfehler!!!
            *temperatur = *last_temp;           // Fehlerkorrektur mit
        }                                       // letztem Wert
        // bedingte Kompilierung
        #ifdef ENTWICKLUNG
        printf(anz_text, *temperatur);
        #endif
        }
    // Funktionsende
    }
    // bedingte Kompilierung
    #ifndef ENTWICKLUNG
    while(1) {              // Dauerschleife nur im produktivem Programm
    #endif
        // Daten holen und bearbeiten
        daten_holen(vl_hk, &temp_vl_hk, &last_vl_hk
                            text_vlhk); // VL-Temperatur Heizkreis
        daten_holen(rl_hk, &temp_rl_hk, &last_rl_hk
                            text_rlhk); // RL-Temperatur Heizkreis
        daten_holen(vl_ww, &temp_vl_ww, &last_vl_ww
                            text_vlww); // VL-Temperatur WWS
        daten_holen(rl_ww, &temp_rl_ww, &last_rl_ww
                            text_rlww); // RL-Temperatur WWS
        daten_holen(vl_so, &temp_vl_so, &last_vl_so
                            text_vlso); // VL-Temperatur Solarkoll.

        /* Beispiel für das Zeitformat aus dem arduino-Projekt:
         * 17.7.2013-19:45:59
         * Beispiel für eine komplette Protokollzeile (3 Sensoren):
         * 17.7.2013-19:45:59 23.37 21.12 20.62
        */

        // Zeit und Datum ermitteln und Stringvariablen bilden
        time(&sekunde);                 // Die aktuelle Zeit bilden 
        zeit localtime(&sekunde);     // Konvertiert time_t in eine 
                                        // tm Struktur als lokale Zeit.
        // Zeitstempel:
        strftime(zeit_string,           // Formatiert eine tm Struktur
                80,                     // in einen string
                "%d.%m.%Y-%H:%M:%S",    // Formatvorgabe
                zeit);                  // die tm Struktur
        // Name der  Protokolldatei:
        strftime(datei_name,            // Formatiert eine tm Struktur
                20,                     // in einen string
                "%Y-%m-%d.dat",         // Formatvorgabe
                zeit);                  // die tm Struktur
        // Daten protokollieren
        #ifndef ENTWICKLUNG
        if ( (log_dat fopen(datei_name"a")) != NULL) {
            fprintflog_dat"%s %.2f %.2f %.2f %.2f %.2f\n",
                zeit_string,            // Zeitstempel
                temp_vl_hk,             // VL-Heizkreis
                temp_rl_hk,             // RL-Heizkreis
                temp_vl_ww,             // VL-Warmwasserspeicher
                temp_rl_ww,             // RL-Warmwasserspeicher
                temp_vl_so);            // VL-Solarkollektor
                fcloselog_dat );      // Datei wieder schließen
            }
    sleep(60);
    // Ende der Dauerschleife
    }
        #else
        printf"%s %.2f %.2f %.2f %.2f %.2f\n",
                zeit_string,            // Zeitstempel
                temp_vl_hk,             // VL-Heizkreis
                temp_rl_hk,             // RL-Heizkreis
                temp_vl_ww,             // VL-Warmwasserspeicher
                temp_rl_ww,             // RL-Warmwasserspeicher
                temp_vl_so);            // VL-Solarkollektor
        #endif
    // Programmende
    return EXIT_SUCCESS;
}