Saltar a contenido

Registro, aserciones y escenarios

Lo que separa un banco de pruebas de una maqueta bonita. Se construye desde la fase 1.

El simulador es el único observador posible

El controlador pertenece a otro equipo. El simulador es el único punto donde se puede registrar la conversación completa con marca de tiempo. Ese registro es la evidencia con la que se discutirá cualquier fallo de temporización.

Reloj

Todo lo que se registre o se emita usa el reloj monótono del proceso, en microsegundos desde el arranque. Nunca la hora de pared.

Un ajuste NTP en el nodo Swarm haría saltar los timestamps hacia atrás en mitad de una prueba y corrompería la traza. La hora de pared se guarda una sola vez, en el evento de arranque de sesión, para poder situar la sesión en el calendario.

Registro de eventos

SQLite en modo WAL. Numeración monótona por sesión. Persistido antes de enviar por WebSocket.

CREATE TABLE events (
  n         INTEGER PRIMARY KEY,
  t_us      INTEGER NOT NULL,   -- monotono desde arranque
  kind      TEXT    NOT NULL,
  signal    TEXT,
  actor     TEXT,
  payload   TEXT                -- JSON
);
CREATE INDEX idx_events_t   ON events(t_us);
CREATE INDEX idx_events_sig ON events(signal, t_us);

Todo evento Modbus registra unit ID, código de función, dirección, valores y el instante en que el simulador aplicó el cambio, no el de recepción del datagrama.

Escrituras fuera del tick

better-sqlite3 es síncrono. Las escrituras se acumulan en un buffer en memoria y se vuelcan en lote desde el camino desacoplado. Escribir dentro del lazo de tick introduce jitter en la medida que el banco existe para tomar.

Sesiones

Una sesión abarca desde la carga de configuración hasta la siguiente. Se identifica por hash del JSON aplicado, lo que permite saber después con qué radar exacto se corrió cada prueba.

Descargable como fichero para adjuntar a un ticket.

Aserciones

Evaluadas en el simulador contra su reloj monótono (D-14).

{
  "id": "hv-drop-on-interlock",
  "description": "El HV debe caer en menos de 200 ms tras perder el interlock",
  "when": "falling(tx.interlocks_ok)",
  "expect": "not tx.radiating_status",
  "within_ms": 200
}

El instante t=0 es aquel en que el simulador aplica la condición de disparo. El momento del clic del operador no es medible y no se usa.

El resultado registra el margen medido, no solo aprobado o fallado: saber que el controlador tardó 190 ms sobre un límite de 200 es información distinta de saber que tardó 20 ms.

Tipos útiles:

Tipo Qué comprueba
within_ms La condición se cumple antes del plazo
not_before_ms La condición no se cumple antes del plazo, para verificar retardos deliberados
stable_for_ms La condición se mantiene durante el plazo
never La condición no se cumple en toda la sesión

Escenarios

Secuencias temporizadas en JSON. Existen porque las pruebas de temporización repetibles no se pueden hacer a mano: el retardo del túnel hace que el clic no sea un instante.

{
  "id": "blower-fail-and-reset",
  "steps": [
    { "at_ms": 0,    "action": "force",   "signal": "tx.cb_blower_ok_status", "value": false },
    { "at_ms": 300,  "action": "assert",  "id": "hv-drop-on-interlock" },
    { "at_ms": 5000, "action": "release", "signal": "tx.cb_blower_ok_status" },
    { "at_ms": 5300, "action": "pulse",   "signal": "tx.reset_faults_command", "ms": 100 }
  ]
}

Los tiempos se miden contra el reloj monótono, así que la ejecución es reproducible dentro de la resolución del tick.

El forzado manual sigue siendo el modo principal de trabajo

Los escenarios son para pruebas repetibles y regresión. El trabajo exploratorio del operador es manual y en caliente, que es como se descubren los comportamientos que luego merece la pena convertir en escenario.

Métricas de calidad de enlace

El simulador contabiliza y expone, para cada sesión: transacciones Modbus por segundo, latencia entre petición y respuesta, paquetes UDP emitidos y descartados por degradación, y desviación real de la cadencia respecto a la nominal.

Sirven para responder la pregunta que aparece siempre al analizar un fallo: si el problema fue del controlador o del banco.