Airbus Military

Sistema híbrido de cálculo militar aeroespacial

airbus space defence logo

Airbus Military necesitaba sustituir una herramienta legacy de cálculo aeroespacial por un sistema moderno que pudiera usarse en operaciones militares, muchas veces sin conexión a internet, trabajando con datos sensibles y con requisitos de alta fiabilidad.

El proyecto consistió en la creación de una nueva aplicación híbrida, escalable y mantenible, sobre la que después se han construido múltiples evolutivos y herramientas internas relacionadas.

Diseñé y desarrollé la nueva solución para que funcionara de forma consistente en Windows e iOS, y levanté toda la estrategia de automatización de pruebas para garantizar la calidad del software sin depender solo de tests manuales.

Entre las piezas clave que construí se encuentran:

  • Plugins nativos para aplicaciones híbridas (iOS/Electron) que permiten acceder a capacidades específicas de cada plataforma.
  • Un sistema de comunicación de datos entre módulos que facilita añadir nuevas funcionalidades sin romper las existentes.
  • Una arquitectura de testing E2E sobre dispositivos reales, con analítica integrada y ejecución guiada para personal no técnico.
  • Procesos de importación y despliegue de cargas complejas, con cifrado y descifrado de datos alineado con los requisitos de seguridad del entorno.

El nuevo ecosistema permitió al equipo moverse más rápido y ganar peso dentro de la organización: los evolutivos dejaron de ser proyectos pesados para convertirse en iteraciones mucho más ágiles sobre una base estable.

La capa de pruebas automáticas redujo de forma significativa los errores en producción y, sobre todo, liberó tiempo al equipo de ingenieros en operaciones de vuelo: ahora pueden lanzar baterías de tests complejos sin saber programar y con evidencias claras de qué se ha probado en cada versión (vídeos, capturas, cobertura, etc).

En la práctica, el sistema ha reducido el trabajo manual repetitivo, ha disminuido el riesgo de fallo humano y ha hecho mucho más cómodo evolucionar una herramienta crítica en un entorno altamente regulado.

LTA+

Aplicación Híbrida

airbus space defence logo

Si tuviera que resumir este proyecto en una frase, sería algo así como: un motor de cálculo de los 70 incrustado en una app híbrida moderna, con requisitos militares, mucha restricción y cero margen para hacer el tonto.

No fue un proyecto “de libro”: hubo mucho código legacy, herramientas rotas, ciberataques, documentación muy escasa y decisiones que había que tomar con información incompleta. Pero precisamente por eso fue clave para mí.

Me obligó a salir mi rol de “frontend Angular” y pensar en el sistema completo: motor heredado, plugins nativos, seguridad, flujo de datos, UX real de los usuarios.

Aprendí a tomar ownership cuando nadie te da el manual: montar infra improvisada, diseñar procesos de importación, proponer una arquitectura técnica E2E ante un problema que lleva años enquistado.

Confirmé que prefiero resolver problemas reales (aunque estén llenos de barro) antes que vivir en entornos perfectos (SPOILER: no existen).

¿Repetiría todo tal cual? No. Hoy plantearía algunos bloques de otra forma, modularizaría antes ciertas partes y atacaría la automatización de testing mucho antes en el ciclo de vida del proyecto. Pero este trabajo marcó un antes y un después en cómo entiendo mi papel: no solo como alguien que escribe código, sino como alguien que arma soluciones complejas, con restricciones reales y responsabilidad sobre lo que llega al usuario final.

Arquitectura

Monolítica & Multicapa

airbus space defence logo

La aplicación sigue una arquitectura monolítica multi-capa que se ejecuta íntegramente en local. Excepcionalmente, el proceso de importación ejecuta operaciones SFTP contra sistemas externos, alojados en redes locales (para que nos entendamos, no puedes llegar si no estás en la base militar presencialmente).

A más bajo nivel se encuentra el motor de cálculo aeronáutico (llamado CAPS), desarrollado originalmente en Fortran y transpilado a C. A partir de ahí se compila como librería estática/dinámica (.a/.dll para iOS/Windows). Un plugin de Capacitor se encarga de mapear y lanzar a las operaciones a través de Node.js y Swift/Objective-C.

En la capa intermedia, Capacitor actúa como wrapper entre el frontal (Angular) y las implementaciones nativas. Gracias a esto, la misma base de código funciona tanto en Electron (Windows) como en iPad (iOS).

Al tratarse de una aplicación militar, debe operar en entornos hostiles, con conectividad limitada o directamente sin conexión. Por eso:

  • Toda la lógica se ejecuta en local.
  • La aplicación ma ntiene una base de datos local.
  • La carga de datos se realiza previamente “en tierra”, en entornos seguros, mediante SFTP.
  • Tras un proceso de importación complejo, la información se almacena en: ficheros JSON, base de datos SQLite y base de datos DexieJS.

La arquitectura fue evolucionando de forma orgánica, condicionada por los requerimientos específicos del proyecto y, sobre todo, por el motor de cálculo heredado: una evolución de un motor aeronáutico utilizado en aviones de los años 70 y 80, que imponía muchas restricciones sobre cómo debíamos diseñar el resto de capas.

Plugins Nativos

CAPS, Filesystem, SFTP & ZIP

airbus space defence logo

Durante el desarrollo tuvimos que afrontar varios desafíos que implicaban interactuar con la capa nativa. Trataré de resumir los plugins más importantes que fabricamos.

CAPS Cordova Plugin

En otras secciones ya he hablado del CAPS. Para resumir, es un motor de cálculos aerespacial hecho en fortran y transpilado a C. Para utilizar el motor de cálculo desde Angular, heredamos un plugin Cordova.

El plugin tenía en su interior el motor de cálculo, almacenado como librería estática (caps.a para iOS). Desde objective-c, se mapeaban las funciones con una capa C. La capa C, a su vez, realizaba llamadas directamente contra la librería estática y devolvía la información.

Este plugin fue uno de los retos técnicos más grandes del proyecto, y hablo más en profundidad de él en las secciones de Arquitectura y en Comunicaciones Multicapa.

EFB Filesystem Plugin

Uno de los problemas recurrentes en este proyecto era que queríamos tratar el sistema de ficheros igual en iPad y en Windows (Electron), pero el plugin oficial de Filesystem no cubría bien el caso desktop. Eso nos obligaba a escribir código condicional y ramas específicas por plataforma, justo lo contrario a lo que quieres en una app crítica.

Para solucionarlo, propuse un fork del plugin oficial de Filesystem de Ionic y añadimos una implementación específica para Electron. El objetivo era muy simple: Desde el punto de vista del código de negocio, trabajar con ficheros debe ser igual en iOS que en Electron.

EFB SFTP Plugin

Para poder actualizar la app en entornos militares sin acceso a internet “normal”, necesitábamos hablar con un servidor SFTP: descargar cargas de datos, subir reportes de configuración y hacerlo todo de forma controlada.

La solución fue crear un plugin SFTP propio, con implementación nativa en iOS/iPad (Swift + NMSSH) y su equivalente para Electron (Node + ssh2-sftp-client).

EFB ZIP Plugin

Con las cargas de datos teníamos el problema de descomprimir ficheros en el dispositivo. Ya existían soluciones de la comunidad disponibles, pero tenían poco soporte, y muchas no permitían la descompresión de ficheros cifrados.

La falta de fiabilidad de los plugins disponibles, junto con que muchos no soportaban Electron + iOS, nos llevó a construir nuestra propia solución: un plugin que permite comprimir y descomprimir ficheros con contraseña opcional, para Electron e iOS.

Mi Rol

Funciones, metodoloía & documentación

airbus space defence logo

Al inicio, era el único desarrollador del equipo junto con mi Team Lead. Yo llegaba con un perfil centrado en Angular y heredamos una aplicación legacy con código espagueti, difícil de mantener y tecnológicamente obsoleta. Tras varios intentos de iterar sobre esa base, llegamos a la conclusión de que sería más eficiente sustituirla por un nuevo desarrollo desde cero.

En unos 3 meses conseguimos una réplica funcional de la aplicación original, pero con un código mucho más escalable y mantenible. La nueva implementación mejoró notablemente la capacidad de respuesta de la app y permitió una UX/UI más dinámica y moderna.

Con el tiempo fueron incorporándose nuevos compañeros que también aportaron mucho al producto. En paralelo, mi rol fue cambiando: pasé de desarrollador frontend especializado en Angular a desarrollador de aplicaciones híbridas (Ionic + Capacitor), y me convertí en uno de los desarrolladores de referencia del equipo. Mis compañeros solían plantearme cuestiones sobre implementaciones y de temas técnicos.

Mi Team Lead empezó a consultarme de forma recurrente sobre problemas técnicos, alternativas de software e incluso algunas cuestiones de organización del equipo. En la fase final del proyecto llegué a cubrir su rol durante su baja por paternidad. En ese periodo seguí siendo principalmente un perfil técnico, pero también asumí responsabilidades de coordinación: organización del trabajo, reparto de tareas (sobre todo de soporte y mantenimiento) y soporte al equipo en la toma de decisiones.


Metodología y documentación

El equipo seguía una adaptación propia de SCRUM, ajustada a las particularidades de Airbus y al tipo de software. Se utilizaban sprints de un mes, lo que ayudaba a proteger al equipo del goteo continuo de requerimientos informales y aglutinar los nuevos requisitos para planificar el siguiente sprint con cabeza.

Fue un enfoque propuesto por el Team Lead que funcionó especialmente bien en este contexto.

En cuanto a documentación, no existía un proceso formal y exhaustivo. La mayor parte de la documentación se centraba en código y en operativa compleja, creada por iniciativa de los propios desarrolladores. Algunos flujos críticos, como la rquitectura de testing E2E, quedaron documentados con alto grado de detalle.

Personalmente, abogo por evitar la sobredocumentación: documentar lo crítico, lo contraintuitivo y lo que aporta valor real al mantenimiento, pero no convertir cada detalle del código en papeleo que encarece el desarrollo sin aportar retorno.

Tecnología

Dispositivos y lenguajes

airbus space defence logo

La aplicación se construyó principalmente para funcionar en iPads. Posteriormente, se dio soporte a sistemas Windows. Los dispositivos soportados son:

  • iPad, iPad Pro y iPad Mini. Se hicieron pruebas en en entorno macOS de escritorio con éxito, pero nunca se llevó a producción para estos dispositivos.
  • Microsoft Surface
  • Dispositivos Windows en general

En cuanto al software, la aplicación se construyó utilizando estas tecnologías principales:

  • Ionic, Angular, Capacitor y TypeScript para el frontal y la capa híbrida.
  • Swift (iOS) y Node.js (Windows) para el desarrollo de plugins nativos.
  • Python para scripts de automatización y procesos de encriptación.

Durante el desarrollo también fue necesario trabajar con C/Objective-C, ya que el motor de cálculo estaba escrito originalmente en Fortran y transpilado a C. Uno de nuestros plugins propios ejecutaba estas funciones en C desde Swift. No fue necesario programar C, pero sí entender lo suficiente el código como para mapear correctamente los parámetros desde el plugin hacia el motor de cálculo. Esto lo explicaré con más detalle en la sección de retos técnicos.

Tests Automáticos E2E

Arquitectura Técnica

airbus space defence logo

El testing tradicional en Angular (Jasmine/Karma) se aplicó solo a módulos y funcionalidades críticas. La validación funcional de los cálculos y la operativa recaía en un equipo de ingenieros, ya que muchos detalles escapaban al conocimiento del equipo de desarrollo.

WDIO interface WDIO interface

Arquitectura Técnica

Las pruebas de regresión se hacían siempre a mano, tanto por parte del equipo técnico como por los ingenieros en operaciones de vuelo. Eran procesos largos, repetitivos y con mucha exposición al error humano.

Quise atacar este problema por mi cuenta y, durante mi tiempo libre, estuve investigando herramientas hasta dar con una combinación viable: Appium + WebdriverIO, ejecutando tests sobre la app real en iPad y en entorno de escritorio. Monté la base del proyecto en TypeScript + Jasmine para no sacar al equipo de su zona de confort.

El reto más delicado fue conseguir que los tests corrieran en dispositivos iOS sin disponer de cuenta de pago de Apple, lo que implicó varios workarounds y un procedimiento muy concreto. Documenté todo el proceso en una guía interna para que el resto del equipo pudiera replicarlo sin problemas.

A partir de ahí diseñé la arquitectura técnica con una idea clara: los tests debían poder ser definidos por personal no técnico.

La solución fue basarlos en ficheros CSV:

  • Cada fila del CSV representa un caso de prueba, con entradas y salidas esperadas.
  • El sistema lee el CSV, genera los tests de forma dinámica y ejecuta los cálculos en la app nativa.
  • Los resultados que aparecen en la pantalla de la app se comparan automáticamente con los valores esperados y se marcan como OK/KO.

Con este modelo, los especialistas en operaciones de vuelo pueden crear y mantener sus baterías de pruebas directamente desde Excel, sin tocar código. Solo con esto ya conseguimos reducir de forma muy clara el tiempo dedicado a testing manual y eliminar gran cantidad de trabajo mecánico.

Para que también aportara valor a perfiles de gestión y certificación, evolucioné la solución con:

  • Generación automática de informes, con un dashboard donde se ve el número de casos ejecutados, porcentaje de éxito y detalle de los fallos.
  • Capturas de pantalla y vídeos de cada ejecución, configurables, que sirven como evidencia para auditorías y para los procesos de subida a producción.

En la práctica, el sistema permite:

  1. Cargar un CSV exportado desde Excel.
  2. Lanzar una campaña de tests sobre la app real.
  3. Obtener un informe visual con resultados, métricas y evidencias (imágenes/vídeo).

Esto tuvo un impacto directo en el equipo de operaciones de vuelo: pasaron de tener que validar a mano, caso a caso, durante horas o días, a poder lanzar campañas completas de pruebas en cadena y revisarlas de forma mucho más ágil y fiable, varias veces al mes.

Toda esta arquitectura fue iniciativa personal, desarrollada completamente en mi tiempo libre antes de presentarla al equipo.

Seguridad & Datos

Software Militar

airbus space defence logo

Siendo una aplicación militar, la seguridad era un requisito central. Por ello, el software funciona solo en entorno local, sin conexiones externas durante la operación normal.

La carga de datos se realiza exclusivamente en entornos seguros, mediante SFTP. Para ello se desarrolló un plugin de Capacitor específico para SFTP, con cierta complejidad añadida por la falta de librerías maduras y documentación clara en iOS.

Además, se implantó un formato de datos estricto, alineado con estándares aeronáuticos, lo cual hizo el proceso de importación más complejo a la par que muy eficaz para detectar inconsistencias en los datos entrantes.

El proceso de importación valida el formato de cada campo, verifica su correcta estructura y garantiza un almacenamiento coherente en la app.

Para la validación de licencias de clientes se diseñó un sistema basado en ficheros de licencia encriptados con variantes de algoritmos estándar + codificación Base64. Se utiliza un script de Python para generar licencias. En la app, un servicio de desencriptado (Angular) para validar las licencias en tiempo de ejecución.

En cuanto a la ingestión de datos desde SFTP:

  • Se descarga un fichero comprimido protegido por contraseña.
  • El usuario introduce la contraseña previo a proceder con la importación: descompresión, validación e ingestión de datos.

Una vez validados, los datos se reparten entre:

  • Ficheros JSON estáticos
  • Una base de datos SQLite consumida mediante un plugin de Ionic
  • Y una Inner DB en Angular consumida con una implementación propia basada en DexieJS + observables, asegurando reactividad en la lectura de datos.

Comunicaciones Multicapa

El motor de cálculo

airbus space defence logo

Este fue uno de los retos más duros del proyecto. El objetivo era claro pero nada trivial: conectar la app híbrida con el motor de cálculo en C (CAPS) y entender cómo alimentar y leer esa “caja negra”.

La documentación era muy mínima y las primeras pruebas no funcionaban. Durante un tiempo dependimos de un plugin Cordova legacy que “misteriosamente” hacía las llamadas correctas, pero sin explicar cómo. A partir de ahí tocó hacer ingeniería inversa y reconstruir la lógica con algo más sostenible.

Cuando el proyecto maduró y ya conocíamos mejor el sistema, pudimos avanzar:

  • Para Windows (Electron) se generó una versión del motor como .dll y se creó una capa nativa específica que hacía de puente con esa librería: recibía los parámetros desde la app, llamaba a la DLL y devolvía los resultados.
  • En Angular, la app usaba servicios distintos según la plataforma (Electron | iPad), seleccionados mediante un patrón tipo Factory, de forma que el resto del código no tuviera que preocuparse de los detalles de cada entorno.
  • El motor trabajaba con un array de números plano, donde cada posición correspondía a una variable. Ese mapping se hizo prácticamente “a mano”: había parámetros obligatorios incluso cuando no aplicaban a ciertos cálculos y valores especiales que había que respetar para que el motor no fallase.
  • La salida funcionaba igual: otro array donde cada índice tenía un significado concreto. Hasta que no descubrías qué representaba cada posición, era imposible interpretar los resultados.

Todo esto se hizo con documentación muy limitada y fragmentada, apoyándonos en el comportamiento del plugin antiguo y en muchas pruebas controladas. Fue un proceso largo, pero permitió que la app híbrida hablara de forma fiable con un motor crítico que nadie quería tocar, y sentó las bases para poder mantenerlo a futuro sin depender de “magia negra”.

Importación de Datos

XML, JSON, SQLite & DexieJS

airbus space defence logo

Otro reto importante fue diseñar el proceso de importación de datos. Yo definí la primera versión del flujo, que luego fue creciendo hasta convertirse casi en un subsistema complejísimo.

El problema, en resumen, era este:

  • Cargar una lista de aeropuertos y sus propiedades desde un XML generado por un software legacy.
  • Cargar y validar una base de datos SQLite con la información técnica necesaria para los cálculos: fases del vuelo, características de la flota, configuración específica de cada avión, modificaciones, etc.
  • Detectar y corregir datos incoherentes (pistas con orientaciones > 360º, pistas invertidas, valores imposibles, etc.).
  • Dejarlo todo en un formato que la aplicación pudiera consumir de forma rápida y consistente.

Para el XML diseñé un flujo de importación muy orientado a objetos:

  1. El XML se parseaba a un objeto intermedio.
  2. Ese objeto alimentaba una clase AirportList.
  3. Cada aeropuerto se construía como instancia de Airport.
  4. Cada aeropuerto creaba a su vez sus pistas (Runway[]), ajustando y corrigiendo datos en el propio constructor.

Al final del proceso teníamos en memoria un modelo limpio y coherente, que se volcaba a un único fichero JSON local. Este enfoque tenía varias ventajas:

  • Podíamos validar y limpiar los datos antes de escribir nada en disco.
  • En caso de fallo durante la importación, la app seguía funcionando con la lista anterior.
  • La persistencia se reducía a un solo “commit” final, simple y fácil de razonar.

El flujo de SQLite era diferente:

  • Primero se copiaba la base de datos a nivel de fichero usando el plugin de FileSystem de Ionic.
  • Después se verificaba su integridad y coherencia frente a los datos de aeropuertos importados desde el XML.

Con el tiempo, el sistema de importación fue incorporando más tipos de datos, más reglas de validación y más pasos intermedios. Mi aportación evolucionó hacia refactorizar y aplicar principios SOLID: separar responsabilidades, aislar reglas de negocio y hacer que la lógica fuese más legible, testeable y sencilla de extender a futuro, sin tener que reescribir el núcleo cada vez que entraba un nuevo requisito.

Ciberataque

Linux & Git

airbus space defence logo

Pocos meses después de incorporarme, un ciberataque tumbó todos los repositorios y sistemas de la empresa (Akkodis, antes Akka Consulting). Nuestro equipo quedó sin herramientas para coordinarse ni para trabajar con el código.

Hablando con mi Team Lead buscamos una solución para restaurar la continuidad de desarrollo:

  • En un equipo disponible monté un servidor Linux con arranque dual Windows / Linux.
  • Instalé Ubuntu Server con un entorno gráfico ligero (XFCE).
  • Desplegué una instancia de GitLab Community.
  • Publiqué el servicio a través de mi red doméstica, abriendo los puertos necesarios para acceso externo.

De esta forma el equipo volvió a tener un repositorio remoto desde el que trabajar mientras los sistemas corporativos estaban caídos. Más adelante, mi Team Lead se hizo cargo de la máquina y le asignó una DNS adecuada para disponer de un entorno más seguro hasta que todo volvió a la normalidad.

No era mi especialidad, pero me permitió aprender y, sobre todo, evitar que el proyecto se quedara bloqueado.