/*
 * Απλό Σύστημα Ελέγχου Θερμοκρασίας με DHT11
 * ARD:icon II IoT
 * DHT11 (pin33), OLED, Buzzer (pin5), 2x Relay (16,17)
 */

#include <Wire.h>
#include <Adafruit_SSD1306.h>
#include <Adafruit_GFX.h>
#include <DHT.h>

// === ΟΘΟΝΗ OLED ===
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

// === ΑΙΣΘΗΤΗΡΑΣ DHT11 ===
#define DHTPIN 33
#define DHTTYPE DHT11
DHT dht(DHTPIN, DHTTYPE);

// === ΕΞΟΔΟΙ ===
#define BUZZER_PIN 5
#define RELAY_HEAT_PIN 16   // Θέρμανση
#define RELAY_COOL_PIN 17   // Ψύξη

// === ΟΡΙΑ ΘΕΡΜΟΚΡΑΣΙΑΣ ===
const float TEMP_LOW = 18.0;    // κάτω από 18°C -> θέρμανση
const float TEMP_HIGH = 28.0;   // πάνω από 28°C -> ψύξη
const float ALARM_LOW = 13.0;   // ακραίο κρύο
const float ALARM_HIGH = 33.0;  // ακραία ζέστη

// === ΜΕΤΑΒΛΗΤΕΣ ===
float temperature = 0.0;
float humidity = 0.0;
unsigned long lastRead = 0;
const long readInterval = 2000;  // διάβασμα κάθε 2 δευτερόλεπτα

void setup() {
  Serial.begin(115200);
  Serial.println("System starting...");

  // OLED
  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println("OLED not found!");
    while (true);
  }
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(0, 0);
  display.println("DHT11 Ready");
  display.display();
  delay(1500);

  // DHT11
  dht.begin();

  // Έξοδοι
  pinMode(BUZZER_PIN, OUTPUT);
  pinMode(RELAY_HEAT_PIN, OUTPUT);
  pinMode(RELAY_COOL_PIN, OUTPUT);
  digitalWrite(RELAY_HEAT_PIN, LOW);
  digitalWrite(RELAY_COOL_PIN, LOW);

  Serial.println("System ready. Monitoring...");
}

void loop() {
  // Διάβασμα αισθητήρα κάθε 2 δευτερόλεπτα
  if (millis() - lastRead >= readInterval) {
    lastRead = millis();
   
    float t = dht.readTemperature();
    float h = dht.readHumidity();
   
    if (!isnan(t) && !isnan(h)) {
      temperature = t;
      humidity = h;
      Serial.print("Temp: "); Serial.print(temperature); Serial.print("°C  Hum: "); Serial.println(humidity);
     
      updateDisplay(temperature, humidity);
      controlRelays(temperature);
      checkAlarm(temperature);
    } else {
      Serial.println("DHT11 read error!");
      displayError();
    }
  }
}

void updateDisplay(float temp, float hum) {
  display.clearDisplay();
  display.setTextSize(1);
  display.setCursor(0, 0);
  display.println("=== CLIMATE CTRL ===");
 
  display.setTextSize(2);
  display.setCursor(0, 18);
  display.print(temp, 1);
  display.println(" C");
 
  display.setTextSize(1);
  display.setCursor(0, 42);
  display.print("Hum: ");
  display.print(hum, 1);
  display.println("%");
 
  display.setCursor(0, 52);
  if (temp < TEMP_LOW) {
    display.println("STATE: HEATING");
    display.drawCircle(110, 50, 6, SSD1306_WHITE);
  } else if (temp > TEMP_HIGH) {
    display.println("STATE: COOLING");
    display.fillCircle(110, 50, 6, SSD1306_WHITE);
  } else {
    display.println("STATE: NORMAL");
    display.drawRect(104, 44, 12, 12, SSD1306_WHITE);
  }
  display.display();
}

void displayError() {
  display.clearDisplay();
  display.setCursor(0, 0);
  display.println("DHT11 ERROR");
  display.println("Check wiring");
  display.display();
}

void controlRelays(float temp) {
  if (temp < TEMP_LOW) {
    digitalWrite(RELAY_HEAT_PIN, HIGH);
    digitalWrite(RELAY_COOL_PIN, LOW);
    Serial.println(">> Heating ON (Relay16)");
  } else if (temp > TEMP_HIGH) {
    digitalWrite(RELAY_HEAT_PIN, LOW);
    digitalWrite(RELAY_COOL_PIN, HIGH);
    Serial.println(">> Cooling ON (Relay17)");
  } else {
    digitalWrite(RELAY_HEAT_PIN, LOW);
    digitalWrite(RELAY_COOL_PIN, LOW);
  }
}

void checkAlarm(float temp) {
  if (temp < ALARM_LOW) {
    alarmTone(3, 500);
    Serial.println("*** ALARM: EXTREME COLD ***");
  } else if (temp > ALARM_HIGH) {
    alarmTone(5, 300);
    Serial.println("*** ALARM: EXTREME HEAT ***");
  } else {
    noTone(BUZZER_PIN);
  }
}

void alarmTone(int beeps, int duration) {
  for (int i = 0; i < beeps; i++) {
    tone(BUZZER_PIN, 2000);
    delay(duration);
    noTone(BUZZER_PIN);
    delay(100);
  }
}