//debugging: pio device monitor --baud 115200 (terminal) -> usb aus/an stecken
//boot halten, reset drücken und wieder auslassen, dann boot loslassen -> bootloader
#include <stdio.h>
#include "driver/gpio.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"
#include "sdkconfig.h"
#include "esp_sleep.h"

#define DS18B20_PIN GPIO_NUM_0  // GPIO-Pin für den DS18B20

#define OUTPUT_PIN GPIO_NUM_2

#define MEASURE_INTERVAL_MS 1000*5  //5 Minuten


static const char *TAG = "DS18B20";
// Deep Sleep-Zeit in Mikrosekunden (5 Minuten)
#define WAKEUP_TIME_SEC 30  

// RTC-Speicher
RTC_DATA_ATTR int relais_status = 0;

#include "esp_wifi.h"
//idf.py menuconfig -> bluetooth deaktiviert
//#include "esp_bt.h"


void disable_wifi() {
    // WLAN deaktivieren
    esp_wifi_stop();
    esp_wifi_deinit();

    // Bluetooth deaktivieren
    //esp_bt_controller_disable();
    //esp_bt_controller_deinit();
}

void ds18b20_init(gpio_num_t pin) {
    gpio_set_direction(pin, GPIO_MODE_OUTPUT);
    gpio_set_level(pin, 0);
    vTaskDelay(pdMS_TO_TICKS(500));
    gpio_set_level(pin, 1);
    vTaskDelay(pdMS_TO_TICKS(500));
}

bool ds18b20_reset() {
    gpio_set_direction(DS18B20_PIN, GPIO_MODE_OUTPUT);
    gpio_set_level(DS18B20_PIN, 0);
    esp_rom_delay_us(480);
    gpio_set_level(DS18B20_PIN, 1);
    esp_rom_delay_us(70);

    gpio_set_direction(DS18B20_PIN, GPIO_MODE_INPUT);
    int presence = gpio_get_level(DS18B20_PIN);
    esp_rom_delay_us(410);

    return presence == 0;
}

void ds18b20_write_bit(int bit) {
    gpio_set_direction(DS18B20_PIN, GPIO_MODE_OUTPUT);
    gpio_set_level(DS18B20_PIN, 0);
    esp_rom_delay_us(bit ? 10 : 60);
    gpio_set_level(DS18B20_PIN, 1);
    esp_rom_delay_us(bit ? 55 : 5);
}

int ds18b20_read_bit() {
    gpio_set_direction(DS18B20_PIN, GPIO_MODE_OUTPUT);
    gpio_set_level(DS18B20_PIN, 0);
    esp_rom_delay_us(3);

    gpio_set_direction(DS18B20_PIN, GPIO_MODE_INPUT);
    esp_rom_delay_us(10);
    int bit = gpio_get_level(DS18B20_PIN);
    esp_rom_delay_us(53);
    return bit;
}

void ds18b20_write_byte(int byte) {
    for (int i = 0; i < 8; i++) {
        ds18b20_write_bit(byte & 0x01);
        byte >>= 1;
    }
}

int ds18b20_read_byte() {
    int byte = 0;
    for (int i = 0; i < 8; i++) {
        byte |= (ds18b20_read_bit() << i);
    }
    return byte;
}

float ds18b20_get_temp() {
    if (!ds18b20_reset()) {
        ESP_LOGE(TAG, "DS18B20 nicht gefunden");
        return -1000;
    }

    ds18b20_write_byte(0xCC);  // Skip ROM
    ds18b20_write_byte(0x44);  // Convert T

    vTaskDelay(pdMS_TO_TICKS(750));

    if (!ds18b20_reset()) {
        ESP_LOGE(TAG, "DS18B20 nicht gefunden");
        return -1000;
    }

    ds18b20_write_byte(0xCC);  // Skip ROM
    ds18b20_write_byte(0xBE);  // Read Scratchpad

    int temp_lsb = ds18b20_read_byte();
    int temp_msb = ds18b20_read_byte();
    int temp = (temp_msb << 8) | temp_lsb;

    return (float)temp / 16.0;
}

void app_main() 
{
    //disable_wifi();
    ESP_LOGI(TAG, "start main");
    vTaskDelay(1000 / portTICK_PERIOD_MS);
    ds18b20_init(DS18B20_PIN);
    gpio_reset_pin(OUTPUT_PIN);
    gpio_set_direction(OUTPUT_PIN, GPIO_MODE_OUTPUT);

    while (1) 
    {
        float temperature = ds18b20_get_temp();
        if (temperature != -1000)
        {
            ESP_LOGI(TAG, "Temperatur: %.2f °C", temperature);
        } else {
            ESP_LOGE(TAG, "Fehler beim Lesen der Temperatur");
        }

        //float temperature = ds18b20_get_temp();

        //if (temperature >= -5.0 && temperature <= 5.0) 
        if(temperature > 26)
        {
            gpio_set_level(OUTPUT_PIN, 1); // Pin ausschalten / Ventilator einschalten
            ESP_LOGI("TEMP", "Temperature in range: %.2f°C, Pin ON", temperature);
        } else 
        {
            gpio_set_level(OUTPUT_PIN, 0); // Pin einschalten / Ventilator ausschalten
            ESP_LOGI("TEMP", "Temperature out of range: %.2f°C, Pin OFF", temperature);
        }
        vTaskDelay(MEASURE_INTERVAL_MS / portTICK_PERIOD_MS);
        // Light-Sleep konfigurieren und starten
        //ESP_LOGI("SLEEP", "Entering light sleep for %d seconds", WAKEUP_TIME_SEC);
        //esp_sleep_enable_timer_wakeup(WAKEUP_TIME_SEC * 1000000ULL);
        
        // Light-Sleep-Modus aktivieren
        //esp_light_sleep_start();
    }
}