/*
  Proyecto: Sistema de Monitoreo Agrícola con ESP32
            SMART AGRO
  Autor: [Ramiro Lopera]
  Fecha: [2025]
  Descripción:
  - Mide temperatura y humedad ambiental DHT22/11 O simulados)
  - Controla 2 dispositivos via MQTT: broker.emqx.io - broker.hivemq.com - mosquitto
  - Muestra información en pantalla OLED
  - Publica datos a broker MQTT
  - Actualización en tiempo real de la interfaz gráfica
  - Lectura de sensores cada N segundos
  - Actualización del contador cada N segundos
  Hardware requerido:
  - ESP32
  - Pantalla OLED SSD1306 128x64
  - Sensor DHT11
  - 2 Módulos Relay
  - Conexión WiFi
  Diagrama de conexiones:
  DHT11:
  - VCC -> 3.3V
  - GND -> GND
  - DATA -> Pin ?
  OLED:
  - SDA -> GPIO 21
  - SCL -> GPIO 22
  Dispositivos:
  - Relay1  -> Pin 26
  - Servo1  -> Pin 27
*/
#include <myimages.h>
#include <WiFi.h>
#include <PubSubClient.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Wire.h>
#include <stdlib.h>
#include <Adafruit_Sensor.h>
#include <DHT.h>
#include <ESP32Servo.h>
// Configuración OLED
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
// Configuración del DHT11
#define DHTPIN 32
#define DHTTYPE DHT11
DHT dht(DHTPIN, DHTTYPE);
// Configuración de los dispositivos
const int RelayPin1 = 25;
const int ServoPin1 = 33;
// vinculo la librería del servo
Servo servo;
// Configuración WiFi
const char* ssid = "Wokwi-GUEST";
const char* password = "";
// Configuración MQTT
const char* mqtt_server = "broker.hivemq.com";  // broker.emqx.io - broker.hivemq.com
const char* tempTopic = "rlopera/AGRO/matera/temperatura";
const char* humeTopic = "rlopera/AGRO/matera/humedad";
const char* contTopic = "rlopera/AGRO/ingresos/contador";
const char* Relay1Topic = "rlopera/AGRO/riegojardin/relay";
const char* Servo1Topic = "rlopera/AGRO/puertagaraje/servo";
WiFiClient espClient;
PubSubClient client(espClient);
long lastMsg = 0;
int contador = 0;
float temperatura = 0;
float humedad = 0;
// Define las variables de actualización de la pantalla y el sensor
unsigned long lastDisplayUpdate = 0;
unsigned long lastSensorUpdate = 0;
// rutina para conectarse a la red WiFi
void setup_wifi() {
  delay(10);
  Serial.println();
  Serial.print("Conectando a ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi conectado");
  Serial.println("Dirección IP: ");
  Serial.println(WiFi.localIP());
}
void callback(char* topic, byte* message, unsigned int length) {
  Serial.print(topic);
  String msg;
  for (int i = 0; i < length; i++) {
    msg += (char)message[i];
  }
  Serial.println(" Mensaje: " + msg);
  // Control del Relay1
  if (String(topic) == Relay1Topic) {
    if (msg == "ON") {
      digitalWrite(RelayPin1, HIGH);
      Serial.println(" - Relay 1 ON");
    } else if (msg == "OFF") {
      digitalWrite(RelayPin1, LOW);
      Serial.println(" - Relay 1 OFF");
    }
  }
  // Control del Servo1
  if (String(topic) == Servo1Topic) {
    if (msg == "ON") {
       digitalWrite(ServoPin1, HIGH);
          servo.write(0);
      Serial.println(" - Servo 1 ON");
    } else if (msg == "OFF") {
       digitalWrite(ServoPin1, LOW);
          servo.write(90);
      Serial.println(" - Servo 1 OFF");
    }
  }
}
void reconnect() {
  while (!client.connected()) {
    Serial.print("Conectando al servidor MQTT...");
    if (client.connect("clientId-AGRORamiro123")) {
      Serial.println("Conectado");
      // Suscribirse a los tópicos para controlar los Dispositivos
      client.subscribe(Relay1Topic);
      client.subscribe(Servo1Topic);
    } else {
      Serial.print("Fallo, rc=");
      Serial.print(client.state());
      Serial.println(" Intentando de nuevo en 5 segundos...");
      delay(5000);
    }
  }
}
void setup() {
  // Configuración serial
  Serial.begin(115200);
  // Configuración de los dispositivos
  pinMode(RelayPin1, OUTPUT);
//  pinMode(ServoPin1, OUTPUT);
  digitalWrite(RelayPin1, LOW);  // se establecen los dispositivos apagados
  digitalWrite(ServoPin1, LOW);
  // Configuración del sensor DHT11
  dht.begin();
// Mapeamos el servo para PWM
  servo.attach(ServoPin1, 500, 2400);
  // Configuración de la pantalla OLED
  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println(F("No se encuentra la pantalla OLED"));
    while (true)
      ;
  }
  // display.setRotation(2);  //180 grados
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0, 0);
  display.print("Conectando WiFi...");
  display.display();
  // Conectar a WiFi
  setup_wifi();
  // Configurar MQTT
  client.setServer(mqtt_server, 1883);
  client.setCallback(callback);
  // Mostrar en la pantalla OLED
  display.clearDisplay();
  display.setCursor(0, 0);
  display.print("Conectado a WiFi");
  display.display();
}
void loop() {
  if (!client.connected()) {
    reconnect();
  }
  client.loop();
  unsigned long now = millis();
  // Actualización de pantalla (frecuente)
  if (now - lastDisplayUpdate > 200) {  // Actualizar cada 200 ms (ajustable)
    lastDisplayUpdate = now;
    // Obtener información de la red WiFi
    int32_t rssi = WiFi.RSSI();
    IPAddress ip = WiFi.localIP();
    // Mostrar los datos en la pantalla OLED
    display.clearDisplay();
    display.setTextSize(1);
    display.drawRoundRect(0, 0, 128, 64, 5, WHITE);
    display.drawBitmap(2, 0, DataTemp, 10, 20, 1);
    display.drawBitmap(75, 0, DataHum, 10, 20, 1);
    display.setCursor(12, 2);
    display.setTextSize(2);
    display.print(temperatura, 1);
    display.setTextSize(1);
    display.print((char)247);
    display.print("C");
    display.setCursor(85, 2);
    display.setTextSize(2);
    display.print(humedad, 0);
    display.setTextSize(2);
    display.print("%");
    display.setCursor(2, 20);
    display.setTextSize(1);
    display.print(ip);
    display.setCursor(100, 20);
    display.print(contador);
    display.setCursor(5, 28);
    display.print(ssid);
    display.print("(");
    display.print(rssi);
    display.print(")");
    String Relay1State = digitalRead(RelayPin1) ? "ON" : "OFF";
    String Servo1State = digitalRead(ServoPin1) ? "ON" : "OFF";
  // Serial.println("===");Serial.println(digitalRead(ServoPin1));Serial.println("===");
    if (Relay1State == "ON") { display.drawBitmap(5, 42, riego_on, 15, 20, SSD1306_WHITE); }
    if (Relay1State == "OFF") { display.drawBitmap(5, 42, riego_off, 15, 20, SSD1306_WHITE); }
    if (Servo1State == "ON") { display.drawBitmap(25, 42, puerta_on, 15, 20, SSD1306_WHITE); }
    if (Servo1State == "OFF") { display.drawBitmap(25, 42, puerta_off, 15, 20, SSD1306_WHITE); }
    display.display();
  }
  // Actualización de sensor y envío MQTT (cada 10 segundos)
  if (now - lastSensorUpdate > 10000) {
    lastSensorUpdate = now;
    contador++;
    temperatura = random(200, 500) / 10.00;  // dht.readTemperature(); //
    humedad = random(10, 999) / 10.00;       // dht.readHumidity(); //
    char tempString[8];
    dtostrf(temperatura, 1, 2, tempString);
    client.publish(tempTopic, tempString);
    char humeString[8];
    dtostrf(humedad, 1, 2, humeString);
    client.publish(humeTopic, humeString);
    char contString[8];
    itoa(contador, contString, 10);
    client.publish(contTopic, contString);
    Serial.print("Temp: ");
    Serial.print(temperatura);
    Serial.print(" °C, Hum: ");
    Serial.print(humedad);
    Serial.print(" %, Count: ");
    Serial.println(contador);
  }
}
/*
Documentación del Proyecto
📋 Descripción General
Sistema IoT para monitoreo agrícola que incluye:
Lectura de temperatura y humedad ambiental
Control remoto de dispositivos mediante relay y servo
Visualización en tiempo real en pantalla OLED
Comunicación mediante protocolo MQTT
🛠 Hardware Requerido
Componente        Especificaciones
Microcontrolador	ESP32
Pantalla	        OLED SSD1306 128x64 (I2C)
Sensor	          DHT11 (Temperatura/Humedad)
Relays	          1 módulos de 5V
Servos	          1 módulos de 5V
Alimentación	     DC
/proyecto-agricola
├── /include
│   └── myimages.h       # Bitmaps personalizados
├── proyecto-agricola.ino # Código principal
*/