# Tarea 4 Flujo de comunicación IoT bidireccional
"""
# Nombre: Flujo de comunicación IoT bidireccional
# Objetivo:
Comprobar la comunicación IoT bidireccional entre un ESP32
simulado en Wokwi y el cliente HiveMQ Web Client, publicando
datos de temperatura y humedad, y controlando un LED mediante
comandos MQTT.
# Pines utilizados: 2, 17, 25 y 27
# Explicación del funcionamiento:
El sistema comienza conectando el ESP32 (simulado en Wokwi)
a la red Wi-Fi.
Una vez conectado, se enlaza al broker MQTT (HiveMQ).
El flujo tiene dos opciones:
1.Flujo de salida (Publicación):
El ESP32 lee el sensor DHT22 cada 5 segundos
y envía (publica) los datos de temperatura y humedad
al broker MQTT para que HiveMQ Web Client los muestre.
2.Flujo de entrada (Suscripción):
El ESP32 está suscrito a un tópico de comandos.
Cuando el usuario envía la orden "on" u "off"
desde HiveMQ Web Client, el broker retransmite
ese mensaje al ESP32. Al recibirlo, la función callback
evalúa el texto y enciende o apaga el LED,
publicando un mensaje de confirmación de estado
hacia la web.
# Describir problemas encontrados:
El sistema no recibía los comandos de HiveMQ de forma
inmediata y parecía congelado.
El comando "On" o "ON" no encendía el LED
solo funcionaba "on" en minúsculas.
# Solución aplicada:
Se uso la función time.ticks_diff()
para que la instrucción cliente.check_msg()
evalúe los comandos entrantes constantemente
en tiempo real.
Se agregó la función .lower()
para convertir todos los mensajes
a minúsculas.
# Conclusión:
Durante el desarrollo de la práctica,
logré comprobar cómo funciona verdaderamente la
comunicación bidireccional en IoT.
Aprendí a configurar el ESP32 para que
actuara como un transmisor leyendo los datos
del sensor de temperatura y humedad (DHT22)
y publicándolos en la nube
utilizando el protocolo MQTT.
Además aprendí que el microcontrolador también
puede 'escuchar' instrucciones de forma remota
al suscribirse a un tópico, lo que me permitió
controlar físicamente un actuador (encender y
apagar un LED) enviando comandos desde una página
web externa (HiveMQ Web Client) y recibir la
confirmación de su estado.
Lo que más me llamó la atención, fue comprender que
gracias a la conexión Wi-Fi y a los servidores
MQTT, es posible monitorear cualquier variable
y controlar hardware desde cualquier parte
en tiempo real.
"""
# IMPORTAR LIBRERÍAS
import network
import dht
import ujson
import time
from machine import Pin
from time import sleep
from umqtt.simple import MQTTClient
# DEFINIR COMPONENTES Y PINES
sensor_dht = dht.DHT22(Pin(17)) # DHT22 conectado al pin 17
led = Pin(2, Pin.OUT) # LED actuador conectado al pin 2
# CONFIGURACIÓN DE RED Y MQTT
ID_CLIENTE = "ESP32_Grupo01_Miriam"
SERVIDOR_MQTT = "broker.hivemq.com"
# Tópicos solicitados
TOPICO_DATOS = b"cnad/cursos_iot/grupo01/esp32_01/datos"
TOPICO_COMANDOS = b"cnad/cursos_iot/grupo01/esp32_01/led/set"
TOPICO_ESTADO = b"cnad/cursos_iot/grupo01/esp32_01/led/status"
# FUNCIÓN CALLBACK (Se ejecuta cuando llega un mensaje de HiveMQ)
def recepcion_mensajes(topic, msg):
print("\n[NUEVO COMANDO RECIBIDO]")
print("Tópico:", topic)
print("Mensaje:", msg)
# Convertimos el mensaje a minúsculas para evitar errores si escriben "On" u "ON"
comando = msg.decode('utf-8').lower()
if comando == "on":
led.value(1) # Encender LED
print("Acción: LED ENCENDIDO")
# Publicamos el nuevo estado para confirmar
cliente.publish(TOPICO_ESTADO, b"ON")
elif comando == "off":
led.value(0) # Apagar LED
print("Acción: LED APAGADO")
# Publicamos el nuevo estado para confirmar
cliente.publish(TOPICO_ESTADO, b"OFF")
# 5. CONECTAR A WI-FI
print("Conectando a Wi-Fi Wokwi-GUEST...")
wifi = network.WLAN(network.STA_IF)
wifi.active(True)
wifi.connect("Wokwi-GUEST", "")
while not wifi.isconnected():
sleep(0.5)
print(".", end="")
print("\n¡Wi-Fi conectado!")
# CONECTAR A MQTT Y SUSCRIBIRSE
print("Conectando a MQTT...")
cliente = MQTTClient(ID_CLIENTE, SERVIDOR_MQTT)
cliente.set_callback(recepcion_mensajes) # Le decimos qué función usar al recibir mensajes
cliente.connect()
cliente.subscribe(TOPICO_COMANDOS) # ¡Nos suscribimos para escuchar comandos!
print("¡Conectado y suscrito a comandos!")
# Variables para controlar el tiempo sin bloquear el sistema
tiempo_anterior = time.ticks_ms()
#CICLO PRINCIPAL
while True:
# Escuchar si llegaron comandos desde HiveMQ (No bloquea el código)
cliente.check_msg()
# Publicar datos del sensor cada 5 segundos
# Usamos ticks_diff en lugar de sleep() para poder seguir escuchando comandos
if time.ticks_diff(time.ticks_ms(), tiempo_anterior) > 5000:
try:
sensor_dht.measure()
temp = sensor_dht.temperature()
hum = sensor_dht.humidity()
# Formato JSON
datos = {
"temperatura": temp,
"humedad": hum
}
mensaje_datos = ujson.dumps(datos)
# Publicar
cliente.publish(TOPICO_DATOS, mensaje_datos)
print("\nPublicando datos:", mensaje_datos)
# Reiniciar el temporizador
tiempo_anterior = time.ticks_ms()
except Exception as e:
print("Error leyendo el sensor:", e)
sleep(0.1) # Pequeña pausa para estabilidad del simulador