// Import des librairies
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include "DHT.h"

/******* PARAMÈTRES À MODIFIER SELON VOTRE CONFIG ********/

#define ssid           "XXXXXXX"             // votre ssid   
#define password       "YYYYYYYYYYYYYYYYYY"  // votre mdp
#define mqtt_server    "192.168.X.X"         // ip du serveur MQTT mosquitto
#define mqtt_username  "XXXX"                // votre login mqtt 
#define mqtt_password  "YYYYYYYY"            // votre mdp mqtt
#define mqtt_topic_in  "domoticz/in"
#define mqtt_topic_out "domoticz/out"
#define  IDX           1                     // Doit être le même que le capteur virtuel dans Domotocz */
#define DHTTYPE        DHT21
#define DHTPin         4       // D2 
#define led            LED_BUILTIN           // led interne
#define led_on         LOW                   // inversé car led interne
#define led_off        HIGH                  // inversé car led interne

const long interval = 10000;                 // lecture de la sonde toute les 10 s 
unsigned long previousMillis = 0;

DHT dht(DHTPin, DHTTYPE);                    // On crée l'objet DHT 
WiFiClient nodemcuClient;                    // On crée l'objet WiFiClient 
PubSubClient client(nodemcuClient);          // On crée l'objet PubSubClient

// La fonction callback qui écrit dans la com série ce qui est répondu ou envoyé par MQTT (domoticz/out) 
// Cette fonction est utile si on dois recevoir des infos de MQTT un switch par exemple.
void callback(char* topic, byte* payload, unsigned int length) {
  Serial.print("[callback()] Message reçu de [");
  Serial.print(topic);
  Serial.print("] ");
  for (int i = 0; i < length; i++) {
    Serial.print((char)payload[i]);
  }
  Serial.println();
}

// Connexion au broker MQTT
void MQTTconnect() {  
  while (!client.connected()) {
    Serial.println("[MQTTconnect()] Attente de connexion ...");    
    if (client.connect("NodeMCU_Client", mqtt_username, mqtt_password)) {
      Serial.println("[MQTTconnect()] Connexion OK"); 
      Serial.print("[MQTTconnect()] Abonnement au topic domoticz/out --> ");
      if ( client.subscribe(mqtt_topic_out, 0) ) Serial.println("OK"); 
      else Serial.println("KO"); 
      Serial.println();  
    } else {
      Serial.print("[MQTTconnect()] echec de connection : ");          
      Serial.print(client.state());
      Serial.println(" nouvelle tentative dans 5 secondes");    
      Serial.println();  
      delay(5000);
    }    
  }
}

void setup(){
  Serial.begin(115200);
  delay(1000);
  Serial.println();
  Serial.println("[setup()] Initialisation ...");
  pinMode(led, OUTPUT);
  digitalWrite(led, led_off); 
  dht.begin(); 
  Serial.print("[setup()] Connexion au WIFI -> ");  
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(250);
    digitalWrite(led, led_on);
    delay(250);    
    digitalWrite(led, led_off);   
  }  
  Serial.println("OK");
  Serial.print("[setup()] Adresse ip : ");
  Serial.println(WiFi.localIP());   
  client.setServer(mqtt_server, 1883);
  client.setCallback(callback);
  Serial.println("[setup()] Initialisation OK");
  Serial.println();
}

void loop(void) {   
  if (!client.connected()) {
    MQTTconnect();
  }
  client.loop();  
  sonde();
}

void sonde() {
  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis >= interval) {    
    previousMillis = currentMillis;
    digitalWrite(led, led_on);
    float humidity = dht.readTemperature();
    float temperature = dht.readHumidity();
    float hum_stat;
    if ( humidity > 70 ) {
      hum_stat = 3;
    } else if ( humidity < 30 ) {
      hum_stat = 2; 
    } else if ( humidity >= 30 & humidity <= 45 ) {
      hum_stat = 0;
    } else if ( humidity > 45 & humidity <= 70 ) {
      hum_stat = 1;
    }
    char mqttbuffer[60];              
    // on met en forme pour domoticz                                    
    sprintf(mqttbuffer, "{ \"idx\" : %d, \"nvalue\" : 0, \"svalue\" : \"%3.1f;%3.1f;%d\" }\n", IDX, humidity, temperature, hum_stat); 
    Serial.print("[sonde()] Message à publier [domoticz/in] --> ");
    Serial.println(mqttbuffer);
    Serial.print("[sonde()] Publication sur domoticz/in --> ");
    if ( client.publish(mqtt_topic_in, mqttbuffer) ) Serial.println("OK"); 
    else Serial.println("KO");  
    Serial.println();  
    digitalWrite(led, led_off);
  }
}