"""
Simulacion de una Caja Fuerte con contraseña Alfanumerica la cual utiliza un Buzzer Pasivo,
LED RGB, Keypad 4x4, Servo la cual simula Cerrado/Abierto.
Se usaron 3 topicos. Para Cambiar/Resetear la clave, Para Controlar la Alarma, Para ver El estado de la caja
Se uso el Protocolo MQTT y el Broker IoAdafruit.
Logica: Al apretar la tecla...si la caja esta abierta se cierra el servo...Si NO!
Se concatena los caracteres al ir oprimiendo el keypad mientras la longitud sea < a 4...
Si fuese mayor se Reinicia el ingreso de clave...Entonces...
Si la tecla es '*' se reinicia el ingreso de clave
Si la tecla es '#' Confirmo la Clave y obersevamos si fue = o != a clave correcta
Mientras le vaya errando a la clave se incrementa la cantidad de errores y vamos informando
cuantos intentos queda, va sonando el error y publica en el broker
Si se paso de intentos...Mandamos un ON al control de alarma para que se ejecute el sonido alarma
tambien cerramos el servo y publicamos el estado.
Si no paso nada de eso es porque la clave fue clavada y hacemos sonar el sonido de exito, abrimos
el servo y reiniciamos los intentos.
SI la caja esta abierta se cierra oprimiendo cualquier tecla.
"""
from machine import Pin, PWM
from time import sleep
import network
import time
import machine
from umqtt.simple import MQTTClient
# -------- CONFIGURACIÓN DE RED Y MQTT --------
WIFI_SSID = 'Wokwi-GUEST' # Cambiar el Dia del Parcial
WIFI_PASS = ''
# USUARIO Y KEY DE ADAFRUIT IO
AIO_USER = 'nahuelcejass'
AIO_KEY = 'aio_rdNr38eCoOMiPga7TWh7eJIfSHng'
AIO_FEED_ALARMA = b'nahuelcejass/feeds/ApagarAlarma'
AIO_FEED_CLAVE = b'nahuelcejass/feeds/CambiarClave'
AIO_FEED_ESTADO = b'nahuelcejass/feeds/EstadoSistema'
MQTT_CLIENT_ID = 'esp32_alarma'
# -------- CONECTAR A WIFI --------
def conectar_wifi():
timeout=15
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
if not wlan.isconnected():
print('Conectando a WiFi...')
wlan.connect(WIFI_SSID, WIFI_PASS)
for i in range(timeout):
if wlan.isconnected():
break
print(f"Esperando conexión... ({i+1}s)")
time.sleep(1)
if wlan.isconnected():
print('WiFi conectado:', wlan.ifconfig())
else:
print('No se pudo conectar al WiFi.')
while True:
time.sleep(1)
# -------- CONECTAR A MQTT --------
def conectar_mqtt():
try:
client = MQTTClient(MQTT_CLIENT_ID, 'io.adafruit.com', user=AIO_USER, password=AIO_KEY)
client.set_callback(mqtt_callback)
client.connect()
client.subscribe(AIO_FEED_ALARMA)
client.subscribe(AIO_FEED_CLAVE)
print("Conectado a Adafruit IO MQTT")
return client
except Exception as e:
print("Error al conectar con Adafruit IO MQTT:")
print("Detalle:", str(e))
while True:
time.sleep(1)
# -------- VARIABLES --------
clave_correcta = "0000" # Clave de Fabrica
codigo_ingresado = ""
alarma_activa = False
intentos_fallidos = 0
caja_abierta = False
# -------- PINES --------
filas = [Pin(22, Pin.IN, Pin.PULL_UP),
Pin(21, Pin.IN, Pin.PULL_UP),
Pin(19, Pin.IN, Pin.PULL_UP),
Pin(18, Pin.IN, Pin.PULL_UP)]
columnas = [Pin(5, Pin.OUT),
Pin(17, Pin.OUT),
Pin(16, Pin.OUT),
Pin(4, Pin.OUT)]
teclas = [['1','2','3','A'],
['4','5','6','B'],
['7','8','9','C'],
['*','0','#','D']]
buzzer = PWM(Pin(13))
buzzer.duty(0) # Buzzer Apagado.
Rojo = PWM(Pin(27))
Verde = PWM(Pin(26))
Azul = PWM(Pin(25))
# -------- SERVO (abrir/cerrar caja) --------
servo = PWM(Pin(32), freq=50)
def abrir_servo():
servo.duty(120)
def cerrar_servo():
servo.duty(30)
# -------- LED RGB --------
def set_rgb(r, g, b):
Rojo.duty(r)
Verde.duty(g)
Azul.duty(b)
# -------- SONIDOS --------
def tono(frecuencia, duracion):
buzzer.freq(frecuencia)
buzzer.duty(512)
sleep(duracion)
buzzer.duty(0)
def sonido_exito():
set_rgb(1023, 0, 1023) # Verde Si fue concedido
tono(1000, 0.2)
sleep(0.1)
tono(1500, 0.2)
set_rgb(0, 0, 0) # Apagar Led
def sonido_error():
set_rgb(0, 1023, 1023) # Rojo Si hubo error
tono(300, 0.1)
sleep(0.05)
tono(200, 0.2)
set_rgb(0, 0, 0) # Apagar
def sonido_alarma():
tono(800,0.2)
set_rgb(1023,1023,0) # Rojo
sleep(0.1)
tono(800,0.2)
set_rgb(0,1023,1023) # Azul
sleep(0.1)
set_rgb(0, 0, 0) # Apagado
def sonido_reinicio():
set_rgb(0, 512, 512) # Luz Amarilla tenue
tono(600, 0.1)
sleep(0.05)
tono(400, 0.1)
set_rgb(0, 0, 0) # Apagado
# -------- TECLADO --------
def leer_tecla():
for col in range(4):
for c in range(4):
columnas[c].value(1)
columnas[col].value(0)
for fil in range(4):
if filas[fil].value() == 0:
sleep(0.2)
while filas[fil].value() == 0:
pass
return teclas[fil][col]
return None
# -------- CALLBACK GENERAL --------
def mqtt_callback(topic, msg):
print("Mensaje recibido:")
print(" Topic:", topic)
print(" Mensaje:", msg)
if topic == AIO_FEED_ALARMA:
manejar_alarma(msg)
elif topic == AIO_FEED_CLAVE:
manejar_cambio_clave(msg)
# -------- MANEJADORES --------
def manejar_alarma(msg):
global alarma_activa, intentos_fallidos
if msg == b'OFF':
alarma_activa = False
intentos_fallidos = 0
buzzer.duty(0)
print("Alarma desactivada desde Adafruit IO")
client.publish(AIO_FEED_ESTADO, "Alarma desactivada desde Adafruit IO") # Importante
cerrar_servo()
elif msg == b'ON':
alarma_activa = True
print("Alarma activada desde Adafruit IO")
client.publish(AIO_FEED_ESTADO, "Alarma activada desde Adafruit IO")
cerrar_servo()
def manejar_cambio_clave(msg):
global clave_correcta
caracteres_permitidos = ['1','2','3','A','4','5','6','B','7','8','9','C','0','D']
texto = msg.decode('utf-8').strip().upper()
print(f"Clave recibida: '{texto}'")
if len(texto) != 4:
print("Error: La clave debe tener 4 caracteres")
client.publish(AIO_FEED_ESTADO, "Debe tener 4 Caracteres")
return
for caracter in texto:
if caracter not in caracteres_permitidos:
print("Error. Caracteres Invalidos!")
client.publish(AIO_FEED_ESTADO,"Error. Caracteres Invalidos!")
return
clave_correcta = texto
print(f"Clave actualizada: {clave_correcta}")
client.publish(AIO_FEED_ESTADO,f"Clave cambiada correctamente ({clave_correcta})")
# -------- INICIO --------
conectar_wifi()
client = conectar_mqtt()
set_rgb(0, 900, 1023)
sleep(0.5)
set_rgb(0, 0, 0)
cerrar_servo()
client.publish(AIO_FEED_ALARMA, "OFF")
client.publish(AIO_FEED_ESTADO, "Sistema inicializado y alarma desactivada")
# -------- BUCLE PRINCIPAL --------
while True:
client.check_msg()
if alarma_activa:
sonido_alarma() # Bloqueamos el Teclado Por si suena la Alarma
continue
tecla = leer_tecla()
if tecla:
if caja_abierta: #Si el servo esta abierto, al presionar cualquier tecla lo cierra y luego se ingresa otro codigo
cerrar_servo()
caja_abierta = False
elif tecla == "#":
if codigo_ingresado == clave_correcta:
print("Clave correcta")
sonido_exito()
intentos_fallidos = 0
client.publish(AIO_FEED_ESTADO, "Acceso concedido - Clave correcta")
abrir_servo()
caja_abierta = True
else:
intentos_fallidos += 1
print(f"Clave incorrecta (Intento {intentos_fallidos}/3)")
sonido_error()
client.publish(AIO_FEED_ESTADO, f"Clave incorrecta - Intento {intentos_fallidos}/3")
if intentos_fallidos >= 3:
print("Máximo de intentos alcanzado - Activando alarma!")
client.publish(AIO_FEED_ALARMA, "ON")
client.publish(AIO_FEED_ESTADO, "Alarma activada por 3 intentos fallidos")
cerrar_servo()
codigo_ingresado = ""
elif tecla == "*":
print("Código reiniciado")
sonido_reinicio()
codigo_ingresado = ""
elif len(codigo_ingresado) < 4:
codigo_ingresado += tecla
print("Código actual:", codigo_ingresado)
elif len(codigo_ingresado) >= 4:
codigo_ingresado = ""
print("Ingreso de Clave Reiniciada")
sonido_reinicio()
sleep(0.1)