// https://www.hivemq.com/mqtt/public-mqtt-broker/
#include <WiFi.h>
#include <PubSubClient.h>
#include <DHT.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
// Configuración OLED
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_ADDR 0x3C
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
// Configuración DHT11/22
#define DHTPIN 14
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);
// Configuración LEDs
#define LED1_PIN 25
#define LED2_PIN 26
// Configuración WiFi
const char* ssid = "Wokwi-GUEST";
const char* password = "";
// Configuración MQTT (HiveMQ)
const char* mqtt_server = "broker.hivemq.com";
const int mqtt_port = 1883;
const char* temp_topic = "profelopera/dht11/temperatura";
const char* hum_topic = "profelopera/dht11/humedad";
const char* led1_topic = "profelopera/led1/control";
const char* led2_topic = "profelopera/led2/control";
WiFiClient espClient;
PubSubClient client(espClient);
// Variables globales
unsigned long lastMsg = 0;
int counter = 0;
float temperatura = 0;
float humedad = 0;
// Función para conectar WiFi
void setup_wifi() {
delay(10);
Serial.println("\nConectando a WiFi: " + String(ssid));
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("\n✅ WiFi conectado");
Serial.print("📡 IP: ");
Serial.println(WiFi.localIP());
Serial.print("📶 RSSI: ");
Serial.println(WiFi.RSSI());
Serial.print("🖧 MAC: ");
Serial.println(WiFi.macAddress());
}
// Función para conectar MQTT
void reconnect_mqtt() {
while (!client.connected()) {
Serial.print("Conectando a MQTT...");
String clientId = "ESP32profeLopera-" + String(random(0xffff), HEX);
if (client.connect(clientId.c_str())) {
Serial.println("✅ Conectado a HiveMQ");
// Suscribirse a los topics de control de LEDs
client.subscribe(led1_topic);
client.subscribe(led2_topic);
Serial.println("📡 Suscrito a topics de control");
} else {
Serial.print("❌ Falló, rc=");
Serial.print(client.state());
Serial.println(" Reintentando en 5 segundos");
delay(5000);
}
}
}
// Callback para mensajes MQTT entrantes
void callback(char* topic, byte* payload, unsigned int length) {
String message;
for (int i = 0; i < length; i++) {
message += (char)payload[i];
}
Serial.print("📨 Mensaje recibido en: ");
Serial.print(topic);
Serial.print(" -> ");
Serial.println(message);
// Control LED 1
if (String(topic) == led1_topic) {
if (message == "ON") {
digitalWrite(LED1_PIN, HIGH);
Serial.println("💡 LED 1 ENCENDIDO");
} else if (message == "OFF") {
digitalWrite(LED1_PIN, LOW);
Serial.println("💡 LED 1 APAGADO");
}
}
// Control LED 2
if (String(topic) == led2_topic) {
if (message == "ON") {
digitalWrite(LED2_PIN, HIGH);
Serial.println("💡 LED 2 ENCENDIDO");
} else if (message == "OFF") {
digitalWrite(LED2_PIN, LOW);
Serial.println("💡 LED 2 APAGADO");
}
}
}
// Función para actualizar OLED
void update_display() {
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
// Mostrar información WiFi
display.setCursor(0, 0);
display.println("=== WiFi Info ===");
display.print("");
display.println(ssid);
display.print("");
display.print(WiFi.localIP());
display.print(" (");
display.print(WiFi.RSSI());
display.println(" dBm)");
display.print("MAC ");
display.println(WiFi.macAddress());
// Mostrar sensores
display.println("=== Sensores ===");
display.print("T: ");
display.print(temperatura, 1);
display.print("C - ");
display.print("H: ");
display.print(humedad, 0);
display.println(" %");
// Mostrar estado LEDs
display.println("=== Actuadores ===");
display.print("LED1: ");
display.print(digitalRead(LED1_PIN) ? "ON " : "OFF");
display.print(" - LED2: ");
display.println(digitalRead(LED2_PIN) ? "ON " : "OFF");
display.display();
}
void setup() {
Serial.begin(115200);
// Inicializar LEDs
pinMode(LED1_PIN, OUTPUT);
pinMode(LED2_PIN, OUTPUT);
digitalWrite(LED1_PIN, LOW);
digitalWrite(LED2_PIN, LOW);
// Inicializar OLED
if(!display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDR)) {
Serial.println("❌ Error en OLED");
}
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.println("Iniciando...");
display.display();
// Inicializar DHT11
dht.begin();
// Conectar WiFi
setup_wifi();
// Configurar MQTT
client.setServer(mqtt_server, mqtt_port);
client.setCallback(callback);
// Actualizar display con información inicial
update_display();
}
void loop() {
// Mantener conexión MQTT
if (!client.connected()) {
reconnect_mqtt();
}
client.loop();
// Enviar datos cada 3 segundos
unsigned long now = millis();
if (now - lastMsg > 3000) {
lastMsg = now;
counter++;
// Leer sensores
temperatura = dht.readTemperature();
humedad = dht.readHumidity();
// Verificar lecturas válidas
if (isnan(temperatura) || isnan(humedad)) {
Serial.println("❌ Error leyendo DHT11");
temperatura = 0;
humedad = 0;
}
// Mostrar en Serial
Serial.println("\n=== Envío #" + String(counter) + " ===");
Serial.print("🌡️ Temperatura: ");
Serial.print(temperatura);
Serial.print(" °C - ");
Serial.print("💧 Humedad: ");
Serial.print(humedad);
Serial.println(" %");
// Publicar datos por MQTT
char tempStr[8];
char humStr[8];
dtostrf(temperatura, 1, 2, tempStr);
dtostrf(humedad, 1, 2, humStr);
client.publish(temp_topic, tempStr);
client.publish(hum_topic, humStr);
client.publish("profelopera/network/ssid", ssid);
client.publish("profelopera/network/ip", WiFi.localIP().toString().c_str());
client.publish("profelopera/network/rssi", String(WiFi.RSSI()).c_str());
client.publish("profelopera/network/mac", WiFi.macAddress().c_str());
Serial.print("✅ Datos publicados en MQTT - ");
Serial.println("📊 Contador: " + String(counter));
// Actualizar pantalla OLED
update_display();
}
delay(100);
}