# Proyecto integrador local · Tema 48

Python 3.10 o posterior, con `sqlite3`, sin paquetes externos. El dispositivo es
simulado: no lee un sensor ni maneja GPIO. El servidor escucha únicamente en
127.0.0.1:8765 y usa HTTP sin TLS para este banco en una sola computadora.

## Arranque en PowerShell

Descomprimí el ZIP en una carpeta de trabajo y abrí una terminal allí.

```powershell
$env:IOT_DEVICE_TOKEN = [guid]::NewGuid().ToString('N')
$env:IOT_ADMIN_TOKEN = [guid]::NewGuid().ToString('N')
# Anotá ambos valores para el banco local; no los publiques.
$env:IOT_DEVICE_TOKEN
$env:IOT_ADMIN_TOKEN
py servidor.py
```

En una segunda terminal, ubicada en la misma carpeta, definí IOT_DEVICE_TOKEN
con el valor generado en la primera. Una terminal abierta por separado no
hereda automáticamente las variables que asignaste en la otra.

```powershell
$env:IOT_DEVICE_TOKEN = 'PEGAR_EL_TOKEN_DE_EQUIPO_GENERADO'
py dispositivo.py --ciclos 30 --sin-red 5
```

No hace falta compartir el token de administrador con el agente.

Abrí http://127.0.0.1:8765 en el navegador. Ingresá IOT_ADMIN_TOKEN y consultá el
estado. Guardá versión 2, on=30, off=27. Consultá de nuevo después de que el
agente produzca otras muestras: la configuración deseada y la versión reportada
en cada muestra son evidencias distintas. El panel se actualiza con el botón.

Detené cada programa con Ctrl+C en su terminal. El servidor conserva historia y
configuración deseada en `proyecto.sqlite3`, junto a los scripts. No lo incluyas
en una distribución del proyecto. La cola, configuración aplicada y salida del
agente están en RAM: reiniciarlo pierde pendientes, crea otra sesión y arranca
con configuración 1 hasta consultar la guardada en el servidor.

## Pruebas

```powershell
py pruebas.py
```

Las pruebas usan una base temporal y un puerto de loopback libre; no usan tokens
del entorno ni acceden a tu base. Verifican control, antigüedad, duplicados,
colisión de identidad de registro, autorización, configuración y persistencia.

## Límites

- Temperaturas sintéticas: 24, 29, 27, 25, inválida, 30, 27 y 25 °C, en ciclo.
- Cada muestra avanza un segundo lógico. La red y la planificación del escritorio
  pueden demorar más: esto no garantiza plazos de un firmware de tiempo real.
- Histéresis inclusiva: on=28, off=26; en la banda se conserva la salida previa.
- Una lectura inválida o de edad mayor de 5 s apaga la salida de este banco.
- Cola de 3 registros en RAM; descarta el nuevo al llenarse sin detener el control.
- Hasta dos envíos por ciclo; solo se retira un registro al recibir su acuse.
- SQLite deduplica por dispositivo/sesión/secuencia y rechaza otro contenido
  para la misma identidad. El acuse se emite después de confirmar la transacción.
- El servidor admite 10000 registros nuevos; al llenarse devuelve 503. No implementa
  rotación ni retención. El panel muestra los últimos 20 nuevos ingresados.
- Un token representa una unidad y otro al administrador; no hay alta, revocación,
  TLS, OTA, política de reloj absoluta, ni seguridad de producción implementadas.

Para una placa real, conservar el núcleo de reglas y sustituir adquisición,
salida, reloj y transporte; implementar persistencia local y las políticas de
seguridad, mantenimiento y recuperación de los temas anteriores. No exponer este
servidor ni los tokens por una red: `http.server` es una herramienta didáctica.
