← Índice del curso

Internet de las Cosas · Tema 36

Paneles y visualización

Una tarjeta que muestra «4,1 °C» puede representar una lectura de hace dos segundos o de hace dos horas. Un gráfico continuo puede esconder una caída del sensor. Un botón que reconoce una alarma puede confundirse con su recuperación. Un panel útil hace visibles esas diferencias para que quien lo consulta pueda decidir con la información que realmente existe.

01 · Cerrar el recorrido del dato

Del contrato de telemetría a la pantalla

En el tema 35 definimos qué reportar, cada cuánto y con qué calidad. Ahora usamos esos datos para construir un panel de operación: una vista que permite entender qué ocurre, dónde falta información y qué necesita atención. La interfaz no debería borrar las distinciones que cuidamos en el firmware y el servidor.

El recorrido del bloque queda completo: el dispositivo mide y decide; la cola conserva; el servicio recibe y guarda; el panel consulta y presenta. Cada parte puede fallar de una manera distinta. Un error al dibujar no prueba una falla física, y una conexión abierta con el servidor no demuestra que el sensor siga adquiriendo.

Una pregunta de operación

«¿Hay una alarma activa que debo atender?». La vista necesita estado confirmado, antigüedad del conocimiento y reconocimiento del operador.

Una pregunta de diagnóstico

«¿Por qué el valor dejó de avanzar?». La vista necesita calidad, tiempo de adquisición, diagnóstico y una historia que muestre los huecos.

El laboratorio es un panel local de una cámara, sin servidores ni acciones sobre equipos reales. Sus umbrales y tiempos son didácticos. El botón de reconocimiento cambia el estado de la simulación; el control remoto del dispositivo comienza en el tema 37.

02 · Diseñar alrededor de preguntas

Una vista general y un detalle útil

Un panel de flota y una vista de dispositivo resuelven niveles distintos. La primera permite localizar equipos que requieren atención; la segunda permite explicar qué ocurrió. Mostrar todos los gráficos de todos los sensores desde el inicio suele dificultar ambas tareas.

Información apropiada para cada nivel de navegación.
NivelPreguntaElementos útiles
Flota o sitio¿Dónde tengo un problema?Lista filtrable, alarmas activas, equipos sin datos recientes y contadores de atención
Dispositivo¿Qué sabe el sistema de este equipo?Valor, calidad, edades, última alarma y diagnóstico
Historia¿Qué pasó en ese período?Serie temporal, eventos, intervalos y resolución explícita
Diagnóstico¿Qué explica la falla?Versiones, errores, reinicios, cola y contadores

En una lista de equipos, «sin datos» debe ser una categoría visible. Si solo se muestran dispositivos que publicaron en la última hora, uno que dejó de transmitir puede desaparecer en lugar de llamar la atención. El inventario y los datos recientes cumplen funciones diferentes.

Un resumen que conserve contexto

Una tarjeta de temperatura debería mostrar valor y unidad, estado del dato y antigüedad. La alarma y el diagnóstico se presentan al lado con sus propias etiquetas. «Atención requerida» puede agrupar problemas, pero la interfaz debe permitir distinguir una alarma física de un dato vencido.

Para comparar cámaras, mantené escalas y unidades comparables. Si cada gráfico ajusta automáticamente su eje vertical a un intervalo distinto, una variación de 0,1 °C puede verse tan grande como otra de 5 °C. El eje puede adaptarse, pero sus límites deben quedar visibles.

La jerarquía visual se elige por importancia: primero lo que requiere una decisión, después la explicación y finalmente los detalles de diagnóstico. Una cuadrícula de indicadores idénticos le exige al operador encontrar por su cuenta cuál importa.

03 · Una temperatura no alcanza

Valor, calidad, frescura y diagnóstico

Para construir el estado de una tarjeta distinguimos cuatro preguntas. ¿Cuál fue la última adquisición? ¿Fue válida? ¿Cuánto hace que hay un valor válido? ¿Cuánto hace que recibimos diagnóstico del equipo? Las respuestas pueden combinarse de varias maneras.

Política de presentación del ejemplo, no una propiedad universal del sensor.
SituaciónValor principalInformación adicional
Última adquisición válida y dentro del plazoTemperatura con unidad«Actual» y edad de la medición
Última adquisición inválida«Sin dato actual»«Inválido» y último valor válido, marcado como histórico
Última adquisición válida, pero vencida«Sin dato actual»«Atrasado» y edad del último valor válido
Nunca se recibió una adquisición«Sin dato actual»«Sin datos»; no inventar un cero

Esta política evita presentar un número histórico como actual. Otro producto puede mantenerlo en el lugar principal con una advertencia destacada; lo importante es que valor, calidad y antigüedad no queden ambiguos. Una adquisición inválida no significa 0 °C ni borra la existencia del último dato válido.

Edad del último valor válido = instante de referencia − tiempo de su medición
Dato fresco, en este modelo: edad ≤ límite de frescura
Diagnóstico reciente: edad del último latido ≤ límite de silencio

Con un límite de 120 s, una lectura de exactamente 120 s de antigüedad todavía es fresca; a los 121 s se considera atrasada. Fijar la igualdad permite comprobar los bordes del comportamiento. No se usan edades negativas para declarar frescura: un tiempo futuro o un reloj no confiable requieren una indicación distinta y validación en el servicio.

Diagnóstico reciente no equivale a sensor sano

Un equipo puede enviar latidos cada dos minutos y producir lecturas inválidas durante media hora. Su comunicación reciente y la falla de adquisición deben aparecer simultáneamente. Por eso el laboratorio usa etiquetas como «Diagnóstico reciente», sin convertirlas en una afirmación absoluta de conectividad o funcionamiento.

También puede ocurrir lo contrario: quedan lecturas válidas antiguas y se venció el diagnóstico. La temperatura histórica se conserva, pero no sabemos que el proceso siga en ese valor. El panel no declara recuperación de alarma solo porque dejó de recibir datos.

Qué reloj usa el panel

En producción, la API puede entregar la hora del servidor y las marcas UTC del tema 34. La interfaz calcula o recibe edades con una referencia coherente y muestra la zona horaria de las fechas. El reloj local del navegador puede estar adelantado o atrasado; no se usa sin más como prueba de la edad física del dato.

En el simulador, todos los tiempos son segundos relativos al mismo T0 y el reloj se elige manualmente. Esta simplificación permite comprobar cada escenario sin esperar minutos reales ni depender de la hora de la computadora.

04 · Dibujar lo que se conoce

Gráficas que no inventen información

Una serie temporal necesita eje de medición, unidad, intervalo y una explicación de qué representa cada marca. El tiempo de recepción sirve para estudiar transporte; para representar la evolución física usamos el de medición. Ordenar por llegada puede mover un incidente hacia el presente.

Un hueco no es una temperatura de cero ni una evolución conocida Dos gráficos esquemáticos muestran cuatro puntos válidos separados por una adquisición fallida. A la izquierda se los une de manera continua, sugiriendo conocimiento durante el hueco. A la derecha se interrumpe la línea y se identifica el intervalo sin observaciones válidas. La unión sugiere una continuidadEl corte conserva la incertidumbre No sabemos qué pasó entre esas muestrasSin dato válidoLa tabla conserva el motivo del hueco

Una línea entre puntos ya implica una convención de interpolación. Si el sensor falló o hubo una separación mucho mayor que la esperada, unirlos puede sugerir una continuidad que no conocemos. La gráfica cruda del laboratorio corta la línea ante una adquisición inválida o una separación mayor que 90 s, con reportes nominales de 60 s.

Un dato que todavía no llegó no es necesariamente una adquisición fallida. Antes del reenvío vemos un hueco; después puede completarse con sus marcas de origen. La calidad inválida, en cambio, es una observación explícita del sistema sobre esa adquisición.

Un umbral dibujado no es la alarma

La línea de 8 °C ayuda a interpretar la temperatura. No reproduce por sí sola histéresis, persistencia, calidad ni versión de regla. La alarma del tema 32 es un estado confirmado por otra lógica. Su activación y recuperación se dibujan como eventos con sus tiempos originales.

El gráfico del ejemplo muestra una temperatura alta en t = 180 s y una activación en t = 183 s. El dispositivo muestrea localmente cada segundo, pero la gráfica recibe una lectura por minuto. La regla tiene información intermedia que esos puntos periódicos no muestran. Una muestra de 7,8 °C en t = 300 s puede coexistir con una alarma todavía activa.

Inspeccionar sin depender solo del dibujo

El usuario debe poder conocer el valor y tiempo de una observación, y distinguir muestra, media y extremo. Una tabla o una exportación permiten revisar lo que la resolución visual no alcanza a mostrar. Las fechas, los redondeos y las unidades deben ser consistentes entre tarjeta, gráfico y tabla.

05 · Estado físico y atención humana

Alarmas y reconocimiento

Una alarma tiene al menos dos dimensiones: si la condición sigue activa y si alguien la reconoció. Reconocer significa «vi este aviso»; recuperar significa que la lógica del proceso confirmó la salida. Confundirlas puede ocultar una condición que todavía requiere atención.

Estados simplificados de una alarma y su presentación.
Estado confirmadoReconocimientoEtiqueta posible
No se recibió un estado inicialNo aplicaSin estado informado
ActivaPendienteActiva · sin reconocer
ActivaRecibidoActiva · reconocida
RecuperadaSegún la política de seguimientoRecuperada, con historial del incidente

La falta de eventos no demuestra normalidad: un cliente que acaba de abrir el panel puede no conocer el estado inicial. En producción, una instantánea del estado y una historia de eventos permiten establecer el punto de partida. El simulador deja «Sin estado informado» hasta recibir una transición.

El reconocimiento se asocia a la identidad del incidente, con usuario y fecha, y requiere los permisos correspondientes en un sistema real. No se envía una temperatura inventada ni se fuerza una recuperación. Si existe un rearme manual del equipo, es una operación de control con condiciones propias, que se estudia en los próximos temas.

No reactivar por un evento viejo que llegó tarde

Si una recuperación de t = 362 s ya fue recibida y luego llega una activación de t = 183 s, esa entrega completa el historial. No vuelve a poner activa la alarma actual. El servicio ordena por el identificador y la secuencia de transiciones definidos para ese dispositivo; el tiempo ayuda cuando su calidad y orden son confiables.

El modelo didáctico usa tiempos de origen confiables y sin empates. En una implementación se necesita un orden estable incluso con reinicios, cambios de reloj y fechas repetidas. El orden de llegada del WebSocket no sustituye ese contrato.

Alerta de datos vencidos

Una alarma física activa puede coexistir con diagnóstico atrasado. No se elimina la alarma al perder comunicación; se indica que el conocimiento está desactualizado. Un aviso de «sin datos recientes» debe identificar esa causa, en lugar de hacerse pasar por una nueva lectura alta.

«Reconocimiento del operador» no es el ACK de transporte de los temas anteriores. Uno registra atención humana; el otro confirma una etapa de entrega de datos. Un nombre parecido no los convierte en el mismo hecho.

06 · De la consulta a la vista viva

Consultar y actualizar sin retroceder

El panel normalmente consulta una API, no la base directamente. La API aplica permisos por sitio y dispositivo, valida intervalos y devuelve datos acotados con calidad y tiempos. El navegador no necesita credenciales administrativas ni descargar toda la historia para mostrar la última lectura.

Consulta periódica

La interfaz pide una instantánea cada cierto tiempo. Es simple de razonar; agrega espera entre consultas y debe evitar solicitudes superpuestas.

Actualizaciones persistentes

WebSocket o un flujo de eventos acercan cambios cuando llegan. Requieren reconexión, control del volumen y recuperación de lo ocurrido durante el corte.

La tecnología del canal no garantiza frescura de sensor. La API de WebSocket en el navegador permite comunicación persistente, pero la aplicación sigue necesitando acotar buffers, procesar los mensajes y recuperar el estado después de una desconexión.

Dos respuestas pueden llegar al revés

El usuario selecciona la cámara 07 y enseguida la 08. Si la respuesta lenta de la 07 llega después, no debe reemplazar la pantalla de la 08. Cancelar la solicitud anterior y comprobar que la respuesta pertenece a la selección vigente evita esa carrera.

let solicitud = 0;
let anterior = null;

async function cargarDispositivo(id) {
  const turno = ++solicitud;
  if (anterior) anterior.abort();
  const control = new AbortController();
  anterior = control;
  try {
    const respuesta = await fetch(`/api/dispositivos/${encodeURIComponent(id)}/panel`, {
      signal: control.signal,
      cache: 'no-store'
    });
    if (!respuesta.ok) throw new Error(`HTTP ${respuesta.status}`);
    const datos = await respuesta.json();
    if (turno !== solicitud) return; // la selección ya cambió
    // Validar esquema, identidad y revisión antes de aplicar la instantánea.
    // construirVista(datos); mostrarVista(...);
  } catch (error) {
    if (error.name === 'AbortError' || turno !== solicitud) return;
    // Mostrar error de consulta; conservar la vista con su antigüedad real.
  }
}

Es un fragmento de integración con una API hipotética, no el código de red del laboratorio. Un sondeo real agrega un tiempo máximo de espera y programa la siguiente consulta al terminar la anterior, además de una política de reintento. Desactivar caché no garantiza una adquisición reciente: se revisan las marcas temporales de la respuesta.

Instantánea y flujo sin perder el intervalo entre ambos

Al combinar una consulta inicial con eventos, definí una revisión o cursor de corte. La instantánea corresponde a una revisión y el flujo debe continuar desde ella, o permitir recuperar lo faltante. «Primero consulto y después me suscribo» sin un contrato puede perder cambios ocurridos entre esas dos operaciones.

Después de reconectar se obtiene una nueva instantánea o se reanudan los cambios desde el cursor conocido. Los eventos repetidos se reconocen por identidad y las respuestas viejas no hacen retroceder una revisión más nueva. Ese cursor del servidor no es la fecha del último mensaje que casualmente vio el navegador.

07 · Resumir para la pantalla

Resolución y resúmenes del gráfico

Un día con una muestra por segundo contiene 86.400 puntos. Si el gráfico mide 900 píxeles de ancho, representar cada observación puede costar mucho sin hacer visible más detalle. La API puede elegir una resolución según el intervalo, con un presupuesto de puntos.

Puntos crudos = duración / período de adquisición
Ventanas de resumen ≈ duración / ancho de ventana
Ejemplo: 24 h / 5 min = 288 ventanas

El resumen del tema 34 conserva total, válidas, suma, mínimo y máximo. Una gráfica de media más rango muestra tendencias y extremos con muchos menos elementos. Tomar solo «uno de cada cien puntos» puede omitir justo el pico que ocurrió entre esos puntos seleccionados.

La media puede quedar debajo del límite

En nuestra traza, los reportes de t = 120 y 180 s son 4,3 y 9,0 °C. La ventana [120, 240) tiene media de 6,65 °C. Si se muestra solo esa media, la marca queda debajo de 8 °C aunque hubo un reporte por encima. La vista de rango conserva el máximo de 9,0 °C.

El rango no indica cuánto duró la temperatura alta. Tampoco permite reconstruir el orden interno de todas las muestras. En un incidente puede ser necesario acercar el intervalo y consultar un detalle que todavía esté retenido. Si los crudos ya vencieron, el panel debe indicar la resolución disponible y no simular un zoom de datos que ya no existen.

Ventanas parciales y cobertura

Una ventana que todavía está en curso tiene menos observaciones por una razón distinta de otra que terminó con lecturas inválidas. Mostrá estado de intervalo y cantidades por separado. Que el intervalo haya terminado tampoco garantiza que no llegarán correcciones tardías: el plazo de cierre definitivo pertenece a la política de ingesta y retención.

En el simulador las ventanas duran 120 s. El estado «Intervalo terminado» solo significa que su extremo final ya pasó respecto del reloj elegido. Al recibir datos tardíos se recalculan los resúmenes, incluso si ese intervalo había terminado.

Cuando cambies resolución, no mezcles un resumen y sus puntos crudos en un total como si fueran observaciones diferentes. Son dos representaciones de la misma historia. La leyenda, las tablas y cualquier exportación deben decir cuál se está usando.

08 · Que el estado pueda entenderse

Accesibilidad y errores visibles

El color ayuda a localizar problemas, pero no debe ser el único portador de significado. Un borde naranja puede acompañar «Alarma activa» o «Dato atrasado»; la etiqueta identifica cuál de las dos situaciones ocurrió. W3C explica este principio en Uso del color, WCAG 1.4.1.

  • Texto y unidad: mostrar «7,8 °C · Actual», no solo un número de cierto color.
  • Formas y leyenda: distinguir muestras, medias y rangos, además de sus colores.
  • Teclado: filtros y botones con etiquetas y foco visible, sin depender de pasar el puntero por una marca.
  • Alternativa del gráfico: descripción y tabla con los datos relevantes.
  • Actualizaciones: un estado breve que se anuncie sin mover el foco del usuario.

Una gráfica es una imagen compleja: un texto breve describe su propósito, pero una tabla o descripción ampliada aporta los valores que no caben en una frase. Es el enfoque de la guía de imágenes complejas de W3C. En el laboratorio, las tablas conservan lecturas, resúmenes y eventos.

Los cambios de estado se pueden anunciar con role="status" o una región viva adecuada, sin enviar el foco al mensaje. La explicación de Mensajes de estado, WCAG 4.1.3 también señala la necesidad de informar sin interrumpir innecesariamente. No conviene anunciar cada segundo todas las cifras de un panel grande.

Un error de consulta no es una medición

Si falla la API, se conserva la última vista con su fecha y un aviso de actualización fallida. No se ponen todos los sensores en cero ni se renueva la antigüedad de sus lecturas. Al volver la conexión se informa la actualización y se valida la nueva revisión.

Una tarjeta que está cargando, otra sin datos y otra sin permisos no deberían mostrar el mismo guion sin explicación. Sus causas y acciones posibles son diferentes. Tampoco se expone un dispositivo de otro cliente al mostrar errores o aplicar filtros: los permisos se verifican en el servidor.

09 · Lógica de presentación comprobable

Un modelo de vista separado de la interfaz

Antes de dibujar, construimos un resultado con campos explícitos: estado del dato, valor que se puede presentar como actual, último válido, edades, diagnóstico y alarma. La interfaz toma ese resultado y lo muestra. Así se puede probar qué debería decir sin depender de colores, navegador o biblioteca de gráficos.

  1. Filtrar lo recibido: una instantánea solo puede usar entregas conocidas hasta su instante de consulta.
  2. Reconocer identidades: un reintento no agrega otra observación ni reemplaza su primera recepción.
  3. Ordenar por origen: la última medición y la última transición se eligen por su orden de origen válido.
  4. Evaluar dimensiones: calidad, frescura y diagnóstico se calculan por separado.
  5. Presentar y resumir: conservar huecos, cantidades y etiquetas coherentes.

La base del tema 34 ya hace la deduplicación principal. Repetir una comprobación de identidad en el cliente ayuda al aplicar eventos de una reconexión, pero no reemplaza las restricciones y permisos del servicio. El navegador tampoco debería reinterpretar silenciosamente una regla física con parámetros diferentes de los del dispositivo.

Escenarios del laboratorio

Diez reportes de medición nominales, de t = 0 a t = 540 s, y latidos cada 120 s.
EscenarioQué cambiaQué debe mostrar la vista
NormalLecturas y diagnóstico llegan sin retrasoValor fresco y alarma independiente de la última temperatura
Falla de sensorDesde t = 300 s hay adquisiciones inválidas; siguen los latidosDato inválido con diagnóstico reciente; la alarma no se recupera sola
Corte de comunicaciónNo llegan lecturas ni latidos después de t = 240 sDato y diagnóstico atrasados, conservando el último estado de alarma
Datos tardíosLecturas de 180 y 240 s llegan a los 550 y 551 s; hay un reintento a los 553 sSe completa historia sin reemplazar la medición de 540 s
Sin datosNo hay lecturas, latidos ni eventosDesconocido, sin inventar temperatura ni estado normal

En el escenario tardío, la activación de t = 183 s llega a los 552 s. La recuperación de t = 362 s ya llegó a los 362 s. El panel debe seguir mostrando recuperada al recibir esa activación antigua.

Los límites iniciales son 120 s de frescura y 240 s de silencio de diagnóstico. La gráfica cruda usa las mediciones que llegaron, no una señal física secreta; no puede mostrar lo que todavía no conoce el receptor.

10 · Simulación reproducible

Construir el estado en Python

Este programa reproduce el modelo del panel sin interfaz. Usa segundos relativos, temperaturas en décimas y escenarios deterministas. Las comprobaciones cubren datos tardíos, duplicados, calidad inválida, desconocimiento y el límite exacto de frescura.

Python en el navegador. Podés ejecutar y editar el ejemplo; la primera ejecución descarga Pyodide. También funciona como un archivo Python 3 local, sin placa ni servicios.

def datos(escenario):
    if escenario == "vacio":
        return dict(lecturas=[], latidos=[], eventos=[])
    valores = [41, 42, 43, 90, 92, 78, 74, 73, 42, 41]
    lecturas = [dict(id=f"m-{i+1}", t=i*60, rx=i*60, valor=c, calidad=1)
                for i, c in enumerate(valores)]
    latidos = [0, 120, 240, 360, 480, 600]
    eventos = [dict(id="e-1", t=183, rx=183, tipo="activada"),
               dict(id="e-2", t=362, rx=362, tipo="recuperada")]
    if escenario == "sensor":
        lecturas = [dict(f, valor=None, calidad=0) if f["t"] >= 300 else f
                    for f in lecturas]
        eventos = eventos[:1]
    elif escenario == "corte":
        lecturas = [f for f in lecturas if f["t"] <= 240]
        latidos = [t for t in latidos if t <= 240]
        eventos = eventos[:1]
    elif escenario == "tardio":
        lecturas = [dict(f, rx=550) if f["t"] == 180 else
                    dict(f, rx=551) if f["t"] == 240 else f for f in lecturas]
        lecturas.append(dict(lecturas[4], rx=553))
        eventos = [dict(eventos[0], rx=552), eventos[1]]
    return dict(lecturas=lecturas, latidos=latidos, eventos=eventos)


def construir(escenario="normal", ahora=300, frescura=120,
              silencio=240, reconocida=False):
    fuente = datos(escenario)
    llegadas = sorted((f for f in fuente["lecturas"] if f["rx"] <= ahora),
                      key=lambda f: (f["rx"], f["t"]))
    vistos = {}
    for f in llegadas:
        vistos.setdefault(f["id"], f)
    lecturas = sorted(vistos.values(), key=lambda f: f["t"])
    validas = [f for f in lecturas if f["calidad"] == 1]
    ultima = lecturas[-1] if lecturas else None
    ultima_valida = validas[-1] if validas else None
    edad = ahora - ultima_valida["t"] if ultima_valida is not None else None
    estado_dato = ("Sin datos" if ultima is None else
                   "Inválido" if ultima["calidad"] != 1 else
                   "Atrasado" if edad > frescura else "Actual")
    latidos = [t for t in fuente["latidos"] if t <= ahora]
    ultimo_latido = latidos[-1] if latidos else None
    edad_latido = ahora - ultimo_latido if ultimo_latido is not None else None
    estado_enlace = ("Sin diagnóstico" if edad_latido is None else
                     "Diagnóstico atrasado" if edad_latido > silencio else
                     "Diagnóstico reciente")
    eventos = sorted((f for f in fuente["eventos"] if f["rx"] <= ahora),
                     key=lambda f: f["t"])
    activa = eventos[-1]["tipo"] == "activada" if eventos else None
    estado_alarma = ("Sin estado informado" if activa is None else
                     "Recuperada" if not activa else
                     "Activa · reconocida" if reconocida else "Activa · sin reconocer")
    grupos = {}
    for f in lecturas:
        inicio = (f["t"] // 120) * 120
        g = grupos.setdefault(inicio, dict(inicio=inicio, total=0, validas=0,
                                          suma=0, min=None, max=None))
        g["total"] += 1
        if f["calidad"] == 1:
            c = f["valor"]
            g["validas"] += 1
            g["suma"] += c
            g["min"] = c if g["min"] is None else min(g["min"], c)
            g["max"] = c if g["max"] is None else max(g["max"], c)
    resumenes = [dict(g, cerrada=g["inicio"] + 120 <= ahora) for g in grupos.values()]
    return dict(lecturas=lecturas, llegadas=len(llegadas),
                repetidas=len(llegadas)-len(lecturas), ultima=ultima,
                ultimaValida=ultima_valida, edad=edad, estadoDato=estado_dato,
                valorActual=ultima["valor"] if estado_dato == "Actual" else None,
                ultimoLatido=ultimo_latido, edadLatido=edad_latido,
                estadoEnlace=estado_enlace, eventos=eventos, activa=activa,
                estadoAlarma=estado_alarma, ultimaLlegada=llegadas[-1] if llegadas else None,
                resumenes=resumenes)


for escenario, ahora in [("normal", 300), ("sensor", 600), ("corte", 600),
                          ("tardio", 560), ("vacio", 600)]:
    r = construir(escenario, ahora)
    valor = "—" if r["valorActual"] is None else f'{r["valorActual"]/10:.1f} °C'
    print(f'{escenario:8} {valor:15} {r["estadoDato"]:10} {r["estadoEnlace"]}')
    print("         Alarma:", r["estadoAlarma"])

base = construir()
assert (base["valorActual"], base["estadoDato"], base["activa"]) == (78, "Actual", True)
sensor = construir("sensor", 600)
assert (sensor["valorActual"], sensor["estadoDato"], sensor["edad"]) == (None, "Inválido", 360)
assert sensor["estadoEnlace"] == "Diagnóstico reciente" and sensor["activa"] is True
corte = construir("corte", 600)
assert corte["estadoDato"] == "Atrasado" and corte["estadoEnlace"] == "Diagnóstico atrasado"
tardio = construir("tardio", 560)
assert (tardio["valorActual"], tardio["ultimaLlegada"]["valor"]) == (41, 92)
assert tardio["repetidas"] == 1 and tardio["activa"] is False
assert construir(reconocida=True)["estadoAlarma"] == "Activa · reconocida"
assert construir("vacio", 600)["activa"] is None
assert construir("corte", 360, frescura=120)["estadoDato"] == "Actual"
assert construir("corte", 361, frescura=120)["estadoDato"] == "Atrasado"
g = construir("normal", 600)["resumenes"][1]
assert g["suma"]/g["validas"]/10 == 6.65 and g["max"] == 90
print("\n11 comprobaciones superadas.")
print("Reconocer no recupera; recibir tarde no vuelve actual una medición antigua.")

Resultado inicial: normal muestra 7,8 °C actual con alarma activa. Falla de sensor conserva 9,2 °C como último válido, pero no como valor actual. Corte muestra dato y diagnóstico atrasados. Datos tardíos muestra 4,1 °C actual, frente a los 9,2 °C que elegiría la última llegada. Sin datos mantiene la alarma desconocida. Las once comprobaciones terminan sin errores.

El ejemplo asume identidades, tipos y relojes ya validados por la ingesta. No resuelve colisiones con contenido distinto, autenticación ni tiempos de origen futuros. En una API real esas condiciones forman parte del contrato y pueden producir un estado de error o calidad de tiempo desconocida.

La función no cambia registros ni dibuja: devuelve una vista derivada de una instantánea. Por eso podemos contrastarla con la interfaz JavaScript y probar los bordes sin esperar datos reales. La elección de colores y componentes no modifica las reglas que se verifican.

11 · Exploración interactiva

Operar el panel simulado

Elegí el escenario, el instante de consulta y los límites. «Construir vista» reconstruye la instantánea y reinicia el reconocimiento simulado. Después podés reconocer una alarma activa: el texto cambia, pero no su estado físico. No hay conexiones ni acciones externas.

Cámara 07 · Temperatura

Instante de consulta: T0 + 300 s

Lectura actual

—Sin evaluar

Último válido: —

Edad de ese valor: —

Comunicación de diagnóstico

Sin evaluar

Edad del último latido: —

Este estado no certifica el funcionamiento del sensor.

Alarma de temperatura

Sin estado informado

—

El reconocimiento registra atención; no recupera la condición.

Comparación didáctica: si se eligiera la última entrega como valor actual, se mostraría —. La tarjeta superior usa el tiempo de medición y la calidad.

Círculos: muestras válidas; la línea se interrumpe ante datos inválidos o separaciones mayores que 90 s. Rombos: medias ubicadas en el centro de su intervalo, no adquisiciones en ese instante; un rombo hueco indica un intervalo en curso. Barras: mínimo y máximo. Los eventos llevan texto. La línea horizontal es una referencia de 8 °C; la vertical indica el instante de consulta. Las tablas mantienen valores y tiempos en segundos.

Preparando panel.

Lecturas conocidas por el panel

Una fila por identidad, ordenada por medición. Una adquisición inválida conserva su calidad y no se transforma en cero.
Medido (s)Primera recepción (s)ValorCalidad

Transiciones de alarma recibidas

Se ordenan por su origen, aunque lleguen al revés. Una tabla vacía significa que no se recibió un estado inicial en esta simulación.
Ocurrió (s)Recibido (s)Evento

Resúmenes de dos minutos

Estado del intervalo respecto del reloj de consulta; los datos tardíos todavía pueden modificarlo.
Intervalo (s)TotalVálidasMínimoMediaMáximoIntervalo

Recorrido guiado

  1. Con los valores iniciales, la lectura es 7,8 °C · Actual, con diagnóstico reciente. La alarma sigue activa: estar por debajo de la referencia de 8 °C no demuestra que se haya confirmado su salida.
  2. Presioná Reconocer alarma. Pasa a «Activa · reconocida», sin cambiar la lectura ni generar un evento de recuperación. El botón queda deshabilitado para ese reconocimiento.
  3. Elegí Falla del sensor y t = 600 s. Aparece «Sin dato actual · Inválido», último válido 9,2 °C de t = 240 s y edad 360 s. El diagnóstico es reciente y la alarma conserva su activación.
  4. Elegí Corte de comunicación, t = 600 s y límites de 120/240 s. Dato y diagnóstico están atrasados. La alarma no desaparece porque dejó de llegar información.
  5. En el mismo corte, elegí t = 360 s. La lectura de t = 240 tiene edad 120 s y todavía cuenta como actual con ese límite. Si elegís t = 420, pasa a atrasada, mientras el diagnóstico puede seguir dentro de su umbral de silencio.
  6. Elegí Datos y evento tardíos, t = 560 s. El valor actual es 4,1 °C de t = 540 s. La última entrega sería 9,2 °C de t = 240 s. Hay once entregas y diez lecturas únicas; la alarma sigue recuperada aunque la activación vieja haya llegado después.
  7. Volvé a Reportes normales, t = 600 s, y alterná media y rango. En [120, 240) la media es 6,65 °C, pero el máximo es 9,0 °C. Los eventos conservan el contexto del incidente.
  8. Elegí Sin datos recibidos. No aparece una temperatura cero ni una alarma normal. El panel muestra desconocimiento de forma explícita y deshabilita el reconocimiento.

La simulación no mantiene un reloj automático: cambiar el instante vuelve a construir lo que el panel conocía en ese momento. Cada nueva construcción reinicia el reconocimiento para poder repetir el ejercicio; un sistema real lo guarda en el servidor con identidad de incidente y auditoría.

Desafío: ¿por qué una alarma activa no obliga a dibujar el valor actual por encima de 8 °C?

La alarma tiene memoria, histéresis y confirmación de salida. Además, el gráfico periódico no muestra todas las adquisiciones locales. El panel debe mostrar la regla y los eventos como contexto; no reemplaza el estado confirmado con una comparación visual del último punto.

12 · Diseñar y comprobar la presentación

Método y confusiones frecuentes

  1. Definí decisiones: qué debe poder resolver quien mira la flota o el dispositivo.
  2. Separá estados: valor, calidad, frescura, diagnóstico y alarma, con etiquetas independientes.
  3. Fijá referencias: unidad, zona horaria, reloj y límites exactos de antigüedad.
  4. Diseñá las consultas: intervalo, resolución, máximo de puntos y revisión de instantánea.
  5. Construí un modelo de vista: probalo antes de elegir colores o una biblioteca gráfica.
  6. Protegé el orden: datos tardíos y respuestas de otra selección no deben reemplazar un estado más nuevo.
  7. Representá incertidumbre: huecos, calidad inválida, ventanas parciales y ausencia de estado.
  8. Comprobá interacción: teclado, foco, texto, tablas y reconocimiento sin recuperación accidental.
  9. Probá fallas de extremo a extremo: API caída, reconexión, duplicados, reloj dudoso y restauración de la vista.

Qué conviene medir en el propio panel

Tiempo de respuesta, duración de renderizado, cantidad de puntos y retraso de actualización ayudan a detectar una interfaz saturada. Esas métricas describen el panel y su canal de datos; no renuevan la adquisición del sensor. Un indicador de «última actualización de pantalla» debe llamarse así y no confundirse con «última medición».

«Si el WebSocket está abierto, el sensor está conectado y sano»

El canal puede estar abierto entre navegador y servidor mientras el dispositivo lleva horas sin reportar. La frescura del sensor y del diagnóstico se calculan con sus propios datos.

«La lectura inválida se puede mostrar como cero para no romper el gráfico»

Cero es una temperatura posible. Dibujar ese valor inventa una observación y altera mínimos y tendencias. Se conserva calidad inválida y se interrumpe o etiqueta la representación.

«Reconocer la alarma la pone en verde»

La atención humana no cambia la condición física. La etiqueta debe conservar «activa» hasta que exista una recuperación confirmada o la transición de control prevista para ese equipo.

«La última entrega siempre es el último estado»

Una cola puede reenviar historia. Se ordena por la identidad y referencias de origen válidas, mientras recepción se conserva para estudiar el transporte. El dato tardío completa historia sin hacer retroceder la vista actual.

«Si el intervalo terminó, su resumen ya no cambia»

Puede llegar información atrasada. El tiempo de cierre definitivo depende de la política de tardanza y retención, no solo del reloj que aparece en el eje del gráfico.

«Una línea continua es una forma neutral de mostrar los puntos»

Sugiere una evolución entre observaciones. Si hubo un hueco importante o lecturas inválidas, conviene interrumpirla o identificar la interpolación. No se representa certeza donde falta evidencia.

13 · Práctica guiada

Predecí antes de comprobar

1. El borde de frescura

La última lectura válida ocurrió en t = 240 s y el límite es de 120 s. ¿Qué dice el estado a los 360 s y a los 361 s según la política del ejemplo?

Ver solución

A los 360 s tiene edad 120 s y es actual. A los 361 s tiene 121 s y es atrasada. La igualdad está incluida en el límite de frescura.

2. Sensor inválido, equipo que comunica

A los 600 s se recibe diagnóstico actual, pero todas las adquisiciones desde los 300 s son inválidas. El último valor válido fue 9,2 °C a los 240 s. ¿Qué se muestra?

Ver solución

Sin dato actual · Inválido, diagnóstico reciente y último válido de 9,2 °C con edad 360 s, claramente histórico. No se declara normalidad del proceso por haber recibido el latido.

3. Una recuperación que llega primero

El panel ya recibió una recuperación ocurrida a los 362 s. Después recibe la activación de los 183 s. ¿Debe volver a mostrar la alarma activa?

Ver solución

No. La activación antigua completa el historial. La transición más reciente por el orden de origen sigue siendo la recuperación. Esto presupone un contrato que permite ordenar esas transiciones de forma confiable.

4. La media esconde un punto alto

Una ventana contiene 4,3 y 9,0 °C. ¿Cuál es su media? ¿Qué información debería conservar la vista si importa saber que se superó 8 °C?

Ver solución

La media es 6,65 °C. Hay que conservar al menos el máximo de 9,0 °C o el detalle/evento adecuado. La media sola quedaría debajo de la referencia y ocultaría el punto alto.

5. Reconocer durante una falla de comunicación

La última alarma conocida está activa y el diagnóstico venció. Un operador reconoce ese incidente. ¿Qué dimensiones cambian y cuáles siguen sin conocerse?

Ver solución

Cambia el reconocimiento. La última condición conocida sigue activa y el diagnóstico sigue atrasado. El reconocimiento no aporta una medición nueva ni prueba recuperación o reconexión.

6. Una respuesta de otra selección

La consulta de la cámara 07 tarda más que la de la 08, seleccionada después. ¿Qué se comprueba antes de aplicar la respuesta tardía?

Ver solución

Que la respuesta corresponda a la selección y solicitud vigentes, además de una revisión válida. Se puede cancelar la solicitud anterior y usar un identificador de turno; el resultado de la 07 no reemplaza la pantalla de la 08.

7. Presupuesto de puntos

Hay un día de muestras cada segundo. ¿Cuántos puntos crudos son? ¿Cuántas ventanas de cinco minutos? ¿La reducción conserva la forma exacta?

Ver solución

Son 86.400 puntos frente a 288 ventanas. Un resumen con extremos conserva más que la media sola, pero no la forma ni el orden interno completos. El panel indica resolución y permite consultar detalle si todavía existe.

8. No llegó ninguna alarma

Un panel recién abierto no tiene estado inicial ni transiciones de una regla. ¿Qué etiqueta es más fiel: «Normal» o «Sin estado informado»?

Ver solución

Sin estado informado. La ausencia de eventos no demuestra que la regla esté normal. Se necesita una instantánea inicial o una política explícita que establezca ese estado.

14 · Síntesis

Ideas para recordar

  • Un panel responde preguntas de operación y diagnóstico. La vista general localiza problemas y el detalle permite explicarlos.
  • Valor, calidad, frescura, diagnóstico y alarma son dimensiones independientes; una etiqueta «conectado» no las reemplaza.
  • La historia se ordena por origen válido. Datos tardíos y reintentos no deben hacer retroceder la lectura o la alarma actuales.
  • Un hueco no es un cero ni una evolución conocida. La gráfica identifica muestras, medias, extremos e intervalos sin evidencia.
  • Reconocer una alarma registra atención humana. La recuperación corresponde a la lógica del proceso y conserva su propia transición.
  • La resolución debe ser explícita. En [120, 240), una media de 6,65 °C puede coexistir con un máximo de 9,0 °C.
  • Consultas y canales vivos necesitan límites, revisiones y recuperación de cortes. Una actualización de pantalla no renueva la fecha de adquisición.
  • Texto, formas, foco visible y tablas ayudan a interpretar el panel. La presentación se comprueba con fallas, datos ausentes y órdenes de llegada distintos.

¿Listo para el tema 37?

Antes de avanzar, dibujá una vista de tu dispositivo en cuatro situaciones: normal, sensor inválido, dato atrasado y alarma activa reconocida. Escribí qué sabe el sistema en cada una y qué información falta; después probá si la interfaz lo comunica sin depender solo del color.

En el próximo tema, Control remoto de dispositivos, pasamos de observar a enviar órdenes: encender, apagar y cambiar parámetros a distancia, distinguiendo lo solicitado de lo que el equipo realmente confirmó.