Descomposición modular del ecosistema: interfaces proporcionadas/requeridas, dependencias entre componentes y mecanismos de comunicación inter-componente
Archivo: backend/src/services/tcp.service.js
Responsabilidad: Gestiona la conexión TCP persistente con el IC en el puerto
6001. Implementa reconexión automática con backoff exponencial y el Watchdog de 1200ms que
detecta la pérdida del enlace.
Patrón: Singleton — una única instancia activa en el proceso.
Puerto: UDP 4531
Responsabilidad: Recibe frames $BPJ del Joystick táctico a ~100 Hz. Deserializa
los 3 ejes (signed int8) y mapea los 12 botones.
Dirección: Unidireccional (solo recepción).
Puerto: UDP 5501
Responsabilidad: Recibe comandos ASCII del Teclado Naval y envía tramas de
feedback (5 bytes) para actualizar los LEDs físicos del panel.
Dirección: Bidireccional (RX comandos + TX LEDs).
Puerto: UDP 70xx (múltiples)
Responsabilidad: Recibe sentencias NMEA 0183 de GPS ($GPGGA), Girocompás
($HEHDT) e Inclinómetro (Pitch/Roll). Parsea según los estándares IEC 61162-1.
Corrección DEF-02: Lectura Big-Endian del inclinómetro.
Puerto: UDP 8000 (Multicast)
Responsabilidad: Recibe tramas de 42 bytes del CMS con pistas tácticas. Cada
pista contiene bearing, range, clasificación NATO y el flag cmsEnabled.
Frecuencia: ~5 Hz por pista activa.
Puerto: UDP 37511 + (consoleNum - 1)
Responsabilidad: Lanza FFmpeg como proceso hijo aislado (child_process.spawn)
para decodificar el stream H.264 de la cámara EOT. Genera un proceso independiente por
consola.
Aislamiento: No compite con el Event Loop del backend.
Archivo: backend/src/services/binary-protocol.service.js
Responsabilidad: Núcleo del protocolo binario ICD. Serializa tramas TX (29
bytes) con campos de mando y checksum XOR, y deserializa tramas RX (31-33 bytes) con telemetría
del IC.
Patrón: Singleton — único punto de mutación del estado de protocolo.
Responsabilidad: Máquina de Estados Finita que gobierna las transiciones entre
modos de trabajo: RWS (Remote Weapon Station), EOT (Electro-Optical Tracker) y CMS Pista
(asignación de blanco).
Guard Clauses: No permite transición a CMS sin cmsEnabled=1.
Responsabilidad: Aplica el algoritmo de Deadzone (±5) a los ejes X/Y/Z del
Joystick para filtrar ruido mecánico. Mapea los 12 botones a acciones tácticas (energizar EOT,
seleccionar modo, zoom).
Salida: Valores normalizados listos para inyectar en la trama TX.
Responsabilidad: Parsea sentencias NMEA 0183 estandarizadas. Extrae posición GPS
(Lat/Lon), heading verdadero del buque (girocompás) y datos de estabilidad (pitch/roll).
Corrección: Lectura Big-Endian para inclinómetro (DEF-02).
Responsabilidad: Procesa tramas de pistas tácticas del CMS (42 bytes cada una).
Extrae bearing, range, clasificación NATO, y el flag crítico de habilitación de mando.
Impacto: cmsEnabled controla si el operador puede asignar mando de disparo.
Responsabilidad: Genera tramas de 5 bytes para actualizar los LEDs físicos del
Teclado Naval. Solo refleja estados confirmados por el IC (Hardware-Driven UI), nunca estado
optimista local.
Principio: Zero trust — LED encendido SOLO cuando el hardware confirma.
Archivo: backend/src/server.js
Responsabilidad: Punto de entrada del backend. Instancia todos los servicios,
configura los listeners de eventos, ejecuta el Heartbeat Loop (100ms con compensación de drift)
y coordina el pipeline de datos: Drivers → Dominio → WebSocket → Frontend.
Rol: Actúa como bus de eventos central (EventEmitter) del ecosistema.
Archivo: backend/src/services/station-manager.service.js
Responsabilidad: Gestiona la asignación de hasta 3 consolas (C1 Estribor, C2
Babor, C3 Popa). Implementa el patrón de exclusividad de mando: solo una consola puede tener el
mando activo a la vez.
Patrón: Singleton — garantiza consistencia global.
Puerto: ws://localhost:8001
Responsabilidad: Servidor WebSocket Full-Duplex que distribuye actualizaciones
JSON al frontend (broadcast) y recibe comandos del operador (SELECT_STATION, MODE_CHANGE,
SETTINGS).
Frecuencia: ~10 Hz de broadcast (sincronizado con Heartbeat).
Archivo: app/src/lib/stores.js
Stores:
• icData — Telemetría del IC (ronza, elevación, estado)
• stationStatus — Consola activa, modo trabajo, conexión
• gyroData — Heading del buque (girocompás)
• cmsTracks — Array de pistas tácticas activas
Reactividad: writable() → suscripción automática en componentes.
Responsabilidad: Renderiza el Plan Position Indicator (PPI) usando SVG vectorial
puro. Calcula transformaciones polares a cartesianas para posicionar los indicadores de bearing
(RWS/EOT) y las pistas CMS. Rota el displayen modo "Course Up" según el heading del
girocompás.
Renderizado: requestAnimationFrame → ≥30 FPS.
Responsabilidad: Muestra en tiempo real los valores de ronza (bearing),
elevación, estado del IC (encendido/apagado), modo de trabajo activo y nivel de señal TCP.
Actualización: Reactiva via $icData store (~10 Hz).
Responsabilidad: Renderiza el video H.264 decodificado de la cámara EOT sobre un Canvas HTML5. El stream es segregado por estación (C1→:37511, C2→:37512, C3→:37513).
Responsabilidad: Vista de depuración que muestra las tramas TX/RX en formato
hexadecimal crudo en tiempo real. Permite auditar cada byte del protocolo binario para
validación de integridad.
Uso: Pruebas, diagnóstico y auditoría operativa.
Responsabilidad: Panel de selección de estación (C1/C2/C3), configuración de IP del IC, y parámetros operativos. Envía comandos SELECT_STATION al backend via WebSocket.
Controlador hardware del FFS-RWS. Traduce los comandos digitales de BARRACUDA SVELT en señales de control para servomotores, relés e instrumentación óptica. Protocolo binario propietario ICD sobre TCP :6001.
Dispositivos de entrada del operador. El Joystick provee 3 ejes de mando y 12 botones tácticos (UDP :4531). El Teclado Naval provee 36 teclas con LEDs de feedback (UDP :5501 bidireccional).
Sensores de navegación del buque que emiten sentencias NMEA 0183 por UDP :70xx. Proveen posición, heading y estabilidad para el PPI y la compensación de horizontes.
Provee pistas tácticas (42 bytes/pista) y el flag de habilitación de asignación de mando. Sin cmsEnabled=1, el operador no puede asumir el control de disparo. UDP :8000 multicast.
3 cámaras del sistema Electro-Optical Tracker que emiten streams H.264/AVC por UDP RTP, segregados por estación (:37511/:37512/:37513). Decodificado por FFmpeg en cada PC consola.
| Componente Origen | Relación | Componente Destino | Mecanismo | Datos Intercambiados |
|---|---|---|---|---|
| TCPService | emite | BinaryProtocolService | EventEmitter ('tcp:data') | Buffer binario RX 31-33 bytes |
| BinaryProtocolService | usa | TCPService | sendFrame(buffer) | Buffer binario TX 29 bytes + XOR |
| JoystickDriver | emite | JoystickDecoder | EventEmitter ('joy:frame') | Ejes X/Y/Z raw + 12 botones |
| JoystickDecoder | usa | BinaryProtocolService | updateField() | Valores con deadzone aplicada |
| NMEADriver | emite | NMEAService | EventEmitter ('nmea:sentence') | Sentencias NMEA 0183 crudas |
| CMSDriver | emite | CMSService | EventEmitter ('cms:track') | Buffer 42 bytes por pista |
| CMSService | usa | FSM WorkMode | cmsEnabled flag | Habilitación de mando de disparo |
| FSM WorkMode | usa | BinaryProtocolService | updateField('workMode') | RWS=0x01, EOT=0x02, CMS=0x03 |
| server.js | usa | Todos los servicios | Instanciación directa | Configuración desde console.config.json |
| StationManager | usa | server.js | validateExclusivity() | ConsoleId de la estación activa |
| server.js | spawn | VideoService | child_process.spawn() | Puerto UDP dinámico por consola |
| WebSocketServer | ws | Svelte Stores | JSON broadcast ws://localhost:8001 | IC_DATA, STATION_STATUS, NAV_DATA, CMS_TRACKS |
| Svelte Stores | ws | WebSocketServer | JSON command ws://localhost:8001 | SELECT_STATION, MODE_CHANGE, SETTINGS |
| icData Store | suscribe | Radar.svelte | Svelte reactive $icData | Bearing RWS/EOT, telemetría |
| icData Store | suscribe | GaugePanel.svelte | Svelte reactive $icData | Ronza, elevación, estado IC |
| gyroData Store | suscribe | Radar.svelte | Svelte reactive $gyroData | Heading del buque (Course Up) |
| cmsTracks Store | suscribe | Radar.svelte | Svelte reactive $cmsTracks | Array de pistas tácticas CMS |
| FeedbackService | usa | KeyboardDriver | sendLedFeedback(state) | 5 bytes de estado LED confirmado |