01 · Integrar decisiones
De las funciones al sistema
Un dispositivo IoT completo es un conjunto de decisiones relacionadas. Una mayor frecuencia de muestreo mejora la observación, pero también genera más registros. El sueño profundo reduce consumo, pero cambia la recepción de órdenes. TLS necesita memoria y tiempo; OTA necesita espacio, energía y una recuperación prevista.
La arquitectura establece qué componente hace cada trabajo, qué información intercambia y qué ocurre cuando falla. No exige comenzar con una plataforma grande: una placa y un servicio pequeño también necesitan límites claros.
| Capacidad | Decisión al integrarla |
|---|---|
| Adquisición y control local | Cadencia, calidad de lectura, histéresis y salida ante una falla |
| HTTP o MQTT | Plazos, autorización, confirmación y política de reconexión |
| Almacenamiento y telemetría | Cuánto conservar, cuándo transmitir y qué descartar |
| Seguridad y aprovisionamiento | Identidad, credenciales, permisos y recuperación de acceso |
| OTA y gestión de flotas | Compatibilidad, aceptación, reversión y evidencia operativa |
| Bajo consumo | Ventanas de actividad y autonomía compatibles con el servicio |
Trabajaremos con un controlador de temperatura de banco y una variante de monitor a batería. El tema 48 llevará esas decisiones a un proyecto integrador. Aquí nos interesa entender por qué una combinación de componentes puede funcionar o entrar en contradicción.
02 · Especificar el comportamiento esperado
Requisitos que se pueden comprobar
«Debe ser rápido, seguro y consumir poco» no alcanza para elegir una placa ni escribir una prueba. Se necesita describir escenario, condición, límite y evidencia de aceptación.
El caso principal es un controlador de temperatura de banco alimentado de forma continua. Un sensor entrega lecturas y una salida representa un ventilador; durante el aprendizaje puede usarse un LED de baja tensión. El control local permanece atendido aunque la red deje de estar disponible.
| ID | Requisito | Evidencia de aceptación |
|---|---|---|
| R1 | Muestrear cada 1 s y decidir localmente en hasta 2 s desde un cambio observable | Ensayo de entrada y medida del tiempo hasta la decisión |
| R2 | Seguir el control local durante una caída de red | Desconectar red y verificar lectura, decisión y salida |
| R3 | Atender configuración remota en hasta 15 s bajo la red nominal definida | Medida de extremo a extremo con confirmación del equipo |
| R4 | Conservar al menos 6 minutos de muestras sin conexión | Interrumpir entrega y recuperar la historia sin pérdidas dentro del presupuesto |
| R5 | Identificar cada unidad y limitar sus permisos | Intentar acceder a recursos propios, ajenos y con credenciales revocadas |
| R6 | Actualizar solo firmware autorizado y recuperar un arranque fallido | Prueba de rechazo de imagen y recorrido de aceptación o reversión |
Definir el alcance de los tiempos
El modelo reservará 0,1 s para procesamiento local y 2 s para una comunicación nominal. Son supuestos de planificación. La conversión del sensor, las colas del sistema y las demoras del servicio deben estar incluidas en mediciones reales antes de sostener una garantía.
Una orden almacenada en la plataforma no garantiza atención mientras no hay red. La especificación distingue respuesta bajo conectividad nominal, comportamiento durante una interrupción y recuperación posterior.
La variante a batería cambia el contrato
El monitor a batería mide cada 60 s, abre una ventana de comunicación cada 600 s y admite hasta 900 s para atención remota bajo condiciones nominales. No gobierna una salida continua. Puede usar sueño profundo entre tareas y conserva 24 horas de muestras. Es otro perfil de servicio, aunque comparta placa y parte del firmware.
03 · Ubicar responsabilidades y límites
Arquitectura y responsabilidades
DISPOSITIVO PLATAFORMA
┌──────────────────────────────┐ ┌─────────────────────────┐
│ Sensor → validación │ │ Ingesta autenticada │
│ ↓ │ estados │ ↓ │
│ Política local → salida │ ───────→ │ Historia y estado actual│
│ ↓ │ │ ↓ │
│ Cola acotada → comunicación │ │ Panel y alertas │
│ ↑ │ comandos │ ↓ │
│ Validación y configuración │ ←─────── │ API con autorización │
│ │ │ │
│ Identidad · diagnóstico · OTA│ ←──────→ │ Inventario y campañas │
└──────────────────────────────┘ └─────────────────────────┘
↑ alimentación, reloj y hardware de recuperaciónEl camino sensor → decisión → salida pertenece al dispositivo. La plataforma almacena historia, organiza la flota y propone cambios autorizados. Una conexión lenta puede retrasar telemetría; no debe bloquear el trabajo local comprometido.
| Frontera | Contrato | Ante una falla |
|---|---|---|
| Sensor → aplicación | Valor, unidad, calidad y antigüedad | No sustituir una lectura inválida por cero |
| Aplicación → salida | Estado solicitado y condiciones permitidas | Aplicar la política física definida |
| Cola → servidor | Identidad de registro y confirmación | Reintentar sin multiplicar efectos ni crecer sin límite |
| Servidor → configuración | Versión, permisos, rangos y vigencia | Rechazar y conservar una configuración válida |
| Servicio OTA → arranque | Imagen autorizada, compatible y aceptable | Conservar recuperación bajo la política elegida |
Un responsable por estado
El módulo de control es el único que decide la salida lógica. El receptor de comandos entrega una solicitud validada; no escribe directamente el GPIO desde un callback de red. Así se evita que el control automático, una orden remota y una tarea OTA compitan por la misma salida.
También se distingue la orden lógica del estado físico observado. Guardar salida=true demuestra una decisión de software; confirmar que el ventilador gira requiere una señal de realimentación apropiada.
04 · La arquitectura llega a los pines
Hardware y comportamiento físico
La elección del microcontrolador empieza por interfaces, memoria, alimentación, entorno y mantenimiento. La disponibilidad de Wi-Fi no resuelve por sí sola el número de pines, la corriente de una carga o el espacio de flash necesario para actualizar.
| Bloque | Decisiones que documentar |
|---|---|
| Sensor | Rango, precisión, tiempo de conversión, bus, errores y calibración |
| Salida | Etapa de manejo, corriente, protección de cargas y estado durante arranque |
| Alimentación | Consumo continuo, ráfagas de radio, regulación y caída de tensión |
| Conectividad | Antena, cobertura, ubicación y proceso de configuración |
| Memoria | RAM simultánea, particiones, datos persistentes y crecimiento de imagen |
| Servicio | Programación, recuperación, identificación física y acceso de diagnóstico |
El estado de arranque también es una decisión
Antes de que el firmware configure una salida, el pin puede tener otro comportamiento. Se seleccionan pines y resistencias para que reset, bootloader y programación no activen accidentalmente una carga. El análisis incluye periféricos externos y pérdida parcial de alimentación.
Para el banco de esta lección se define salida desactivada ante lectura inválida o durante reinicio. Ese criterio pertenece al ejemplo: en un sistema térmico real apagar un ventilador podría agravar el problema. La condición segura se determina para la aplicación y puede necesitar circuitos independientes del software.
Alimentación continua frente a batería
El controlador prioriza atención local continua. El monitor a batería acepta mayores demoras y apaga subsistemas entre trabajos. El presupuesto energético del tema 46 debe realizarse para cada perfil y para las fallas de red; cambiar solamente el nombre del modo no demuestra autonomía.
05 · Mantener atendida la función local
Organización del firmware
Se puede implementar con un bucle cooperativo o con tareas de un sistema operativo. En ambos casos hacen falta prioridades, plazos, propietarios de datos y límites de memoria. Crear muchas tareas no elimina un bloqueo de red ni una condición de carrera.
| Módulo | Responsabilidad | Límite |
|---|---|---|
| Adquisición | Solicitar muestra, validar y registrar calidad | Plazo del sensor; lectura anterior no presentada como nueva |
| Control | Histéresis y salida según estado válido | No esperar red ni escritura extensa |
| Persistencia | Guardar configuración y cola | Tamaño, frecuencia de escritura e integridad |
| Comunicaciones | Reconectar, intercambiar datos y confirmar | Timeouts, lotes y reintentos acotados |
| Mantenimiento | Diagnóstico y actualización | Permiso local para interrumpir la función y recursos reservados |
al iniciar:
fijar salida de arranque
validar configuración persistida o cargar valores admitidos
preparar sensor, almacenamiento y comunicaciones
en cada iteración o activación planificada:
atender adquisición sin espera indefinida
evaluar control con lectura y configuración vigentes
atender escritura y envío con presupuesto de trabajo
procesar solicitudes validadas sin escribir directamente la salida
registrar progreso y fallos de cada subsistema
admitir mantenimiento solo bajo sus condiciones
Es pseudocódigo de responsabilidades, no un firmware listo para cargar. Una biblioteca síncrona puede ocupar todo el intervalo aunque esté dentro de una función llamada «atender». Se mide su peor duración o se aísla de forma que el control conserve sus plazos.
Configuración coherente
Los umbrales se validan como conjunto: por ejemplo, el umbral de encendido debe ser mayor que el de apagado. La aplicación recibe una versión completa y coherente; no observa la mitad de una escritura. Se distingue versión deseada, validada, aplicada y reportada.
Un watchdog detecta determinadas ausencias de progreso, pero un reinicio no corrige necesariamente una configuración inválida. Su alimentación debe depender del avance significativo de las tareas relevantes, y la recuperación debe dejar evidencia del motivo.
06 · Datos con significado estable
Contratos de datos y comandos
El protocolo transporta bytes. El contrato explica qué significan, quién puede producirlos y cómo se rechazan datos incorrectos. Conviene versionar esquema, unidades y reglas de compatibilidad.
{
"schema": 1,
"device_id": "banco-017",
"boot_id": "sesion-opaca-ejemplo",
"seq": 42,
"uptime_ms": 42000,
"temperature_c": 28.4,
"quality": "valid",
"output_requested": true,
"config_applied": 7,
"firmware_build": 12
}El ejemplo describe un snapshot actual. El backend vincula la identidad de la conexión con el inventario y agrega su tiempo de recepción. El texto device_id dentro del JSON no autentica al emisor. Si el reloj del equipo no está sincronizado, no se inventa una fecha absoluta a partir de uptime_ms.
Tres intercambios distintos
| Intercambio | Necesita | Error que evitar |
|---|---|---|
| Historia de mediciones | Identidad estable, instante o contexto temporal y deduplicación | Convertir un lote atrasado en presencia actual |
| Configuración deseada | Versión, rangos, permisos y reporte de aplicación | Mostrar «aplicada» solo porque se guardó en la nube |
| Acción puntual | ID de comando, vigencia, autorización y resultado | Reejecutar una acción vieja al reconectar |
Una confirmación de transporte y una confirmación de aplicación prueban etapas diferentes. Si el producto promete que una medición ya quedó durable en el servidor, define un acuse a ese nivel. Si promete una acción física, necesita el resultado que efectivamente pueda observar.
HTTP y MQTT dentro de la arquitectura
Ambos pueden servir para telemetría y configuración. Se eligen según patrón de intercambio, infraestructura y restricciones, manteniendo contratos independientes de la biblioteca de transporte. La elección no elimina duplicados, mensajes atrasados, reconexiones ni autorización por recurso.
07 · La desconexión es un escenario previsto
Operación sin conexión
El controlador continúa con la última configuración válida y su política local, mientras conserva muestras dentro de una cola acotada. La pérdida de red y la falla del sensor son estados independientes: puede haber una lectura válida sin conexión o un sensor inválido con transporte disponible.
| Situación | Conducta local | Evidencia |
|---|---|---|
| Red ausente | Continuar control, guardar y reconectar con límites | Edad de conexión, intentos y ocupación de cola |
| Sensor inválido | Aplicar salida desactivada del ejemplo; no usar lectura vieja indefinidamente | Calidad y antigüedad de la última muestra válida |
| Cola llena | Aplicar descarte definido sin impedir el control | Contador de descartes y rango de historia perdida |
| Configuración inválida | Rechazarla y mantener una válida | ID, versión y motivo del rechazo |
| Reinicio | Salida de arranque y recuperación validada de datos | Motivo, build y nueva sesión |
Dimensionar la cola
Para una interrupción de duración D y un intervalo de muestra Tm, se estima conservadoramente ceil(D/Tm) registros nuevos con fase arbitraria. El presupuesto del laboratorio supone cola vacía al comenzar, muestras periódicas y ausencia de envíos durante todo el corte.
espacio requerido = ceil(N × bytes por registro × margen)
En el controlador, 6 minutos equivalen a 360 muestras de 1 s. Con 96 bytes por registro y factor 1,2 se requieren 41 472 bytes = 40,5 KiB. El monitor de 24 horas y muestras de 60 s requiere 1440 registros: 165 888 bytes = 162 KiB. Un KiB representa 1024 bytes.
Los 96 bytes son una reserva de formato persistido por registro, no una afirmación sobre el tamaño del JSON mostrado. El margen del 20 % es un supuesto didáctico; índices, metadatos, alineación, recuperación y sistema de archivos deben medirse.
La recuperación también necesita capacidad
Al volver la red se siguen generando muestras. Para vaciar el atraso, la tasa de entrega confirmada debe superar la de producción durante suficiente tiempo. Se limita el envío por lote para que TLS, almacenamiento y telemetría no desplacen al control local. Una cola que estaba llena antes del corte requiere otro presupuesto.
08 · Reservar para lo que ocurre a la vez
Presupuestos de recursos
Los consumos de RAM se suman cuando coinciden. Tener memoria para TLS en una prueba y para OTA en otra no demuestra que ambas funciones puedan coexistir con el sensor, las pilas de tareas y la cola.
| Uso de RAM | Reserva | Supuesto |
|---|---|---|
| Aplicación y sistema | 32 KiB | Incluye pilas y estructuras previstas en el modelo |
| Comunicación protegida | 48 KiB | Se reserva incluso si se desmarca TLS, porque el requisito sigue exigiéndolo |
| Adquisición | 4 KiB | Buffers del sensor y procesamiento |
| Gestión de cola persistente | 8 KiB | Ventana de trabajo; la historia completa permanece en flash |
| OTA habilitada | 16 KiB | Reserva adicional simultánea durante mantenimiento |
Con OTA se requieren 108 KiB de RAM. Reservar 128 KiB supera esa suma en papel, pero todavía hay que comprobar máximos reales, fragmentación, bloques contiguos y variaciones entre builds. El laboratorio no representa la RAM total física de un ESP32 específico.
La imagen debe entrar en su partición
El diseño presupone una imagen de 768 KiB y dos slots de aplicación para la estrategia OTA con reversión. Cada slot debe alojar la imagen completa. Sumar espacio libre disperso en otras particiones no agranda el slot de destino.
+ almacenamiento de historia
+ cantidad de slots × tamaño por slot
límite del ejemplo = 4096 KiB
Con cola de 64 KiB y dos slots de 1024 KiB se asignan 2368 KiB. La reserva fija agrupa metadatos y otros usos del modelo. Una tabla real debe asignar correctamente bootloader, metadatos OTA, credenciales y particiones con sus requisitos de formato y alineación.
La documentación OTA de ESP-IDF describe particiones de aplicación, selección de arranque y aceptación o reversión. El modelo usa dos slots para su estrategia elegida; no implementa ni verifica una tabla de particiones ESP-IDF.
Tiempo, energía y ancho de banda también se presupuestan
Para el control se usa intervalo de muestra + 0,1 s como demora local estimada. Para atención remota se usa intervalo de comunicación + 2 s: ambos perfiles consultan trabajo pendiente en esa ventana, incluso el controlador despierto. Un diseño con recepción continua tendría otro modelo.
Estos límites presuponen sensor, CPU y red bajo las condiciones definidas. Un dato que tarda en atravesar la nube, una conversión lenta o un lote de recuperación pueden ampliarlos. Los resultados se contrastan con pruebas y con el presupuesto de energía del tema anterior.
09 · Diseñar también el mantenimiento y el retiro
Seguridad y ciclo de vida
La identidad no se agrega al final como un campo del JSON. El diseño define dónde se crea la credencial, cómo se instala, qué recursos autoriza y cómo se reemplaza o revoca. Compartir una misma credencial entre toda la flota dificulta aislar una unidad comprometida.
La línea base NISTIR 8259A organiza capacidades como identificación, configuración, protección de datos, acceso a interfaces, actualización y conocimiento del estado de seguridad. Es un punto de partida para requisitos propios, no una lista que por sí sola pruebe seguridad.
| Etapa | Qué dejar resuelto |
|---|---|
| Preparación y alta | Identidad única, vínculo con inventario y credencial inicial protegida |
| Instalación | Red, pertenencia, validación del sensor y configuración inicial |
| Operación | Permisos mínimos, calidad, versiones y antigüedad de evidencia |
| Mantenimiento | Renovación de credenciales, OTA autorizada y diagnóstico acotado |
| Recuperación | Acceso local autorizado y procedimiento ante credenciales o firmware inválidos |
| Retiro o transferencia | Revocar acceso, tratar datos y cambiar pertenencia de forma trazable |
Cuándo puede actualizar el controlador
Una campaña propone trabajo; el equipo comprueba si puede ejecutarlo. En el banco se admite mantenimiento cuando la salida está desactivada, la alimentación cumple la política y no hay una tarea esencial pendiente. Si no se dan las condiciones, se posterga y se reporta el motivo.
La autorización y compatibilidad del firmware se verifican antes de aceptarlo. El primer arranque confirma salud bajo criterios locales. Migrar configuración o datos exige preservar la compatibilidad necesaria para una eventual reversión, como vimos en el tema 44.
Qué comprueba el laboratorio
Los controles de identidad única, TLS con validación y OTA recuperable representan decisiones declaradas. Marcarlos no genera certificados, no prueba criptografía ni instala un bootloader. Las diez comprobaciones del modelo son una revisión de consistencia, que debe acompañarse con evidencia de implementación.
10 · Vincular decisiones con evidencia
Pruebas y trazabilidad
Un diseño revisable relaciona cada requisito con un componente responsable y una prueba. Si nadie puede explicar qué evidencia demostraría el requisito, todavía falta precisión en el contrato.
| Requisito | Responsable | Prueba | Evidencia |
|---|---|---|---|
| R1: respuesta local | Adquisición y control | Cambio de entrada mientras se transmite | Tiempos de muestra y decisión; salida lógica y física si se instrumenta |
| R2: control sin red | Control y comunicaciones | Corte de enlace, DNS y servidor | Continuidad del control y plazos de reintento |
| R3: cambio remoto | API y gestor de configuración | Enviar versión válida, repetida y fuera de rango | Versión aplicada, rechazo y demora observada |
| R4: historia local | Cola e ingesta | Corte de 6 minutos, recuperación y confirmación perdida | Registros únicos, duplicados tratados y ocupación |
| R5: aislamiento | Identidad y autorización | Una unidad intenta operar sobre otra | Rechazo y auditoría sin secretos |
| R6: OTA recuperable | Actualizador y arranque | Imagen no autorizada, corte y diagnóstico fallido | Rechazo, recuperación y build finalmente aceptada |
Probar combinaciones
La integración falla a menudo cuando dos situaciones coinciden: publicar mientras se guarda configuración, reconectar mientras hay muestras pendientes o actualizar mientras crece la memoria de TLS. Se comprueba que las exclusiones previstas se respeten y que los recursos simultáneos sigan dentro de su presupuesto.
Incluí corte de alimentación durante escritura, sensor ausente, credencial vencida, reloj incorrecto, cola llena y servidor que recibe pero pierde la confirmación de aplicación. La recuperación debe ser acotada y conservar la función definida para cada estado.
Una entrega mínima de diseño
- Ficha del caso de uso, entorno, límites y requisitos numerados.
- Diagrama de bloques y responsable de cada estado y recurso.
- Tabla de interfaces, mensajes, configuración y confirmaciones.
- Presupuestos de tiempos, energía, RAM, flash y almacenamiento.
- Políticas ante red caída, dato inválido, reinicio y mantenimiento.
- Matriz de pruebas, resultados y limitaciones todavía abiertas.
- Instrucciones de alta, instalación, recuperación y retiro.
El panel debería mostrar build, configuración aplicada, salud, antigüedad de contacto y contadores útiles. Los registros incluyen contexto para diagnosticar, sin contraseñas, tokens ni claves privadas.
11 · Revisar restricciones de forma reproducible
Modelo ejecutable en Python
El evaluador calcula almacenamiento, tiempos y reservas, y devuelve diez resultados independientes. Una restricción fallida no oculta las demás. Los perfiles comparten el requisito de identidad única, transporte validado y actualización recuperable; el monitor no exige control continuo.
El código usa biblioteca estándar de Python 3. El botón carga Pyodide la primera vez. No simula un sensor ni una red: verifica las hipótesis de planificación que se declararon en esta lección.
from math import ceil, isfinite
def base(perfil="control"):
if perfil not in ("control", "monitor"):
raise ValueError("Perfil desconocido")
p = dict(perfil=perfil, modo="activo", muestra=1, envio=10,
plazo=15, corte=0.1, almacen=64, ram=128, slot=1024,
identidad="unica", tls=True, ota=True)
if perfil == "monitor":
p.update(modo="profundo", muestra=60, envio=600,
plazo=900, corte=24, almacen=256)
return p
def evaluar(p):
if (p["perfil"] not in ("control", "monitor")
or p["modo"] not in ("activo", "profundo")
or p["identidad"] not in ("unica", "compartida")):
raise ValueError("Opción desconocida")
limites = {"muestra": (1, 3600), "envio": (1, 86400),
"plazo": (1, 86400), "corte": (0, 168),
"almacen": (16, 4096), "ram": (64, 256),
"slot": (512, 2048)}
for clave, (minimo, maximo) in limites.items():
v = p[clave]
if (type(v) not in (int, float) or not isfinite(v)
or not minimo <= v <= maximo):
raise ValueError(f"Magnitud inválida: {clave}")
if any(type(p[k]) is not bool for k in ("tls", "ota")):
raise ValueError("TLS y OTA requieren booleanos")
if p["envio"] < p["muestra"]:
raise ValueError("El envío debe ser al menos el intervalo de muestra")
registros = ceil(p["corte"] * 3600 / p["muestra"])
bytes_cola = ceil(registros * 96 * 1.2)
ram = 32 + 48 + 4 + 8 + (16 if p["ota"] else 0)
flash = 256 + p["almacen"] + (2 if p["ota"] else 1) * p["slot"]
local = p["muestra"] + 0.1
remoto = p["envio"] + 2
control = p["perfil"] == "control"
criterios = [
("Atención continua", None if not control else p["modo"] == "activo"),
("Respuesta local hasta 2 s", None if not control else local <= 2),
("Ventana remota", remoto <= p["plazo"]),
("Cola para el corte", bytes_cola <= p["almacen"] * 1024),
("RAM simultánea", ram <= p["ram"]),
("Imagen de 768 KiB por slot", 768 <= p["slot"]),
("Asignación de flash", flash <= 4096),
("Identidad por unidad", p["identidad"] == "unica"),
("TLS con validación", p["tls"]),
("OTA recuperable", p["ota"]),
]
fallos = sum(ok is False for _, ok in criterios)
aplicables = sum(ok is not None for _, ok in criterios)
return dict(registros=registros, bytes_cola=bytes_cola, ram=ram,
flash=flash, local=local, remoto=remoto,
criterios=criterios, fallos=fallos, aplicables=aplicables)
for perfil in ("control", "monitor"):
r = evaluar(base(perfil))
print(f"{perfil}: {r['fallos']} fallos / {r['aplicables']} aplicables")
print(f" Cola: {r['registros']} registros; {r['bytes_cola'] / 1024:g} KiB")
print(f" RAM: {r['ram']} KiB; flash asignada: {r['flash']} KiB")
mal = dict(base(), modo="profundo", plazo=5, corte=24,
ram=64, slot=512, identidad="compartida", tls=False, ota=False)
r = evaluar(mal)
print("\nDiseño contradictorio:")
for nombre, ok in r["criterios"]:
print(f" {nombre}: {'no aplica' if ok is None else 'cumple' if ok else 'falla'}")
assert evaluar(base())["bytes_cola"] == 41472
assert evaluar(base("monitor"))["bytes_cola"] == 165888
assert evaluar(base())["ram"] == 108
assert evaluar(base())["flash"] == 2368
assert evaluar(base())["fallos"] == 0
assert evaluar(base("monitor"))["aplicables"] == 8
assert evaluar(base("monitor"))["fallos"] == 0
assert r["fallos"] == 8
assert evaluar(dict(base(), corte=0))["bytes_cola"] == 0
assert evaluar(dict(base(), almacen=40.5))["fallos"] == 0
assert evaluar(dict(base(), muestra=1.9))["local"] == 2
assert evaluar(dict(base(), muestra=2))["fallos"] == 1
assert evaluar(dict(base(), slot=2048))["flash"] > 4096
for cambio in ({"muestra": 0}, {"envio": 0.5}, {"corte": -1},
{"plazo": float("nan")}, {"tls": 1}, {"envio": 0.8}):
try:
evaluar(dict(base(), **cambio))
except ValueError:
pass
else:
raise AssertionError(f"Debía rechazar {cambio}")
print("\nComprobaciones superadas; faltan ensayos reales de implementación.")Se verifican los dos perfiles, límites inclusivos, almacenamiento, RAM, flash y entradas inválidas. El modelo acepta magnitudes decimales dentro del rango; el laboratorio ofrece algunos tamaños discretos para facilitar la comparación.
12 · Revisar un diseño antes de implementarlo
Laboratorio de arquitectura
Los controles describen una propuesta. El evaluador calcula sus consecuencias y muestra qué restricciones cumple bajo los supuestos anteriores. Cambiar el perfil conserva los demás parámetros para que puedas descubrir incompatibilidades; los botones cargan un conjunto completo.
Ficha de diseño
Servicio y tiempos
Recursos reservados
Decisiones de seguridad y mantenimiento
Preparando evaluación.
| Restricción | Resultado | Motivo y siguiente comprobación |
|---|
Decisiones por revisar
Recorrido guiado
- Cargá el controlador. Hay 10 restricciones aplicables sin fallos, 40,5 KiB de historia, 108 KiB de RAM requerida y 2368 KiB de flash asignada. Todavía faltan pruebas reales.
- Elegí sueño profundo sin cambiar el perfil. Falla la atención continua comprometida para este controlador. Volvé a atención activa.
- Cambiá el intervalo de muestra a 2 s. La demora local estimada pasa a 2,1 s y supera el requisito de 2 s. El límite con 0,1 s de proceso sería 1,9 s.
- Cargá de nuevo el controlador y subí el corte a 1 h. Se requieren 405 KiB de historia: la reserva de 64 KiB ya no alcanza.
- Restaurá el controlador y fijá cada slot en 2048 KiB. La imagen entra, pero el total de 4416 KiB supera la flash disponible. Un recurso puede cumplir un límite y romper otro.
- Cargá el monitor. Hay 8 restricciones aplicables y dos que no corresponden a su servicio. Necesita 162 KiB para sus 24 horas de historia y estima hasta 602 s de espera remota nominal.
- En el monitor reducí el plazo remoto a 15 s. Dormir y comunicarse cada 600 s no satisface ese contrato. No se arregla aumentando el tamaño de la batería.
- Cargá el diseño contradictorio. Aparecen 8 fallos independientes. Corregir solo TLS deja pendientes memoria, historia, tiempos, identidad, atención continua y mantenimiento.
- Vaciá un campo o poné el intervalo de envío por debajo del de muestra. Se ocultan resultados anteriores y aparece un error de entrada. Eso se distingue de un diseño válido como entrada que incumple requisitos.
¿Puedo habilitar OTA y dar por resuelta la actualización?
No. Esa opción reserva dos slots y memoria de trabajo, y declara una intención. Todavía faltan autenticidad, compatibilidad, manejo de cortes, criterios de aceptación, datos persistentes y pruebas de recuperación.
¿Un resultado sin fallos significa que el dispositivo está listo?
No. Significa que estas restricciones son coherentes bajo ciertos supuestos. El laboratorio no mide sensor, autonomía, cobertura, picos, seguridad real, consumo de CPU ni comportamiento físico.
13 · Práctica guiada
Predecí antes de comprobar
1. Una nube lenta
La publicación tarda 8 s y bloquea el mismo bucle que debería decidir la salida cada segundo. ¿Qué contradicción hay y qué evidencia pedirías?
Ver solución
La comunicación puede impedir cumplir el plazo local. Se rediseña la espera o su aislamiento y se mide el tiempo hasta la decisión mientras la red está lenta. Una prueba sin publicaciones no alcanza.
2. Cola para una hora
Se produce una muestra por segundo, con 96 bytes reservados y factor 1,2. ¿Alcanzan 64 KiB para una hora sin entrega?
Ver solución
No. Son 3600 registros y 3600 × 96 × 1,2 = 414 720 bytes = 405 KiB. Se modifica la reserva, el contrato de historia, el formato o la cadencia, verificando sus consecuencias.
3. La suma de RAM
Hay 128 KiB disponibles y el presupuesto simultáneo suma 108 KiB. ¿Qué queda por demostrar?
Ver solución
El máximo real, las pilas, las bibliotecas, la fragmentación y las asignaciones contiguas bajo concurrencia y fallas. Los 20 KiB de diferencia son margen del cálculo, no evidencia de ejecución.
4. Imagen y partición
Una imagen ocupa 768 KiB, el slot de destino 512 KiB y hay 1 MiB libre en otra partición. ¿La imagen entra en el slot?
Ver solución
No. La capacidad debe estar en la partición de destino. Cambiar el mapa requiere una estrategia de actualización y recuperación compatible con los equipos instalados.
5. Una muestra inválida
Un sensor desconectado devuelve error. ¿Conviene convertirlo a 0 °C para mantener el JSON numérico?
Ver solución
No. Se conserva una calidad inválida y se aplica la política del caso. Cero sería un dato físico falso y podría producir una decisión incorrecta.
6. Orden aceptada por la API
La plataforma responde que guardó configuración 8, pero el dispositivo sigue reportando configuración 7. ¿Qué puede mostrar el panel?
Ver solución
Deseada: 8; última aplicada reportada: 7, con antigüedad y estado pendiente o rechazado según la evidencia. La respuesta de la API no demuestra aplicación local.
7. Recuperar historia
La cola tiene atraso y se confirma un registro por segundo, mientras el sensor genera uno nuevo por segundo. ¿Se vacía?
Ver solución
No con esas tasas sostenidas. La entrega debe superar la producción para reducir el atraso. También se verifica el presupuesto de recursos durante esa recuperación.
8. Mismo firmware, otro servicio
Un monitor despierta para comunicarse cada diez minutos. Se le exige atender órdenes en cinco segundos manteniendo esa política. ¿Basta cambiar un timeout?
Ver solución
No. La ventana de recepción contradice la latencia. Hay que revisar requisitos, conectividad, modo de actividad y energía, y medir el diseño que resulte.
14 · Síntesis
Ideas para recordar
- Los requisitos se expresan con escenarios, límites y evidencia de aceptación.
- La arquitectura asigna responsables y separa el control local de las demoras de red.
- La condición física ante sensor inválido, arranque y mantenimiento se define para cada aplicación.
- Los contratos distinguen historia, estado actual, configuración y acciones puntuales.
- Una cola necesita capacidad, descarte, confirmación y una recuperación más rápida que la producción.
- RAM, flash, energía y tiempos se presupuestan para los escenarios que pueden coincidir.
- Identidad, permisos, OTA, recuperación y retiro pertenecen al diseño desde el inicio.
- Un monitor dormido y un controlador continuo pueden compartir componentes, pero tienen contratos diferentes.
- Las revisiones de consistencia se completan con mediciones y pruebas de fallas reales.
¿Listo para el tema 48?
Antes de avanzar, elegí un perfil de servicio y redactá su ficha: requisitos numerados, bloques, mensajes, presupuestos y pruebas. Explicá qué sigue funcionando sin red, cómo se trata una lectura inválida y qué evidencia permite aceptar una actualización.
En el próximo tema, Proyecto integrador, construimos un dispositivo medidor y controlador conectado de punta a punta a partir de estas decisiones.