/*******************includes**************************/

#include <LiquidCrystal_I2C.h>
#include <Adafruit_MPU6050.h>
#include <Adafruit_Sensor.h>
#include "DHTesp.h"
#include <WiFi.h>
#include <PubSubClient.h>

/***************************************************/

/*********************define*************************/
#define colonne 20
#define ligne 4
#define LCD_addr 0x27
#define inputPin  34
#define PIN_TRIG 33
#define PIN_ECHO 32
#define Button 14
DHTesp dhtSensor;

/*********************Macro*************************/
LiquidCrystal_I2C LCD = LiquidCrystal_I2C(LCD_addr, colonne, ligne);
Adafruit_MPU6050 mpu;
/****************declaration des variable Globale*/
float xdeg , ydeg, zdeg;
int pirState = LOW;
int val = 0; 
float lux = 0;
const int DHT_PIN = 21;
const float GAMMA = 0.7;
const float RL10 = 50;
const int LIGHT_SENSOR_PIN =35;

/***************connexion internet with MQTT***************/
const char* ssid = "Wokwi-GUEST";
const char* password = "";
const char* mqtt_server = "broker.emqx.io";
const int port = 1883 ;
WiFiClient espClient;
PubSubClient client(espClient);

/**********************function for detect wifi *****/
void setup_wifi() {

  delay(10);
  // We start by connecting to a WiFi network
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);

  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(100);
    Serial.print(".");
  }

  randomSeed(micros());

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
}
void callback(char* topic, byte* payload, unsigned int length) {
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  for (int i = 0; i < length; i++) {
    Serial.print((char)payload[i]);
  }
}

void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Create a random client ID
    String clientId = "ESP8266Client-";
    clientId += String(random(0xffff), HEX);
    // Attempt to connect
    if (client.connect(clientId.c_str())) {
      Serial.println("Connected");
      // Once connected, publish an announcement...
      client.publish("iotfrontier/mqtt", "iotfrontier");
      // ... and resubscribe
      client.subscribe("iotfrontier/mqtt");
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 100 melliseconds");
      // Wait 100 melliseconds before retrying
      delay(100);
    }
  }
  
}

/***************************************************/
void setup() {
  // put your setup code here, to run once:

  Serial.begin(9600);

  pinMode(inputPin, INPUT);
  pinMode(LIGHT_SENSOR_PIN, INPUT);
  pinMode(PIN_TRIG, OUTPUT);
  pinMode(PIN_ECHO, INPUT);
  pinMode(Button , INPUT);
 
  LCD.init();
  LCD.backlight();
  dhtSensor.setup(DHT_PIN, DHTesp::DHT22);
  
  while (!Serial)
    delay(10); // will pause Zero, Leonardo, etc until serial console opens
  Serial.println("MPU6050 find");
  // Try to initialize!
  if (!mpu.begin()) {
    Serial.println("Failed to find MPU6050 chip");
    while (1) {
      delay(10);
    }
 }
 /****************init connexion ******************/
   setup_wifi();
   client.setServer(mqtt_server, port); 
   client.setCallback(callback); 

/************************_______********************/
}

void loop() {
  TempAndHumidity  data = dhtSensor.getTempAndHumidity(); // get temp and humidity
  val = digitalRead(inputPin);
  digitalWrite(PIN_TRIG, HIGH);
  delayMicroseconds(10);
  digitalWrite(PIN_TRIG, LOW);
  long duration = pulseIn(PIN_ECHO, HIGH);
  float distance_cm = duration / 58.0;  
    sensors_event_t a, g, temp;
    mpu.getEvent(&a, &g, &temp);

  /* conversion de rad to deg */
    xdeg = g.gyro.x * 57,5;
    ydeg = g.gyro.y * 57,5;
    zdeg = g.gyro.z * 57,5;
 

      float analogValue = analogRead(LIGHT_SENSOR_PIN);
      float voltage = analogValue / 4095.  * 5;
      float resistance = 2000 * voltage / (1 - voltage / 5);
      lux = pow (RL10 * 1e3 * pow(10,GAMMA) / resistance, (1 / GAMMA));
      delay(200);
      client.publish("PIR","pas de mouvement");

       /*-----------------------------*/

      
      if(val == HIGH ){
        //lcd_affichage();
      client.publish("PIR","detect Mouvement ✓ "); 
      //Serial.println("affichage sur lcd");
      LCD.clear();  
      LCD.setCursor(0, 0);
      LCD.print("Mouvement detecte");
      LCD.setCursor(0, 1);
      LCD.print("Temp DHT: " + String(data.temperature, 1) + "\xDF"+"C  ");
      LCD.setCursor(0, 2);
      LCD.print("Humidity DHT: " + String(data.humidity, 1) + "% ");
      LCD.setCursor(0, 3);
      LCD.print("Lux Value=");
      LCD.setCursor(11, 3);
      LCD.print(lux);
      delay(4000); 
      LCD.clear();
      LCD.setCursor(0, 0);
      LCD.println("temperature MPU :");
      LCD.setCursor(12, 0);
      LCD.println(temp.temperature);
      LCD.setCursor(17, 0);
      LCD.println("deg");
      LCD.setCursor(0,1);
      LCD.print("Dist cm =");
      LCD.setCursor(10,1);
      LCD.print(distance_cm);
      delay(4000);
      LCD.clear();
      LCD.setCursor(0, 0);
      LCD.println("Acceleration:");
      LCD.setCursor(0, 1);
      LCD.println("axe x:");
      LCD.setCursor(7, 1);
      LCD.println(a.acceleration.x);
      LCD.setCursor(0, 2);
      LCD.println("axe y:");
      LCD.setCursor(7, 2);
      LCD.println(a.acceleration.y);
      LCD.setCursor(0, 3);
      LCD.println("axe z:");
      LCD.setCursor(7, 3);
      LCD.println(a.acceleration.z);
      delay(4000);
      LCD.clear();
      LCD.setCursor(0, 0);
      LCD.println("Rotation:");
      LCD.setCursor(0, 1);
      LCD.println("axe X:");
      LCD.setCursor(7, 1);
      LCD.println(xdeg);
      LCD.setCursor(0, 2);
      LCD.println("axe Y:");
      LCD.setCursor(7, 2);
      LCD.println(ydeg);
      LCD.setCursor(0, 3);
      LCD.println("axe Z:");
      LCD.setCursor(7, 3);
      LCD.println(zdeg); 
      delay(4000);
      }

  if (!client.connected()) {
    reconnect(); // reconnect if losing connexion MQTT 
  }
   client.loop();
/***************envoie data via wifi to MQTT server **********/

      String MPU_ACC_X = String(a.acceleration.x, 1);
      String  MPU_ACC_Y = String(a.acceleration.y, 1);
      String MPU_ACC_Z = String(a.acceleration.z, 1);
      String  MPU_ROT_X = String(xdeg, 1);
      String  MPU_ROT_Y = String(ydeg, 1);
      String  MPU_ROT_Z = String(zdeg, 1);
      String  MPU_temp = String(temp.temperature, 1);
      String  LDR_lum = String(lux, 1);
      String  DHT_hum =String(data.humidity,1);
      String  DHT_temp=String(data.temperature,1);
      String  HC=String(distance_cm,1);
	
        client.publish("Acc_x", MPU_ACC_X.c_str()); 
        client.publish("Acc_y", MPU_ACC_Y.c_str());     
        client.publish("Acc_z", MPU_ACC_Z.c_str());
        client.publish("rot_x",MPU_ROT_X.c_str());
        client.publish("rot_y", MPU_ROT_Y.c_str());       
        client.publish("rot_z",MPU_ROT_Z.c_str());
        client.publish("MPU_temp",MPU_temp.c_str());  
        client.publish("lux", LDR_lum.c_str());
        client.publish("DHT_temp", DHT_temp.c_str());
        client.publish("DHT_hum", DHT_hum.c_str());
        client.publish("HC",HC.c_str());
        delay(100);
      LCD.setCursor(0, 0);
      LCD.print("----Affichage in----");
      LCD.setCursor(0, 1);
      LCD.print("-----dashboard------");
      LCD.setCursor(0, 2);
      LCD.print("                    ");
      LCD.setCursor(0, 3);
      LCD.print("                    ");

}