Modelo de hardware multinivel: sensores, tarjetas, sistemas

Sesion s32 · 2026-04-11 · Como se mapea el hardware fisico y simulado al DataPlane

1. Los tres niveles del hardware

El hardware de la plataforma LRU tiene una jerarquia natural de tres niveles. Esto aplica tanto al hardware fisico real como al simulado:

Nivel 3: SISTEMA (system) Un sistema avionico completo — puede estar compuesto por multiples tarjetas Ej: ADIRU (Air Data Inertial Reference Unit) Engine Control (FADEC izq + FADEC der) Electrical System (3 generadores + 2 TRUs + baterias) Nivel 2: TARJETA / DISPOSITIVO (device) Una tarjeta electronica, microcontrolador, o LRU fisica Ej: ble_A92418 (ESP32 con BME280 + ADC + IMU + FPGA) FADEC_L (controlador motor izquierdo) ADR_1 (Air Data Reference modulo 1) Nivel 1: SENSOR (sensor) Un sensor individual que produce un valor numerico Ej: adc1 (canal ADC 12-bit) n1_l (RPM motor izquierdo, %) alt_baro_capt (altitud barometrica, pies) temp1 (temperatura BME280, °C)

Ejemplo real: tarjeta ESP32 ble_A92418

┌───────────────────────────────────────────────────────────────┐ │ ble_A92418 (ESP32 + Mongoose OS) NIVEL 2: TARJETA │ │ │ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │ │ │ BME280 │ │ MAX44009 │ │ ADC (4 canales) │ │ │ │ (I2C) │ │ (I2C) │ │ │ │ │ │ · temp1 °C │ │ · lux1 lux │ │ · adc1 0-4095 │ │ │ │ · pres1 hPa │ │ │ │ · adc2 0-4095 │ │ │ │ · hum1 % │ │ │ │ · adc3 0-4095 │ │ │ └─────────────┘ └─────────────┘ │ · adc4 0-4095 │ │ │ └─────────────────────┘ │ │ ┌──────────────────────────┐ ┌──────────────────────────┐ │ │ │ MPU9255 + AK8963 (I2C) │ │ FPGA (SPI) │ │ │ │ · ax, ay, az ±16g │ │ · sw1 switches │ │ │ │ · gx, gy, gz ±2000°/s│ │ · cnt1 contador │ │ │ │ · mx, my, mz ±1200µT │ │ · track1_h joystick H │ │ │ └──────────────────────────┘ │ · track1_v joystick V │ │ │ └──────────────────────────┘ │ │ │ │ Total: 25 sensores en 1 tarjeta │ └───────────────────────────────────────────────────────────────┘

Ejemplo real: sistema ADIRU A320 (simulado)

┌───────────────────────────────────────────────────────────────┐ │ ADIRU (Air Data Inertial Reference Unit) NIVEL 3: SISTEMA │ │ │ │ En un A320 real: 3 unidades (ADIRU 1, 2, 3) cada una con │ │ su propia tarjeta, comunicadas via ARINC 429 │ │ │ │ ┌────────────────────┐ ┌────────────────────┐ │ │ │ ADR (Air Data) │ │ IR (Inertial Ref) │ │ │ │ │ │ │ │ │ │ · alt_baro pies │ │ · pitch ° │ │ │ │ · cas nudos │ │ · roll ° │ │ │ │ · mach ratio │ │ · heading ° │ │ │ │ · sat °C │ │ · track ° │ │ │ │ · tat °C │ │ · gs nudos │ │ │ │ · qnh hPa │ │ · lat/lon ° │ │ │ └────────────────────┘ └────────────────────┘ │ │ │ │ En simulacion: sim1_adiru_capt (1 hwObj con ~15 sensores) │ │ En hardware futuro: podria ser 3 tarjetas fisicas │ └───────────────────────────────────────────────────────────────┘

Ejemplo real: sistema compuesto de motores

┌───────────────────────────────────────────────────────────────────┐ │ Engine Control System NIVEL 3: SISTEMA │ │ │ │ ┌──────────────────────────┐ ┌──────────────────────────┐ │ │ │ sim1_engine_l │ │ sim1_engine_r │ │ │ │ (FADEC motor izquierdo) │ │ (FADEC motor derecho) │ │ │ │ NIVEL 2: DISPOSITIVO │ │ NIVEL 2: DISPOSITIVO │ │ │ │ │ │ │ │ │ │ · n1_l % │ │ · n1_r % │ │ │ │ · n2_l % │ │ · n2_r % │ │ │ │ · egt_l °C │ │ · egt_r °C │ │ │ │ · ff_l kg/h │ │ · ff_r kg/h │ │ │ │ · oil_qty_l qt │ │ · oil_qty_r qt │ │ │ │ · oil_psi_l psi │ │ · oil_psi_r psi │ │ │ │ · vib_n1_l mils │ │ · vib_n1_r mils │ │ │ └──────────────────────────┘ └──────────────────────────┘ │ │ │ │ El ECAM lee de AMBOS dispositivos simultaneamente │ └───────────────────────────────────────────────────────────────────┘

2. Como se ve todo esto en el DataPlane

El DataPlane aplana toda la jerarquia. No importa si un sensor pertenece a una tarjeta con 25 sensores o a un sistema con 3 tarjetas — en el DataPlane es un slot con un nombre unico:

DataPlane — Float64Array plano, 512 slots CANALES DEL HARDWARE REAL (BLE): hw/ble_A92418/adc1 → slot 100 → Float64 hw/ble_A92418/adc2 → slot 101 hw/ble_A92418/temp1 → slot 102 hw/ble_A92418/pres1 → slot 103 hw/ble_A92418/ax → slot 104 hw/ble_A92418/ay → slot 105 ... (25 sensores) hw/ble_0BC4BC/adc1 → slot 125 ← mismo nombre de sensor, hw/ble_0BC4BC/adc2 → slot 126 distinto dispositivo, hw/ble_0BC4BC/temp1 → slot 127 distinto slot CANALES DE SIMULACION (SIM_CATALOG): hw/sim1_adiru_capt/alt_baro → slot 0 hw/sim1_adiru_capt/cas → slot 1 hw/sim1_adiru_capt/pitch → slot 2 hw/sim1_engine_l/n1_l → slot 20 hw/sim1_engine_l/egt_l → slot 21 hw/sim1_engine_r/n1_r → slot 30 hw/sim1_engine_r/egt_r → slot 31 ... (137+ canales total)
Principio fundamental: el DataPlane no conoce niveles

El DataPlane solo conoce canales planos con un nombre unico compuesto de hw/{deviceId}/{sensorId}. No sabe si sim1_engine_l y sim1_engine_r son parte del mismo "sistema de motores" — esa agrupacion logica vive en el SIM_CATALOG (nivel de dominio), no en el DataPlane (nivel de transporte).

3. Donde vive el conocimiento de cada nivel

NivelConceptoQuien lo modelaEjemplo
Nivel 3
Sistema
Agrupacion logica de dispositivos SIM_CATALOG → DisplayDef con multiples SystemDef Display "ECAM" agrupa systems: engine_l, engine_r, apu, elec, hyd...
Escenarios por sistema SIM_CATALOG → ScenarioDef afecta sensores de multiples devices Escenario "Engine Fire L" afecta sensores de sim1_engine_l + sim1_elec + sim1_hyd
Nivel 2
Dispositivo
Identidad y ciclo de vida ORC → hwObjs map (online/offline, firmware, type) ble_A92418: type=physical, firmware=rpc1cl_v2.1.0
RouterMode por dispositivo RouterService → routerMode per hwObjId ble_A92418: HwReal, sim1_engine_l: Rnd
Registro de sensores SIM_CATALOG (sim) ó capabilities MQTT (hw real) sim1_engine_l: 7 sensores definidos en catalogo
Nivel 1
Sensor
Valor numerico en tiempo real DataPlane → Float64Array[slot] slot 21 = 620.0 (EGT motor izq, °C)
Metadatos del sensor SIM_CATALOG → SensorDef (min, max, unit, cruise, thresholds) egt_l: min=0, max=1000, unit=°C, cruise=620, amber=850, red=950

4. Como IB_04 resuelve un sensor: el camino completo

4.1 Sensor de simulacion (sim1_*)

Clip manifest declara: needles: { "egt_gauge": { sensorId: "egt_l" } } IB_04 en init: 1. Busca "egt_l" en SIM_CATALOG → encontrado en system "engine_l", display "ecam" → SensorDef: { id:"egt_l", min:0, max:1000, unit:"°C", cruise:620 } 2. Calcula el deviceId: → display "ecam" ≠ "hw" → deviceId = "sim1_engine_l" 3. Resuelve el canal del DataPlane: → channelName = "hw/sim1_engine_l/egt_l" → dpIndex = dp.indexOf("hw/sim1_engine_l/egt_l") → slot 21 4. Cachea NeedleBinding: { sensorId: "egt_l", dpIndex: 21, min: 0, max: 1000, clipRef: <aguja> } IB_04 en tick: raw = dp.read(21) → 620.0 pct = (620 - 0) / (1000 - 0) = 0.62 aguja.change1(0.62, 620.0)

4.2 Sensor de hardware real (ble_*)

Clip manifest declara (modo channel para hardware enlazable): needles: { "speed": { channel: "speed" } } IB_04 en init: 1. Consulta el ORC: ¿que hwObj esta enlazado a este swObj, canal "speed"? → enlace activo: hwObjId = "ble_A92418", puerto = "adc1" 2. Resuelve el canal del DataPlane: → channelName = "hw/ble_A92418/adc1" → dpIndex = dp.indexOf("hw/ble_A92418/adc1") → slot 100 3. Busca metadatos del sensor: → SIM_CATALOG no tiene "adc1" de ble_A92418 → Usa capabilities del hwObj (enviadas por firmware): min=0, max=4095 → O usa cfg1 del ORC como fallback: valMin1In=0, valMax1In=4095 4. Cachea NeedleBinding: { sensorId: "adc1", dpIndex: 100, min: 0, max: 4095, clipRef: <aguja> } IB_04 en tick: raw = dp.read(100) → 2048.0 pct = (2048 - 0) / (4095 - 0) = 0.5 aguja.change1(0.5, 2048.0)

4.3 Sistema compuesto: ECAM con datos de multiples dispositivos

Clip manifest (ECAM Upper Display): this.ib04 = { swObj: "ECAM_Upper", needles: { "n1_l": { sensorId: "n1_l" }, // sim1_engine_l → slot 20 "n1_r": { sensorId: "n1_r" }, // sim1_engine_r → slot 30 "egt_l": { sensorId: "egt_l" }, // sim1_engine_l → slot 21 "egt_r": { sensorId: "egt_r" }, // sim1_engine_r → slot 31 "ff_l": { sensorId: "ff_l" }, // sim1_engine_l → slot 22 "ff_r": { sensorId: "ff_r" }, // sim1_engine_r → slot 32 } }; IB_04 en init: Resuelve cada sensorId independientemente: · "n1_l" → SIM_CATALOG → system "engine_l" → device "sim1_engine_l" → slot 20 · "n1_r" → SIM_CATALOG → system "engine_r" → device "sim1_engine_r" → slot 30 · "egt_l" → SIM_CATALOG → system "engine_l" → device "sim1_engine_l" → slot 21 ... IB_04 NO necesita saber que "engine_l" y "engine_r" son parte del mismo "sistema de motores". Cada NeedleBinding apunta a su slot y punto. IB_04 en tick: Recorre los 6 NeedleBindings, lee 6 slots, normaliza, llama 6× change1(). No importa que vengan de 2 dispositivos distintos — son 6 reads O(1).

5. Escenarios clave y como se resuelven

5.1 Tarjeta con muchos sensores (25 sensores, solo uso 3)

No hay desperdicio

La tarjeta ble_A92418 tiene 25 sensores, pero el AirSpeed solo usa 3 (adc1, adc2, adc3). IB_04 solo crea 3 NeedleBindings y solo lee 3 slots del DataPlane en cada tick. Los otros 22 sensores siguen existiendo en el DataPlane (otros instrumentos pueden leerlos), pero este clip los ignora. Zero overhead por sensores no usados.

Contraste con IB_03: recibia UN CustomEvent con los 25 puertos JSON-serializados, parseaba todo, y luego filtraba por channelMap.

5.2 Mismo sensor fisico en multiples instrumentos

Lectura compartida sin conflicto

alt_baro_capt puede estar en el PFD, en el Altimetro STBY, y en el ND simultaneamente. Los tres leen el mismo slot del DataPlane — es una lectura pura (Float64Array[21]), sin estado, sin locks, sin copia. Multiplicar lectores es gratis.

5.3 Cambiar entre hardware real y simulado

Solo cambia el dpIndex del NeedleBinding

Cuando el instructor cambia la fuente de un instrumento:

Simulacion: sensorId: "cas_capt"dpIndex: slot 1 (canal sim1_adiru_capt/cas)

Hardware real: se re-enlaza → dpIndex: slot 100 (canal ble_A92418/adc1)

El NeedleBinding actualiza dpIndex, min, max. El siguiente tick lee del nuevo slot. Zero destroy/recreate.

5.4 Sistema futuro con multiples tarjetas fisicas

Escenario futuro: un ADIRU real compuesto por 3 tarjetas ESP32, cada una con sus sensores:

ADIRU real: tarjeta_adiru_1 (ESP32): alt_baro_1, cas_1, mach_1, sat_1 tarjeta_adiru_2 (ESP32): alt_baro_2, cas_2, mach_2, sat_2 tarjeta_adiru_3 (ESP32): alt_baro_3, cas_3, mach_3, sat_3 DataPlane: hw/tarjeta_adiru_1/alt_baro_1 → slot 200 hw/tarjeta_adiru_1/cas_1 → slot 201 hw/tarjeta_adiru_2/alt_baro_2 → slot 210 hw/tarjeta_adiru_2/cas_2 → slot 211 hw/tarjeta_adiru_3/alt_baro_3 → slot 220 hw/tarjeta_adiru_3/cas_3 → slot 221 PFD Captain (swObj): needles: { "alt": { sensorId: "alt_baro_1" }, // ADIRU 1 para captain "spd": { sensorId: "cas_1" }, } PFD F/O (swObj): needles: { "alt": { sensorId: "alt_baro_2" }, // ADIRU 2 para first officer "spd": { sensorId: "cas_2" }, }
El modelo escala sin cambios

No importa si hay 1 tarjeta o 30. Cada tarjeta registra sus sensores en el DataPlane. Cada instrumento apunta sus agujas a los sensorIds que necesita. El DataPlane aplana todo. IB_04 solo ve slots planos.

6. El SIM_CATALOG como registro de metadatos

El SIM_CATALOG ya modela los tres niveles, aunque implicitamente:

Concepto catalogoNivelQue contiene
DisplayDef Vista / agrupacion por pantalla id, label, lista de SystemDefs. Ej: "ecam", "pfd", "nd", "hw"
SystemDef Nivel 2 (dispositivo logico) id, label, lista de SensorDefs. Ej: "engine_l", "adiru_capt"
SensorDef Nivel 1 (sensor) id, label, min, max, unit, cruise, thresholds, puertoHwObj

Lo que IB_04 necesita del catalogo

// IB_04 solo necesita esto para resolver un sensorId:
interface SensorResolution {
  sensorId:   string;    // "egt_l"
  deviceId:   string;    // "sim1_engine_l" — para construir el canal DataPlane
  min:        number;    // 0
  max:        number;    // 1000
  unit?:      string;    // "°C" — opcional, para change1(pct, rawValue) con texto
}

// Funcion de resolucion:
function resolveSensor(sensorId: string): SensorResolution | null {
  for (const display of SIM_CATALOG.displays) {
    for (const system of display.systems) {
      const sensor = system.sensors.find(s => s.id === sensorId);
      if (sensor) {
        const isHw = display.id === 'hw';
        const deviceId = isHw ? system.id : `sim1_${system.id}`;
        return {
          sensorId: sensor.id,
          deviceId,
          min: sensor.min,
          max: sensor.max,
          unit: sensor.unit,
        };
      }
    }
  }
  return null;  // no encontrado — quizas es hardware BLE, resolver via ORC
}
Resolucion en dos fases

Fase 1: Buscar en SIM_CATALOG. Si existe → tenemos deviceId, min, max. Resuelto.

Fase 2: Si no esta en el catalogo (es hardware BLE/MQTT real) → consultar ORC para enlace activo, usar cfg1/capabilities para min/max.

La mayoria de los sensorIds se resuelven en Fase 1 (todos los sensores de simulacion). Solo los sensores de hardware real enlazable necesitan Fase 2.

7. Registro de hardware real en el DataPlane

Cuando un dispositivo BLE real se conecta, sus sensores se registran en el DataPlane via el ORC:

1. ESP32 se conecta al broker MQTT 2. Envia capabilities: { sensores: ["adc1","adc2","temp1","pres1",...], ranges: {...} } 3. MqttAdapter.onMessage() → ORC.handleMqttEvent() 4. ORC registra hwObj "ble_A92418" con 25 sensores 5. DataPlane registra canales: hw/ble_A92418/adc1 → slot auto-asignado hw/ble_A92418/adc2 → slot auto-asignado hw/ble_A92418/temp1 → slot auto-asignado ... 6. Datos llegan: { adc1: 2048, adc2: 3100, temp1: 23.5, ... } 7. ORC → ControlBus.allows() → DataPlane.fromRecord() 8. DataPlane.write(slot, valor) 9. IB_04 tick: dp.read(slot) — el valor ya esta ahi, listo para leer

Para el hardware simulado (sim1_*), el registro ocurre al inicializar la app — el SIM_CATALOG define todos los sensores de antemano y el SimService los registra en el DataPlane.

8. Tabla resumen: donde vive cada cosa

PreguntaRespuestaDonde vive
¿Que sensores tiene un dispositivo? Lista de SensorDefs SIM_CATALOG (sim) ó capabilities MQTT (hw)
¿Que dispositivos forman un sistema? Agrupacion logica SIM_CATALOG → DisplayDef agrupa SystemDefs
¿Cual es el rango de un sensor? min, max, unit SensorDef en SIM_CATALOG ó cfg1 en ORC
¿Que valor tiene un sensor ahora? Float64 DataPlane → slot directo
¿De donde lee una aguja concreta? sensorId → dpIndex IB_04 → NeedleBinding
¿Que modo tiene un dispositivo? Loc/Rnd/HwSim/HwReal RouterService
¿Quien puede escribir en un sensor? Fuente permitida por routerMode ControlBus
¿El dispositivo esta online? Estado de conexion ORC → hwObj.status
¿Que enlace tiene un instrumento? swObj → hwObj + channelMap ORC → matrizEnlaces (solo para hw enlazable)

9. Conclusion: la jerarquia se aplana, no se destruye

Principio de diseno

Los tres niveles de hardware (sensor → dispositivo → sistema) existen en el dominio y se modelan en el SIM_CATALOG. Pero en el plano de transporte (DataPlane), todo se aplana a una lista plana de slots Float64. IB_04 trabaja en el plano aplanado — no necesita subir a los niveles superiores excepto durante la resolucion inicial (init).

Esto significa que:

· Anadir un nuevo dispositivo con 50 sensores = registrar 50 slots mas en el DataPlane. Zero cambios en IB_04.

· Un instrumento que lee de 5 dispositivos distintos = 5 NeedleBindings, cada uno con su dpIndex. Zero cambios en IB_04.

· Cambiar una aguja de simulacion a hardware real = cambiar un dpIndex. Zero cambios en IB_04.

· Un sistema compuesto de 10 tarjetas con 200 sensores = 200 slots en el DataPlane. Los instrumentos apuntan a los que necesitan. IB_04 no cambia.

El modelo escala horizontalmente sin limites porque el DataPlane es un array plano y IB_04 solo hace dp.read(index) — O(1) sin importar cuantos sensores existan en el universo.