#include <DHT.h>
#include <ESP32Servo.h>

#define DHTPIN 12            // Broche de données du capteur DHT22
#define DHTTYPE DHT22        // Type de capteur DHT utilisé

#define LDRPIN 2 // Broche de lecture du capteur de luminosité
#define LED_BAR_GRAPH_1 23   // Broche pour la première LED du bar graph
#define LED_BAR_GRAPH_2 22   // Broche pour la deuxième LED du bar graph
#define LED_BAR_GRAPH_3 21   // Broche pour la troisième LED du bar graph
#define LED_BAR_GRAPH_4 19   // Broche pour la quatrième LED du bar graph
#define RGB_R 25             // Broche pour la LED rouge de l'RGB
#define RGB_G 27             // Broche pour la LED verte de l'RGB
#define RGB_B 26             // Broche pour la LED bleue de l'RGB
#define SERVO_PIN 13         // Broche de contrôle du servomoteur
#define POTENTIOMETER_PIN 35 // Broche de lecture du potentiomètre

// These constants should match the photoresistor's "gamma" and "rl10" attributes
const float GAMMA = 0.7;
const float RL10 = 50;
const char* WIFI_NAME = "Wokwi-GUEST";
const char* WIFI_PASSWORD = "";
const int myChannelNumber = 2543965 ;
const char* myApiKey = "Z5VPIN8C8VVPQWUB";
const char* server = "api.thingspeak.com";

WiFiClient client;

DHT dht(DHTPIN, DHTTYPE);
Servo servo;

void setup() {
  Serial.begin(9600);
  setupPins();
  WiFi.begin(WIFI_NAME, WIFI_PASSWORD);
  while (WiFi.status() != WL_CONNECTED){
    delay(1000);
    Serial.println("Wifi not connected");
  }
  Serial.println("Wifi connected !");
  Serial.println("Local IP: " + String(WiFi.localIP()));
  WiFi.mode(WIFI_STA);
  ThingSpeak.begin(client);
}

void setupPins() {
  pinMode(LDRPIN, INPUT);
  pinMode(RGB_R, OUTPUT);
  pinMode(RGB_G, OUTPUT);
  pinMode(RGB_B, OUTPUT);
  pinMode(LED_BAR_GRAPH_1, OUTPUT);
  pinMode(LED_BAR_GRAPH_2, OUTPUT);
  pinMode(LED_BAR_GRAPH_3, OUTPUT);
  pinMode(LED_BAR_GRAPH_4, OUTPUT);
  servo.attach(SERVO_PIN);
}

void loop() {
  float co2Threshold = readCO2Threshold();
  float co2Level = readCO2Level();

  controlCO2(co2Threshold, co2Level);
  controlTemperature();
  controlLight();


  int x = ThingSpeak.writeFields(myChannelNumber, myApiKey);
  if(x == 200){
    Serial.println("Channel update successful.");
  } else {
    Serial.println("Problem updating channel. HTTP error code " + String(x));
  }
  delay(1000); // Délai d'une seconde entre chaque lecture
}

float readCO2Threshold() {
  int potentiometerValue = analogRead(POTENTIOMETER_PIN);
  return map(potentiometerValue, 0, 4095, 0, 1000); // Seuil de CO2 ajusté par le potentiomètre
}

float readCO2Level() {
  co2Level = analogRead(35);
  ThingSpeak.setField(3, co2Level);
  return co2Level; // Lecture du niveau de CO2
}

void controlCO2(float threshold, float level) {
  if (level > threshold) {
    // Ouvrir progressivement les fenêtres avec le servomoteur
    for (int angle = 0; angle <= 180; angle++) {
      servo.write(angle);
      delay(15);
    }
  }

}

void controlTemperature() {
  float temperatureThreshold = 25; // Seuil de température pour le chauffage/climatisation
  float temperature = dht.readTemperature();
  float humidity = dht.readHumidity(); // Lecture de la température
  if (!isnan(temperature)) {
    if (temperature > temperatureThreshold) {
      digitalWrite(RGB_R, HIGH);
      digitalWrite(RGB_G, HIGH);
      digitalWrite(RGB_B, LOW);
    } else if (temperature < temperatureThreshold) {
      digitalWrite(RGB_R, LOW);
      digitalWrite(RGB_G, HIGH);
      digitalWrite(RGB_B, HIGH);
    }
  } else {
    Serial.println("Error reading DHT sensor!");
  }
   ThingSpeak.setField(1, temperature);
   ThingSpeak.setField(2, humidity);

}

void controlLight() {
  int analogValue = analogRead(LDRPIN);
  float lux = calculateLux(analogValue);

  if (lux >= 0 && lux <= 199) {
    setLEDBar(1);
  } else if (lux >= 200 && lux <= 499) {
    setLEDBar(2);
  } else if (lux >= 500 && lux <= 999) {
    setLEDBar(3);
  } else {
    setLEDBar(4);
  }
  Serial.println(lux);
  ThingSpeak.setField(4, lux);
}


float calculateLux(int analogValue) {
  float voltage = analogValue / 1024. * 5;
  float resistance = 2000 * voltage / (1 - voltage / 5);
  return pow(RL10 * 1e3 * pow(10, GAMMA) / resistance, (1 / GAMMA));
}

void setLEDBar(int level) {
  digitalWrite(LED_BAR_GRAPH_1, level >= 1);
  digitalWrite(LED_BAR_GRAPH_2, level >= 2);
  digitalWrite(LED_BAR_GRAPH_3, level >= 3);
  digitalWrite(LED_BAR_GRAPH_4, level >= 4);
}