import machine, time, network, socket, ubinascii, urequests
from ir_rx.nec import NEC_8
# ==========================================
# 1. CONFIGURACIÓN DE USUARIO
# ==========================================
SSID, PASSWORD = "Tu_Nombre_Red", "Tu_Clave_WiFi"
USER, PASS = "admin", "pico123"
TOKEN = "TU_TOKEN_BOT_AQUI" # De @BotFather
CHAT_ID = "-100123456789" # ID numérico de tu grupo Familia
# ==========================================
# 2. CONFIGURACIÓN DE HARDWARE
# ==========================================
# Sensores y Control de Brillo
sensor_luz = machine.ADC(29)
pote_A = machine.ADC(26)
pote_B = machine.ADC(27)
umbral_oscuridad = 25000
# Salidas Permanentes (Relevadores)
for p in [10, 11]: machine.Pin(p, machine.Pin.OUT, value=0)
# 10 Canales Controlados (PWM para MOSFETs)
pines_ctrl = [16, 17, 18, 19, 20, 21, 22, 14, 15, 28]
canales_pwm = [machine.PWM(machine.Pin(p)) for p in pines_ctrl]
for pwm in canales_pwm: pwm.freq(1000)
# 10 Pulsadores Físicos (GP2 al GP9 + GP12, GP13)
pines_bt = [2, 3, 4, 5, 6, 7, 8, 9, 12, 13]
botones = [machine.Pin(p, machine.Pin.IN, machine.Pin.PULL_UP) for p in pines_bt]
# Bluetooth (UART)
uart = machine.UART(0, baudrate=9600, tx=machine.Pin(0), rx=machine.Pin(1))
# Variables de Estado
estados_logicos = [False] * 10
brillo_actual = [0.0] * 10
ultimo_estado_bt = [1] * 10
VELOCIDAD_FADE = 1800
auth_key = ubinascii.b2a_base64(f"{USER}:{PASS}".encode()).decode().strip()
# ==========================================
# 3. FUNCIONES CORE
# ==========================================
def enviar_telegram(msg):
try:
url = f"https://api.telegram.org/bot{TOKEN}/sendMessage?chat_id={CHAT_ID}&text={msg}"
urequests.get(url).close()
except: pass
def conmutar_canal(idx, origen):
if 0 <= idx < 10:
estados_logicos[idx] = not estados_logicos[idx]
est = "ENCENDIDO 🟢" if estados_logicos[idx] else "APAGADO 🔴"
enviar_telegram(f"🏠 @Woky_luz_bot:\nModulo {idx+1} {est}\nVia: {origen}")
def conectar_wifi():
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
wlan.connect(SSID, PASSWORD)
for _ in range(20):
if wlan.isconnected(): break
time.sleep(1)
return wlan.ifconfig()[0] if wlan.isconnected() else None
def generar_html():
luz = sensor_luz.read_u16()
html = "<!DOCTYPE html><html><head><meta charset='utf-8'><style>"
html += "body{background:#1a1a1a;color:white;text-align:center;font-family:sans-serif;}"
html += ".btn{display:inline-block;padding:20px;margin:10px;border-radius:10px;text-decoration:none;width:60px;font-weight:bold;}"
html += ".on{background:#00ff7f;color:black;} .off{background:#444;color:#888;}"
html += "</style></head><body><h1>@Woky_luz_bot</h1>"
html += f"<div>LDR: {luz} | Umbral: {umbral_oscuridad}</div><br>"
for i in range(10):
c = "on" if estados_logicos[i] else "off"
html += f'<a href="/?ch={i}" class="btn {c}">M{i+1}</a>'
if i == 4: html += "<br>"
html += "</body></html>"
return html
# ==========================================
# 4. INICIALIZACIÓN
# ==========================================
ip = conectar_wifi()
if ip: enviar_telegram(f"✅ Sistema Online\nIP: {ip}")
ir = NEC_8(machine.Pin(2, machine.Pin.IN), lambda d,a,c: conmutar_canal(
list({0x45:0,0x46:1,0x47:2,0x44:3,0x40:4,0x43:5,0x07:6,0x15:7,0x09:8,0x16:9}.values())
[list({0x45:0,0x46:1,0x47:2,0x44:3,0x40:4,0x43:5,0x07:6,0x15:7,0x09:8,0x16:9}.keys()).index(d)], "IR")
if d in [0x45,0x46,0x47,0x44,0x40,0x43,0x07,0x15,0x09,0x16] else None)
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(('', 80))
server.listen(5)
server.setblocking(False)
# ==========================================
# 5. BUCLE PRINCIPAL
# ==========================================
while True:
# A. Pulsadores
for i in range(10):
v = botones[i].value()
if v == 0 and ultimo_estado_bt[i] == 1:
conmutar_canal(i, "Pulsador")
time.sleep(0.1)
ultimo_estado_bt[i] = v
# B. Fade y LDR
luz_v = sensor_luz.read_u16()
br_A, br_B = pote_A.read_u16(), pote_B.read_u16()
for i in range(10):
obj = (br_A if i < 5 else br_B) if (estados_logicos[i] and luz_v < umbral_oscuridad) else 0
if brillo_actual[i] < obj: brillo_actual[i] = min(brillo_actual[i] + VELOCIDAD_FADE, obj)
elif brillo_actual[i] > obj: brillo_actual[i] = max(brillo_actual[i] - VELOCIDAD_FADE, obj)
canales_pwm[i].duty_u16(int(brillo_actual[i]))
# C. Web con Seguridad
try:
conn, addr = server.accept()
req = conn.recv(1024).decode()
if f"Authorization: Basic {auth_key}" in req:
if "ch=" in req:
idx = int(req.split("ch=")[1].split(" ")[0])
conmutar_canal(idx, f"Web ({addr[0]})")
conn.send('HTTP/1.1 200 OK\n\n' + generar_html())
else:
conn.send('HTTP/1.1 401 Unauthorized\nWWW-Authenticate: Basic realm="Pico"\n\n')
if "Authorization" in req: enviar_telegram(f"⚠️ Acceso fallido desde {addr[0]}")
conn.close()
except: pass
# D. Bluetooth
if uart.any():
c = uart.read().decode().strip().upper()
if c in "0123456789": conmutar_canal(9 if c=='0' else int(c)-1, "BT")
elif c.startswith('U'): umbral_oscuridad = int(c[1:])
time.sleep(0.01)