// Les librairies
#include "WiFiEsp.h"    // https://github.com/bportaluri/WiFiEsp
#include "DHT.h"        // https://github.com/adafruit/DHT-sensor-library

// On définit le type de sonde DHT utilisé (DHT11, DHT21)  
#define DHTTYPE DHT22   

// on défini une 2eme com serie en D2 et D8 pour communiquer avec l'ESP
HardwareSerial ESP(D2, D8); // RX, TX 

char ssid[] = "XXXXX";                // Votre réseau wifi
char pass[] = "YYYYY";                // Votre mdp du réseau wifi
int status = WL_IDLE_STATUS;          // l'état du réseau wifi

WiFiEspServer serveur(80);            // On definit le serveur web sur le port 80

float temp, humi;                     // Variable pour stocker les datas de la sonde
uint8_t DHTPin = D4;                  // on définit le pin sur lequel est la sonde
DHT dht(DHTPin, DHTTYPE);             // on définit la sonde DHT

unsigned long previousMillis = 0;     // varaible pour millis
const long interval = 10000;          // interval pour millis

void setup() {
  Serial.begin(115200);               // On démmarre la com série avec le pc a 115200 baud
  pinMode(DHTPin, INPUT);             // On défini le GPIO utilisé par la sonde en entrée
  dht.begin();                        // On initialise la sonde  
  ESP.begin(115200);                  // On démmarre la com série avec l'ESP a 115200 baud
  WiFi.init(&ESP);                    // On initialisle la connection au réseau  

  // On test si on a le réseau à travers l'esp
  if (WiFi.status() == WL_NO_SHIELD) {
    Serial.println("Je tourve pas l'ESP");    
    while (true);  // On ne continue pas
  }
  
  // On essaye de se connécter au réseau wifi
  while ( status != WL_CONNECTED) {
    Serial.print("J'essaye de me connecter au réseau wifi : ");
    Serial.println(ssid);
    status = WiFi.begin(ssid, pass);
  }
  // On affiche les infos de connexions
  Serial.print("Connécté à : ");
  Serial.println(WiFi.SSID());  
  IPAddress ip = WiFi.localIP();
  Serial.print("Mon ip est : ");
  Serial.println(ip);  
  // on démmarre le serveur web
  serveur.begin();
}

// Fonction qui lit la sonde dht22 toutes les 5s (variable interval)
void get_presstemp() { 
  // On stock le temps écoulé depuis le début du programme dans la variable currentMillis
  unsigned long currentMillis = millis();     
  // si le temps actuel - le temps précédent dépasse l'interval        
  if (currentMillis - previousMillis >= interval) {
    // le temps précédent vaut le temps actuel (réinitialise le compteur) 
    previousMillis = currentMillis;
    // Lecture de la sonde
    temp = dht.readTemperature(); 
    humi = dht.readHumidity();
    // si on lit rien on sort de la fonction
    if (isnan(temp) || isnan(humi)) {
      Serial.println("Impossible de lire la sonde !!!");
      return;
    }
    Serial.print("Température : ");
    Serial.print(temp, 2);
    Serial.print(" °C");
    Serial.print(" | Humidité : ");
    Serial.print(humi, 2);
    Serial.println(" %");
  }
}

void loop() {
  // On lance notre fonction pour récupérer les datas de la sonde
  get_presstemp();
  // On définit l'objet client qui sera l'écoute si un client se connecte 
  WiFiEspClient client = serveur.available();
  // si un client est connecté
  if (client) {
    Serial.println("Un nouveau client est connecté");       
    // flag pour definire la fin d'une requête http (ligne vierge)
    boolean currentLineIsBlank = true;
    // quand un client est connecté 
    while (client.connected()) {
      // si il envoie quel que chose
      if (client.available()) {
        // on lit ce qu'il envoie
        char c = client.read();
        // et on l'écrit dans la comme serie avec le pc
        Serial.write(c);
        // si on reçoit \n, et que le flag currentLineIsBlank est vrai, la demande http est terminée
        if (c == '\n' && currentLineIsBlank) {          
          Serial.println("Envoie de la réponse"); 
          // on envoye une réponse          
          client.print(
            "HTTP/1.1 200 OK\r\n"           
            "Content-Type: text/html\r\n"    // le type de la réponse
            "Connection: close\r\n"          // on fermera la connexion aprés l'envoie de la réponse           
            "\r\n");
          client.print(SendHTML(temp,humi)); // on envoie notre page html comme réponse 
          break;                             // on quitte la boucle while apres la déconnection avec l'esp  
        }
        if (c == '\n') {                     // si le caractère reçu est \n          
          currentLineIsBlank = true;         // le flag currentLineIsBlank vaut true
        }
        else if (c != '\r') {                // si le caractère reçu est \r          
          currentLineIsBlank = false;        // le flag currentLineIsBlank vaut false
        }
      }
    }
    // un petit delay pour le temps de réception de la réponse
    delay(10);

    // on ferme la connexion
    client.stop();
    Serial.println("Client déconnecté");
    delay(10);
  }
}

// la fonction qui construit la page html (datas rafraichies par ajax toutes les 10s (fonction js setInterval)
String SendHTML(float Temperature,float Humidity){
  String ptr = "<!DOCTYPE html>\n";
  ptr +="<meta charset=\"utf-8\">\n";
  ptr +="<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">\n";
  ptr +="<title>STM32-L476RG DHT22</title>\n";
  ptr +="<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}\n";
  ptr +="body{margin-top: 50px;} h1 {color: #444444;margin: 50px auto 30px;}\n";
  ptr +="p {font-size: 24px;color: #444444;margin-bottom: 10px;}\n";
  ptr +="</style>\n";
  ptr +="<script>\n";
  ptr +="setInterval(loadDoc,10000);\n";                               // rafraichie ttes les 10s
  ptr +="function loadDoc() {\n";
  ptr +="var xhttp = new XMLHttpRequest();\n";
  ptr +="xhttp.onreadystatechange = function() {\n";
  ptr +="if (this.readyState == 4 && this.status == 200) {\n";
  ptr +="document.getElementById(\"webpage\").innerHTML =this.responseText}\n";
  ptr +="};\n";
  ptr +="xhttp.open(\"GET\", \"/\", true);\n";
  ptr +="xhttp.send();\n";
  ptr +="}\n";
  ptr +="</script>\n";
  ptr +="</head>\n";
  ptr +="<body>\n";
  ptr +="<div id=\"webpage\">\n";
  ptr +="<h1>STM32-L476RG DHT22</h1>\n";  
  ptr +="<p>Temperature: ";
  ptr +=Temperature;
  ptr +="°C</p>";
  ptr +="<p>Humidity: ";
  ptr +=Humidity;
  ptr +="%</p>";  
  ptr +="</div>\n";
  ptr +="</body>\n";
  ptr +="</html>\n";
  return ptr;
}