Curso de Servidores y Redes — Controla un LED por la red

Segundo bloque del itinerario de la asociación, después del curso de Linux, C y Python. La idea no es “otro curso de teoría”: es construir, entre todos y semana a semana, un sistema real que enciende un LED físico desde un servidor por la red local, aprendiendo los fundamentos (HTTP, redes, APIs) cuando el proyecto los pide, no antes.

Qué se construye (el proyecto)

Un sistema cliente-servidor sobre la red local (LAN):

   ┌─────────────────────────┐         red local (LAN)        ┌────────────────────────┐
   │  PORTÁTIL del alumno     │  ◄───────── HTTP ──────────►   │   RASPBERRY PI         │
   │  servidor FastAPI        │                                │   cliente que pregunta │
   │  - GET /led  (estado)    │     192.168.1.50:8000          │   cada X s y enciende  │
   │  - POST /led (cambiar)   │                                │   el LED real (GPIO)   │
   │  - POST /telemetria      │                                │                        │
   │  - panel web + WebSocket │                                │   LED                │
   └─────────────────────────┘                                └────────────────────────┘

El alumno escribe el servidor. El LED vive en una Raspberry Pi compartida de la sala. Al final del curso el servidor también tiene panel web, persistencia, tiempo real, seguridad y va dentro de un contenedor.

Por qué un LED

Es el actuador más barato que existe (20 céntimos) y da la misma recompensa que un robot entero: un programa tuyo cambia algo en el mundo físico. Es la prueba de que “esto funciona de verdad”. Lo ambicioso (robots, sensores) son extensiones de la Sesión 12.

El modelo pedagógico (cómo está pensado)

  1. Demo primero. En la Sesión 1 se enseña el proyecto ya terminado funcionando, y cómo funciona por encima. Así todos saben a dónde van.
  2. Esqueleto andante. No se construye “el servidor entero y luego el cliente”. Desde la primera sesión hay algo de punta a punta que funciona (aunque sea trivial), y cada semana se le añade una rebanada vertical nueva.
  3. Fundamentos bajo demanda. Redes, HTTP, etc. no se leen “de primeras”. El proyecto choca contra un muro (“¿por qué no me responde desde el otro portátil?”) y entonces se explica el concepto, 20 minutos, cuando todos tienen la pregunta en la cabeza.
  4. Una sesión = un entregable visible + un fundamento. Cada semana algo nuevo funciona. Eso es lo que hace que la gente vuelva.

El LED falso y el LED real (la pieza clave de diseño)

El truco que hace que todos trabajen aunque haya pocas Raspberry: el servidor no habla con un LED concreto, habla con una interfaz Led. Hay dos implementaciones intercambiables:

# led.py
class Led:                       # la interfaz: qué sabe hacer un LED
    def encender(self): ...
    def apagar(self): ...
 
class LedFalso(Led):             # en el PORTÁTIL: solo imprime
    def encender(self): print("💡 LED ON")
    def apagar(self):   print("⚫ LED OFF")
 
class LedReal(Led):              # en la RASPBERRY: enciende el pin físico
    def __init__(self, pin=17):
        from gpiozero import LED
        self._led = LED(pin)
    def encender(self): self._led.on()
    def apagar(self):   self._led.off()

Cambiar de simulado a real es una línea (o una variable de entorno). Así:

  • Cada alumno tiene el bucle completo funcionando en su portátil desde el día 1 con LedFalso.
  • La Raspberry compartida entra cuando toca, y solo cambia esa línea para tener el LED real.
  • De paso se enseña, sin decirlo, inversión de dependencias (programar contra interfaces).

Estrategia con pocas Raspberry Pi

  • Todos trabajan en su portátil con LedFalso → nadie espera por hardware.
  • 1–2 Raspberry en la red local, cada una con su IP fija (ej. 192.168.1.60).
  • En las sesiones con Pi se hace por turnos: el alumno apunta la Pi a la IP de su servidor y ve su LED encenderse. Dura 2 minutos por persona y todos pasan.
  • Todo es red local: sin internet, sin abrir puertos al exterior, sin túneles. Las IPs privadas (192.168.x.x) lo simplifican muchísimo y son, además, un buen tema de redes.

Modelo y práctica por sesión

El repositorio del curso guarda el código en dos carpetas paralelas (igual que el Curso de Python):

  • modelo/sNN → el código completo de esa sesión (lo que enseñas / la referencia).
  • practica/sNN → el esqueleto con # TODO de esa sesión (lo que rellena el alumno).

Un script copia el estado elegido a una carpeta de trabajo (trabajo/):

./bin/sesion.sh 3            # copia la PRÁCTICA de la Sesión 3 a  trabajo/  (con # TODO)
./bin/sesion.sh 3 --modelo   # copia el MODELO de la Sesión 3 (resuelto, si te atascas)

Así se separa “entender la red/HTTP” (el objetivo) de la fontanería del repo. El proyecto completo y funcional es modelo/s12 (la demo de la Sesión 1). El detalle del repo, el script y el entorno está en 00_setup-entorno-y-repo.

Índice de sesiones

#SesiónQué se ve funcionando al finalFundamento que entra
000_setup-entorno-y-repoEntorno listo, repo clonado, ./bin/sesion.shterminal, venv, git básico
101-vision-del-proyecto-y-primer-servidorDemo final + tu primer GET /ping en localcliente/servidor, localhost, puerto
202-curl-y-los-verbos-httpEnciendes el LedFalso con curlHTTP, GET/POST, headers, body, curl
303-json-y-validacion-pydanticEl server recibe y valida datos JSONJSON, Pydantic, códigos de estado
404-salir-del-localhost-la-red-localUn compañero llama a TU servidor por tu IPIP, LAN, 0.0.0.0, TCP/IP, firewall
505-la-raspberry-como-cliente-y-el-led-realEl LED físico obedece a tu servidorGPIO, SSH, polling, la interfaz Led
606-panel-web-en-el-navegadorUna web con botones controla el LEDfrontend, navegador como cliente, fetch
707-persistencia-con-sqliteEl histórico sobrevive a reiniciarbases de datos, SQL básico, estado durable
808-tiempo-real-con-websocketsEl LED reacciona al instantepolling vs push, WebSockets, latencia
909-seguridad-y-secretosSolo quien tiene la clave mandaautenticación, secretos, .env, .gitignore
1010-resiliencia-y-manejo-de-erroresSe recupera solo cuando algo fallatimeouts, reintentos, logging
1111-empaquetar-con-dockerEl server arranca igual en cualquier máquinacontenedores, imágenes, reproducibilidad
1212-demo-day-y-extensionesCada uno enseña su varianteconsolidación + cómo seguir

Cómo se imparte (el ritual semanal)

Sesión fija, mismo día y hora. Estructura recomendada (~90 min):

0–10 min   Demo / repaso: qué construimos hoy y por qué (el muro de la semana pasada)
10–30 min  Teoría just-in-time: el fundamento que el proyecto pide hoy (pizarra)
30–80 min  Manos a la obra: ./bin/sesion.sh N, rellenar los TODO, probar con curl/navegador
80–90 min  Puesta en común + el muro que abre la sesión siguiente

Roles que conviene repartir (y rotar entre cuatrimestres):

  • Quien guía la sesión (al principio tú; luego, alumnos veteranos).
  • Quien gestiona las Raspberry y los turnos del LED real.
  • Quien apunta dudas en un canal común para resolverlas en la puesta en común.

Stack y material

  • Software: Python 3, FastAPI, Uvicorn, requests/httpx, SQLite, gpiozero (en la Pi), Docker (Sesión 11).
  • Hardware: portátiles de los alumnos + 1–2 Raspberry Pi con un LED y una resistencia (~220 Ω) en un pin GPIO. Un router/switch para la red local.
  • Repo del curso: con las carpetas modelo/ y practica/ por sesión (ver 00_setup-entorno-y-repo).

Conexiones