"""
===========================================================
DEMOSTRACIÓN PRÁCTICA DE CONCURRENCIA
Sistema de Luces Inteligente con ESP32
===========================================================
"""
# ----------------------------------------------------------
# MÓDULOS NECESARIOS
# ----------------------------------------------------------
import _thread # ¡La clave para la concurrencia!
import time
from machine import Pin
# ----------------------------------------------------------
# CLASE LED
# ----------------------------------------------------------
class Led:
def __init__(self, pin, nombre="LED"):
self.led = Pin(pin, Pin.OUT) # Configurar como SALIDA
self.nombre = nombre
self.estado = False # Comienza apagado
print(f"[INICIALIZACIÓN] Creado {nombre} en pin {pin}")
def encender(self):
self.led.value(1)
self.estado = True
print(f"[{self.nombre}] ENCENDIDO")
def apagar(self):
self.led.value(0)
self.estado = False
print(f"[{self.nombre}] APAGADO")
def toggle(self):
"""
Cambia el estado actual
Si está encendido → lo apaga
Si está apagado → lo enciende
PRÁCTICA: ¿Dónde usarías esto en la vida real?
(Ej: Interruptor de luz, indicador de notificación)
"""
if self.estado:
self.apagar()
else:
self.encender()
def parpadear(self, rapidez=1):
self.encender()
time.sleep(rapidez) # ¡OJO! Esto DETIENE este hilo
self.apagar()
time.sleep(rapidez)
# ----------------------------------------------------------
# HILO 1: LED INTERNO
# ----------------------------------------------------------
def tarea_latido():
"""
OBJETIVO: Simular el latido del corazón del sistema
ANALOGÍA: Como el parpadeo del LED en una laptop
que indica que está funcionando, incluso cuando
no estás haciendo nada visible.
"""
print(" INICIANDO HILO 1: Sistema de latido")
# Creamos nuestro LED "corazón"
corazon = Led(2, "Corazón del Sistema")
ciclo = 0
while True: # ¡Bucle INFINITO! (hasta que apaguemos)
ciclo += 1
# Mensaje educativo:
print(f"\n[LATIDO #{ciclo}]", end=" ")
print("El sistema está VIVO y trabajando...")
# Comportamiento: Parpadeo RÁPIDO
corazon.parpadear(0.3) # 300ms
# ----------------------------------------------------------
# HILO 2: ALARMA (SEÑAL DE ADVERTENCIA)
# ----------------------------------------------------------
def tarea_alarma():
"""
OBJETIVO: Simular una señal de advertencia
APLICACIÓN REAL:
• Alarma de incendios
• Indicador de batería baja
• Alerta de temperatura alta
"""
print("INICIANDO HILO 2: Sistema de alarma")
alarma = Led(4, "ALARMA")
ciclo = 0
while True:
ciclo += 1
print(f"[ALARMA #{ciclo}] Verificando condiciones de seguridad...")
# Comportamiento: Parpadeo LENTO (como alarma real)
alarma.parpadear(1) # 1 segundo
# ----------------------------------------------------------
# HILO 3: INDICADOR RGB (ESTADO DEL SISTEMA)
# ----------------------------------------------------------
def tarea_estado():
"""
OBJETIVO: Mostrar estados complejos con colores
PENSAMIENTO COMPUTACIONAL:
Un solo LED RGB puede mostrar MÚLTIPLES estados
usando combinaciones de colores.
"""
print("INICIANDO HILO 3: Indicador de estado RGB")
# Configurar los 3 pines del RGB
rojo = Pin(16, Pin.OUT)
verde = Pin(17, Pin.OUT)
azul = Pin(18, Pin.OUT)
# Estados predefinidos del sistema:
estados = [
(1, 0, 0), # ROJO: Error crítico
(0, 1, 0), # VERDE: Todo normal
(0, 0, 1), # AZUL: Modo configuración
(1, 1, 0), # AMARILLO: Advertencia
(1, 0, 1), # MAGENTA: Procesando datos
(0, 1, 1), # CIAN: Conectado a red
]
ciclo = 0
while True:
ciclo += 1
# Rotar por todos los estados
estado_actual = estados[ciclo % len(estados)]
# Aplicar el estado
rojo.value(estado_actual[0])
verde.value(estado_actual[1])
azul.value(estado_actual[2])
# Mensaje educativo
colores = ["ROJO", "VERDE", "AZUL", "AMARILLO",
"MAGENTA", "CIAN"]
print(f"[ESTADO #{ciclo}] Color: {colores[ciclo % 6]}")
time.sleep(2) # Mantener cada color 2 segundos
# ----------------------------------------------------------
# PROGRAMA PRINCIPAL
# ----------------------------------------------------------
if __name__ == "__main__":
print("=" * 60)
print(" SISTEMA CONCURRENTE DE GESTIÓN DE LUCES")
print("=" * 60)
print("\nFASE 1: Inicializando componentes...")
# DEMOSTRACIÓN: ¿Qué pasaría sin concurrencia?
print("\n" + "-" * 40)
print("SIMULACIÓN SIN CONCURRENCIA (PROBLEMA):")
print("-" * 40)
print("""
Si ejecutáramos secuencialmente:
1. LED Corazón parpadea rápido ✓
Pero... ¡los otros LEDs ESPERAN!
2. LED Alarma parpadea lento ✓
Pero... ¡el corazón DEJA de latir!
3. RGB cambia colores ✓
Pero... ¡todo lo demás se DETIENE!
RESULTADO: Sistema INÚTIL
""")
input("Presiona Enter para ver la solución con concurrencia...")
print("\n" + "-" * 40)
print("SOLUCIÓN: CON PROGRAMACIÓN CONCURRENTE")
print("-" * 40)
print("""
CON 3 HILOS (LA SOLUCIÓN):
┌────────────────────────────┐
│ HILO 1: Latido constante (no se detiene) │
│ HILO 2: Alarma intermitente (independ.) │
│ HILO 3: Cambio de estados (autónomo) │
└────────────────────────────┘
TODOS funcionan "al mismo tiempo"
NINGUNO bloquea a los otros
El sistema es RESPONSIVO
""")
# ------------------------------------------------------
# ¡EL MOMENTO MÁGICO: CREAR LOS HILOS!
# ------------------------------------------------------
print("\n" + "🔧" * 20)
print("CREANDO HILOS CONCURRENTES...")
print("🔧" * 20)
try:
# Crear hilo 1: Latido del sistema
_thread.start_new_thread(tarea_latido, ())
print(" HILO 1 CREADO: Sistema de latido")
time.sleep(0.5) # Pequeña pausa para ver mensajes
# Crear hilo 2: Sistema de alarma
_thread.start_new_thread(tarea_alarma, ())
print(" HILO 2 CREADO: Sistema de alarma")
time.sleep(0.5)
# Crear hilo 3: Indicador de estado
_thread.start_new_thread(tarea_estado, ())
print(" HILO 3 CREADO: Indicador RGB")
except Exception as error:
print(f" ERROR: {error}")
print("¿Tu ESP32 está bien conectado?")
print("\n" + "✨" * 20)
print("¡SISTEMA EN FUNCIONAMIENTO!")
print("✨" * 20)
print("""
OBSERVA EN TU ESP32:
• LED interno: Parpadea RÁPIDO (latido)
• LED externo: Parpadea LENTO (alarma)
• LED RGB: Cambia de color cada 2 segundos
╔════════════════════════════════════════════╗
║ ¡MAGIA DE LA CONCURRENCIA! ║
║ ║
║ 3 tareas DIFERENTES ║
║ 3 ritmos DIFERENTES ║
║ 1 solo procesador ESP32 ║
║ = APARIENCIA de simultaneidad ║
╚════════════════════════════════════════════╝
""")
print("\n PROGRAMA PRINCIPAL ACTIVO")
print(" (Coordinando desde segundo plano)")
# Mantener el programa corriendo
try:
contador = 0
while True:
contador += 1
print(f"\n [MAIN] Reporte #{contador}: Todos los hilos activos ✓")
time.sleep(5) # Espera larga para no saturar
except KeyboardInterrupt:
print("\n\n Sistema detenido por el usuario")
print(" ¡Hasta la próxima!")