#include <DHT.h>  
#include <WiFi.h>
#include <PubSubClient.h>
#include "Adafruit_VL53L0X.h"

// Definições do sensor DHT
#define DHTPIN 26     // Pino digital onde o DHT11 está conectado
#define DHTTYPE DHT11 // Define o tipo de sensor DHT11

// Definições do Wi-Fi e MQTT
const char* ssid = "Wokwi-GUEST";
const char* password = "";
const char* mqtt_server = "test.mosquitto.org";

WiFiClient espClient;
PubSubClient client(espClient);

// Instancia o objeto DHT
DHT dht(DHTPIN, DHTTYPE);

// Instancia o sensor VL53L0X
Adafruit_VL53L0X lox = Adafruit_VL53L0X();

// Pinos dos sensores
int sensorPin = 25;
int windDirectionPin = 27;
int sensorPin3 = 33;

// Variáveis globais
int Velocidade;
int direcao;
int Nivel;
int Nivelrio;
float temp ;
float humidity;

unsigned long ul_timeToSendMqtt;

void setup_wifi() { 
  delay(10);
  Serial.println();
  Serial.print("Conectando a ");
  Serial.println(ssid);

  WiFi.begin(ssid, password);
  delay(3000);
  while (WiFi.status() != WL_CONNECTED) {
    delay(3000);
    Serial.print(".");
  }

  Serial.println("");
  Serial.println("WiFi conectado");
  Serial.println("Endereço IP: ");
  Serial.println(WiFi.localIP());
}

void reconnect() {
  while (!client.connected()) {
    Serial.print("Tentando conexão MQTT...");
    if (client.connect("ESP32Clientxyz")) {
      Serial.println("conectado");
    } else {
      Serial.print("falhou, rc=");
      Serial.print(client.state());
      Serial.println(" tentando novamente em 5 segundos");
      delay(5000);
    }
  }
}

void setup() {
  // Inicializa a comunicação serial
  Serial.begin(115200);

  // Inicializa o Wi-Fi
  setup_wifi();
  client.setServer(mqtt_server, 1883);

  // Inicializa o sensor DHT
 // dht.begin();
/*
  // Inicializa o sensor VL53L0X
  if (!lox.begin()) {
    Serial.println(F("Failed to boot VL53L0X"));
    while(1);
  }
  Serial.println(F("VL53L0X API Simple Ranging example\n\n")); 
*/
  // Aguarda 2 segundos para estabilização dos sensores
  delay(2000);
}

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

  // Lê o valor analógico do anemômetro
  Velocidade = analogRead(sensorPin);
  Velocidade = map(Velocidade, 0, 4095, 0, 108);
  Velocidade +=5;
  if(Velocidade >4095) Velocidade =0;
  // Lê a direção do vento
  direcao = analogRead(windDirectionPin);
  direcao += 10;
  if(direcao >4095) direcao =0;
  String direcaoStr;
  if (direcao >= 0 && direcao < 584) {
    direcaoStr = "Norte";
  } else if (direcao >= 585 && direcao < 1168) {
    direcaoStr = "Nordeste";
  } else if (direcao >= 1169 && direcao < 1753) {
    direcaoStr = "Leste";
  } else if (direcao >= 1754 && direcao < 2341) {
    direcaoStr = "Sudeste";
  } else if (direcao >= 2342 && direcao < 2926) {
    direcaoStr = "Sul";
  } else if (direcao >= 2927 && direcao < 3514) {
    direcaoStr = "Sudoeste";
  } else if (direcao >= 3515 && direcao < 4018) {
    direcaoStr = "Oeste";
  } else if (direcao >= 4019 && direcao <= 4095) {
    direcaoStr = "Noroeste";
  }

  // Lê a temperatura e a umidade do sensor DHT11
  temp += 1.11;// dht.readTemperature();
  if(temp>100.0) temp = 0.0;
  humidity += 2.22;// dht.readHumidity();
  if(humidity>100.0) humidity = 0.0;
/*
  // Verifica se a leitura falhou
  if (isnan(temp) || isnan(humidity)) {
    Serial.println("Falha na leitura do sensor DHT!");
    return;
  }
*/
/*
  // Lê o nível usando o VL53L0X
  VL53L0X_RangingMeasurementData_t measure;
  lox.rangingTest(&measure, false);
  Nivel = measure.RangeMilliMeter;
*/

  // Lê o nível do rio 
  Nivelrio += 3.33; // analogRead(sensorPin3);
  Nivelrio += 3.33; // analogRead(sensorPin3);
  if(Nivelrio>4095) Nivelrio = 0;
  String NivelrioStr;
  if (Nivelrio >= 0 && Nivelrio <= 1365) {
    NivelrioStr = "abaixo de 1 metro";
  } else if (Nivelrio >= 1366 && Nivelrio <= 2730) {
    NivelrioStr = "abaixo de 2 metros";
  } else if (Nivelrio >= 2731 && Nivelrio <= 4095) {
    NivelrioStr = "abaixo de 3 metros";
  }

  if((millis() - ul_timeToSendMqtt)> 2000) {
  ul_timeToSendMqtt=millis();  
  // Publica os dados no MQTT
  char msg[50];
  snprintf(msg, 50, "Velocidade: %d km/h", Velocidade);
  client.publish("esp32/velocidade", msg);
  Serial.print("esp32/velocidade:  ");
  Serial.println(msg);

  snprintf(msg, 50, "Direcao: %s", direcaoStr.c_str());
  client.publish("esp32/direcao", msg);
  Serial.print("esp32/direcao:  ");
   Serial.println(msg);

  snprintf(msg, 50, "Temperatura: %.2f ºC", temp);
  client.publish("esp32/temperatura", msg);
   Serial.print("esp32/temperatura:  ");
   Serial.println(msg);

  snprintf(msg, 50, "Umidade: %.2f %%", humidity);
  client.publish("esp32/umidade", msg);
   Serial.print("esp32/umidade:  ");
   Serial.println(msg);

  snprintf(msg, 50, "Nivel: %d mm", Nivel);
  client.publish("esp32/nivel", msg);
   Serial.print("esp32/nivel:  ");
   Serial.println(msg);

  snprintf(msg, 50, "Nivelrio: %s", NivelrioStr.c_str());
  client.publish("esp32/nivelrio", msg);
    Serial.print("esp32/nivelrio:  ");
  Serial.println(msg);

  // Aguarda 2 segundos antes de repetir o loop
  //delay(2000);
  }
}