from machine import Pin, ADC, PWM
from time import sleep
import network
import time
from umqtt.simple import MQTTClient
# =========================================================
# CONFIGURACIÓN
# =========================================================
SSID = "Wokwi-GUEST"
PASSWORD = ""
MQTT_BROKER = "broker.hivemq.com"
CLIENT_ID = "esp32_nora_125896estado_9922"
TOPIC_ESTADO = b"iot/seguridad/estado"
TOPIC_LUZ = b"iot/seguridad/luz"
TOPIC_MOVIMIENTO = b"iot/seguridad/movimiento"
TOPIC_PUERTA = b"iot/seguridad/puerta"
TOPIC_GAS = b"iot/seguridad/gas"
TOPIC_ALERTA = b"iot/seguridad/alerta"
# Pines según tu diagrama
pir = Pin(14, Pin.IN)
btn = Pin(13, Pin.IN, Pin.PULL_UP)
ldr = ADC(Pin(34))
ldr.atten(ADC.ATTN_11DB)
pot_gas = ADC(Pin(35))
pot_gas.atten(ADC.ATTN_11DB)
led_rojo = Pin(21, Pin.OUT) # ROJO Puerta
led_extra = Pin(18, Pin.OUT) # VERDE (Estado A/D)
led_gas = Pin(19, Pin.OUT) # AMARILLO Gas
led_blanco = Pin(5, Pin.OUT) # BLANCO Dia/noche
buzzer = PWM(Pin(27))
buzzer.freq(1000)
buzzer.duty(0)
servo = PWM(Pin(33), freq=50)
# =========================================================
# VARIABLES GLOBAL
# =========================================================
armado = False
estado_btn_ant = 1
cliente = None
# =========================================================
# FUNCIONES DE APOYO
# =========================================================
def conectar_wifi():
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
wlan.connect(SSID, PASSWORD)
print("Conectando WiFi", end="")
for _ in range(10): # Reintenta 10 segundos
if wlan.isconnected(): break
print(".", end="")
sleep(1)
if wlan.isconnected():
print("\nWiFi OK:", wlan.ifconfig()[0])
else:
print("\nWiFi FALLÓ (Modo Local)")
def conectar_mqtt():
global cliente
try:
c = MQTTClient(CLIENT_ID, MQTT_BROKER, keepalive=60)
c.connect()
print("MQTT OK")
return c
except:
print("MQTT FALLÓ (Modo Local)")
return None
def enviar_msg(tema, msg):
if cliente:
try:
cliente.publish(tema, msg)
except:
pass
def mover_servo(angulo):
# Ajuste para Wokwi: 40 cerrado, 115 abierto
servo.duty(angulo)
# =========================================================
# INICIO
# =========================================================
conectar_wifi()
cliente = conectar_mqtt()
mover_servo(40) # Iniciar cerrado
print("SISTEMA INICIADO")
estado_previo = None
puerta_anterior = None
movimiento_anterior = None
last_send_gas = time.time()
gas_anterior = None
alerta_gas_anterior = None
alarma_anterior = None
luz_anterior = None
auto_armado_noche = False
armado = False
estado_btn_ant = 1
led_extra.off()
# =========================================================
# BUCLE PRINCIPAL
# =========================================================
while True:
# 1. BOTÓN DE ARMADO
val_btn = btn.value()
if val_btn == 0 and estado_btn_ant == 1:
armado = not armado
led_extra.value(1 if armado else 0)
if armado:
print("SISTEMA: ARMADO")
enviar_msg(TOPIC_ESTADO, "ARMADO")
else:
buzzer.duty(0)
print("SISTEMA: DESARMADO")
enviar_msg(TOPIC_ESTADO, "DESARMADO")
sleep(0.3)
estado_btn_ant = val_btn
# 2. SENSOR DE LUZ (LDR)
v_luz = ldr.read()
# Determinamos el estado actual
if v_luz > 3000:
estado_actual = "NOCHE"
else:
estado_actual = "DIA"
if estado_actual == "NOCHE":
armado = True
if auto_armado_noche == False:
print("Sistema: ARMADO AUTOMATICAMENTE POR NOCHE")
enviar_msg(TOPIC_ESTADO, "ARMADO")
auto_armado_noche = True
else:
auto_armado_noche = False
# Solo ejecutamos si hay un CAMBIO
if estado_actual != estado_previo:
if estado_actual == "NOCHE":
led_blanco.on()
print("Noche detectada. Valor del sensor:", v_luz)
enviar_msg(TOPIC_LUZ, "NOCHE") # AGREGAR
else:
# Como ya sabemos que no es noche, obligatoriamente es día
led_blanco.off()
print("Día detectado. Valor del sensor:", v_luz)
enviar_msg(TOPIC_LUZ, "DIA") # AGREGAR
# Actualizamos el estado para la siguiente comparación
estado_previo = estado_actual
## 3. SENSOR PIR Y PUERTA
v_pir = pir.value()
if v_pir == 1:
mover_servo(115) # Abre
led_rojo.on() # Rojo indica puerta abierta
if movimiento_anterior != "SI":
print("Movimiento: SI")
enviar_msg(TOPIC_MOVIMIENTO, "SI")
movimiento_anterior = "SI"
if puerta_anterior != "ABIERTA":
print("Puerta: ABIERTA")
enviar_msg(TOPIC_PUERTA, "ABIERTA")
puerta_anterior = "ABIERTA"
if armado and estado_actual == "NOCHE": #cambio
buzzer.duty(512)
enviar_msg(TOPIC_ALERTA, "PUERTA ABIERTA DE NOCHE")
else:
mover_servo(40) # Cierra
led_rojo.off() # Rojo se apaga si puerta cerrada
if movimiento_anterior != "NO":
print("Movimiento: NO")
enviar_msg(TOPIC_MOVIMIENTO, "NO")
movimiento_anterior = "NO"
if puerta_anterior != "CERRADA":
print("Puerta: CERRADA")
enviar_msg(TOPIC_PUERTA, "CERRADA")
puerta_anterior = "CERRADA"
# 4. SENSOR DE GAS
v_gas = pot_gas.read() # Lee el valor analógico del sensor/potenciómetro de gas
# Enviar e imprimir dato cada 2 segundos
if armado and (time.time() - last_send_gas) >= 2:
print("Gas:", v_gas) # Imprime en consola
enviar_msg(TOPIC_GAS, str(v_gas)) # Envía valor a MQTT
print("MQTT GAS ENVIADO:", v_gas)
last_send_gas = time.time() # Actualiza el tiempo del último envío
# Lógica de alarma inmediata
if v_gas > 2000:
led_gas.on()
if armado:
buzzer.duty(512)
if alerta_gas_anterior != "GAS":
print("Alerta: GAS detectado | Valor:", v_gas)
enviar_msg(TOPIC_ALERTA, "GAS!")
alerta_gas_anterior = "GAS"
else:
led_gas.off()
buzzer.duty(0)
if alerta_gas_anterior != "NORMAL":
print("Gas normal | Valor:", v_gas)
enviar_msg(TOPIC_ALERTA, "GAS_NORMAL")
alerta_gas_anterior = "NORMAL"
# 5. MANTENER CONEXIÓN
sleep(0.1)