diff --git a/fbw-a32nx/src/base/flybywire-aircraft-a320-neo/SimObjects/AirPlanes/FlyByWire_A320_NEO/model/A320_NEO_INTERIOR.xml b/fbw-a32nx/src/base/flybywire-aircraft-a320-neo/SimObjects/AirPlanes/FlyByWire_A320_NEO/model/A320_NEO_INTERIOR.xml
index 31839d0d653..cbd344a974d 100644
--- a/fbw-a32nx/src/base/flybywire-aircraft-a320-neo/SimObjects/AirPlanes/FlyByWire_A320_NEO/model/A320_NEO_INTERIOR.xml
+++ b/fbw-a32nx/src/base/flybywire-aircraft-a320-neo/SimObjects/AirPlanes/FlyByWire_A320_NEO/model/A320_NEO_INTERIOR.xml
@@ -2193,6 +2193,7 @@
PUSH_OVHD_FUEL_LTKPUMPS1
OVHD_FUEL_LTKPUMPS1
2
+ 7
(L:A32NX_ELEC_AC_ESS_SHED_BUS_IS_POWERED, Bool)
False
False
@@ -2208,6 +2209,7 @@
PUSH_OVHD_FUEL_LTKPUMPS2
OVHD_FUEL_LTKPUMPS2
5
+ 9
(L:A32NX_ELEC_AC_2_BUS_IS_POWERED, Bool)
False
False
@@ -2253,6 +2255,7 @@
PUSH_OVHD_FUEL_RTKPUMPS1
OVHD_FUEL_RTKPUMPS1
3
+ 8
(L:A32NX_ELEC_AC_ESS_SHED_BUS_IS_POWERED, Bool)
False
False
@@ -2270,6 +2273,7 @@
COCKPIT.TOOLTIPS.ENG_2_R_TK_PUMP2_OFF
COCKPIT.TOOLTIPS.ENG_2_R_TK_PUMP2_ON
6
+ 10
(L:A32NX_ELEC_AC_2_BUS_IS_POWERED, Bool)
False
False
diff --git a/fbw-a32nx/src/behavior/src/A32NX_Interior_Misc.xml b/fbw-a32nx/src/behavior/src/A32NX_Interior_Misc.xml
index 6169f91635b..6f4ce75a0ae 100644
--- a/fbw-a32nx/src/behavior/src/A32NX_Interior_Misc.xml
+++ b/fbw-a32nx/src/behavior/src/A32NX_Interior_Misc.xml
@@ -196,6 +196,9 @@
#ID# (>K:FUELSYSTEM_PUMP_TOGGLE)
+
+ (A:FUELSYSTEM PUMP SWITCH:#ID#, Enum) 1 == (A:FUELSYSTEM LINE FUEL PRESSURE:#FUEL_LINE#, psi) 6 < and
+
(A:FUELSYSTEM PUMP SWITCH:#ID#, Enum) 0 ==
(A:FUELSYSTEM PUMP SWITCH:#ID#, Enum) 1 ==
@@ -218,6 +221,7 @@
+ (A:FUELSYSTEM VALVE OPEN:#ID#, Bool)
(A:FUELSYSTEM VALVE SWITCH:#ID#, Bool)
#ID# (>K:FUELSYSTEM_VALVE_TOGGLE)
%((A:FUELSYSTEM VALVE SWITCH:#ID#, Bool) !)%{if}TT:#OFF_TOOLTIP#%{else}TT:#ON_TOOLTIP#%{end}
diff --git a/fbw-a32nx/src/wasm/systems/a320_systems/src/electrical/alternating_current.rs b/fbw-a32nx/src/wasm/systems/a320_systems/src/electrical/alternating_current.rs
index 67ea4e65072..a03967325c3 100644
--- a/fbw-a32nx/src/wasm/systems/a320_systems/src/electrical/alternating_current.rs
+++ b/fbw-a32nx/src/wasm/systems/a320_systems/src/electrical/alternating_current.rs
@@ -6,12 +6,13 @@ use std::time::Duration;
use systems::{
apu::ApuGenerator,
electrical::{
- AlternatingCurrentElectricalSystem, Contactor, ElectricalBus, Electricity,
- EmergencyGenerator, ExternalPowerSource, IntegratedDriveGenerator, TransformerRectifier,
+ AlternatingCurrentElectricalSystem, Contactor, ElectricalBus, ElectricalElement,
+ Electricity, EmergencyGenerator, ExternalPowerSource, IntegratedDriveGenerator,
+ TransformerRectifier,
},
engine::Engine,
shared::{
- AuxiliaryPowerUnitElectrical, DelayedTrueLogicGate, ElectricalBusType,
+ AuxiliaryPowerUnitElectrical, DelayedTrueLogicGate, ElectricalBusType, ElectricalBuses,
EngineFirePushButtons,
},
simulation::{InitContext, SimulationElement, SimulationElementVisitor, UpdateContext},
@@ -36,6 +37,7 @@ pub(super) struct A320AlternatingCurrentElectrical {
ac_stat_inv_bus: ElectricalBus,
ac_gnd_flt_service_bus: ElectricalBus,
ext_pwr_to_ac_gnd_flt_service_bus_and_tr_2_contactor: Contactor,
+ auxiliary_supplies: A320AuxiliaryPowerSupplies,
}
impl A320AlternatingCurrentElectrical {
pub fn new(context: &mut InitContext) -> Self {
@@ -66,6 +68,7 @@ impl A320AlternatingCurrentElectrical {
ElectricalBusType::AlternatingCurrentGndFltService,
),
ext_pwr_to_ac_gnd_flt_service_bus_and_tr_2_contactor: Contactor::new(context, "12XN"),
+ auxiliary_supplies: A320AuxiliaryPowerSupplies::new(context),
}
}
@@ -204,6 +207,25 @@ impl A320AlternatingCurrentElectrical {
electricity.flow(&self.static_inv_to_ac_ess_bus_contactor, &self.ac_ess_bus);
}
+ /// ## Dependencies:
+ /// * AC electrical
+ /// * DC electrical
+ pub fn update_auxiliary(
+ &mut self,
+ electricity: &mut Electricity,
+ emergency_overhead: &A320EmergencyElectricalOverheadPanel,
+ ) {
+ self.auxiliary_supplies.update(
+ electricity,
+ &self.main_power_sources,
+ &self.ac_bus_1,
+ &self.ac_bus_2,
+ &self.ac_ess_shed_bus,
+ &self.ac_stat_inv_bus,
+ emergency_overhead,
+ );
+ }
+
fn update_shedding(
&mut self,
emergency_generator: &EmergencyGenerator,
@@ -333,6 +355,8 @@ impl SimulationElement for A320AlternatingCurrentElectrical {
self.ext_pwr_to_ac_gnd_flt_service_bus_and_tr_2_contactor
.accept(visitor);
+ self.auxiliary_supplies.accept(visitor);
+
visitor.visit(self);
}
}
@@ -460,6 +484,14 @@ impl A320MainPowerSources {
electricity.flow(&self.bus_tie_2_contactor, bus);
}
+ fn power_by_generator_1(
+ &self,
+ electricity: &mut Electricity,
+ element: &impl ElectricalElement,
+ ) {
+ electricity.flow(&self.engine_1_gen, element);
+ }
+
pub fn gen_contactor_open(&self, number: usize) -> bool {
self.engine_generator_contactors[number - 1].is_open()
}
@@ -544,3 +576,112 @@ impl SimulationElement for A320AcEssFeedContactors {
visitor.visit(self);
}
}
+
+struct A320AuxiliaryPowerSupplies {
+ // Fuel pumps 1 supply
+ fuel_pump_1_supply: ElectricalBus,
+ fuel_pump_1_normal_contactor: Contactor,
+ fuel_pump_1_standby_contactor: Contactor,
+
+ // Fuel pumps 2 supply
+ fuel_pump_2_supply: ElectricalBus,
+ fuel_pump_2_contactor: Contactor,
+
+ // APU fuel pump supply
+ apu_fuel_pump_supply: ElectricalBus,
+ apu_fuel_pump_static_inverter_contactor: Contactor,
+ apu_fuel_pump_ess_sched_contactor: Contactor,
+}
+impl A320AuxiliaryPowerSupplies {
+ fn new(context: &mut InitContext) -> Self {
+ Self {
+ fuel_pump_1_supply: ElectricalBus::new(
+ context,
+ ElectricalBusType::Virtual("FUEL_PUMP_1_SUPPLY"),
+ ),
+ fuel_pump_1_normal_contactor: Contactor::new(context, "17QA"), // 18QA for R WING pump, both have the same condition
+ fuel_pump_1_standby_contactor: Contactor::new(context, "53QA"), // 54QA for R WING pump, both have the same condition
+
+ fuel_pump_2_supply: ElectricalBus::new(
+ context,
+ ElectricalBusType::Virtual("FUEL_PUMP_2_SUPPLY"),
+ ),
+ fuel_pump_2_contactor: Contactor::new(context, "19QA"), // 20QA for R WING pump, both have the same condition
+
+ apu_fuel_pump_supply: ElectricalBus::new(
+ context,
+ ElectricalBusType::Virtual("FUEL_PUMP_APU_SUPPLY"),
+ ),
+ apu_fuel_pump_static_inverter_contactor: Contactor::new(context, "9QC.1"),
+ apu_fuel_pump_ess_sched_contactor: Contactor::new(context, "9QC.2"),
+ }
+ }
+
+ fn update(
+ &mut self,
+ electricity: &mut Electricity,
+ main_power_sources: &A320MainPowerSources,
+ ac_bus_1: &ElectricalBus,
+ ac_bus_2: &ElectricalBus,
+ ac_ess_sched: &ElectricalBus,
+ static_inverter_bus: &ElectricalBus,
+ overhead: &A320EmergencyElectricalOverheadPanel,
+ ) {
+ let dc_ess_powered =
+ electricity.any_is_powered(&[ElectricalBusType::DirectCurrentEssential]);
+ let dc_1_powered = electricity.any_is_powered(&[ElectricalBusType::DirectCurrent(1)]);
+ let dc_2_powered = electricity.any_is_powered(&[ElectricalBusType::DirectCurrent(2)]);
+ let gen_1_line_on = overhead.generator_1_line_is_on();
+
+ // Contactor powered by DC 1 but only when DC ESS is powered too
+ self.fuel_pump_1_normal_contactor
+ .close_when(gen_1_line_on && dc_1_powered && dc_ess_powered);
+ // Contactor powered by DC ESS if DC 1 is not powered or gen 1 line is off
+ self.fuel_pump_1_standby_contactor
+ .close_when((!gen_1_line_on || !dc_1_powered) && dc_ess_powered);
+
+ electricity.flow(ac_bus_1, &self.fuel_pump_1_normal_contactor);
+ main_power_sources.power_by_generator_1(electricity, &self.fuel_pump_1_standby_contactor);
+ electricity.flow(&self.fuel_pump_1_normal_contactor, &self.fuel_pump_1_supply);
+ electricity.flow(
+ &self.fuel_pump_1_standby_contactor,
+ &self.fuel_pump_1_supply,
+ );
+
+ // Contactor powered by DC 2
+ self.fuel_pump_2_contactor.close_when(dc_2_powered);
+ electricity.flow(ac_bus_2, &self.fuel_pump_2_contactor);
+ electricity.flow(&self.fuel_pump_2_contactor, &self.fuel_pump_2_supply);
+
+ let ess_sched_powered = electricity.is_powered(ac_ess_sched);
+ self.apu_fuel_pump_static_inverter_contactor
+ .close_when(!ess_sched_powered);
+ self.apu_fuel_pump_ess_sched_contactor
+ .close_when(ess_sched_powered);
+ electricity.flow(
+ static_inverter_bus,
+ &self.apu_fuel_pump_static_inverter_contactor,
+ );
+ electricity.flow(ac_ess_sched, &self.apu_fuel_pump_ess_sched_contactor);
+ electricity.flow(
+ &self.apu_fuel_pump_static_inverter_contactor,
+ &self.apu_fuel_pump_supply,
+ );
+ electricity.flow(
+ &self.apu_fuel_pump_ess_sched_contactor,
+ &self.apu_fuel_pump_supply,
+ );
+ }
+}
+impl SimulationElement for A320AuxiliaryPowerSupplies {
+ fn accept(&mut self, visitor: &mut T) {
+ self.fuel_pump_1_supply.accept(visitor);
+ self.fuel_pump_1_normal_contactor.accept(visitor);
+ self.fuel_pump_1_standby_contactor.accept(visitor);
+ self.apu_fuel_pump_supply.accept(visitor);
+ self.apu_fuel_pump_static_inverter_contactor.accept(visitor);
+ self.apu_fuel_pump_ess_sched_contactor.accept(visitor);
+
+ visitor.visit(self);
+ }
+}
diff --git a/fbw-a32nx/src/wasm/systems/a320_systems/src/electrical/mod.rs b/fbw-a32nx/src/wasm/systems/a320_systems/src/electrical/mod.rs
index 9d09d12a759..9c29b697963 100644
--- a/fbw-a32nx/src/wasm/systems/a320_systems/src/electrical/mod.rs
+++ b/fbw-a32nx/src/wasm/systems/a320_systems/src/electrical/mod.rs
@@ -132,6 +132,9 @@ impl A320Electrical {
spd_cond,
);
+ self.alternating_current
+ .update_auxiliary(electricity, emergency_overhead);
+
self.main_galley
.update(context, electricity, &self.alternating_current, overhead);
self.secondary_galley
diff --git a/fbw-a32nx/src/wasm/systems/a320_systems/src/fuel/mod.rs b/fbw-a32nx/src/wasm/systems/a320_systems/src/fuel/mod.rs
index dd82b0167a5..57b41cda935 100644
--- a/fbw-a32nx/src/wasm/systems/a320_systems/src/fuel/mod.rs
+++ b/fbw-a32nx/src/wasm/systems/a320_systems/src/fuel/mod.rs
@@ -2,7 +2,8 @@
use nalgebra::Vector3;
use systems::{
- fuel::{FuelCG, FuelInfo, FuelPayload, FuelSystem, FuelTank},
+ fuel::{FuelCG, FuelInfo, FuelPayload, FuelPump, FuelPumpProperties, FuelSystem},
+ shared::ElectricalBusType,
simulation::{InitContext, SimulationElement, SimulationElementVisitor},
};
use uom::si::f64::*;
@@ -45,7 +46,7 @@ impl From for A320FuelTankType {
}
pub struct A320Fuel {
- fuel_system: FuelSystem<5>,
+ fuel_system: FuelSystem<5, 5>,
}
impl A320Fuel {
pub const A320_FUEL: [FuelInfo<'static>; 5] = [
@@ -76,17 +77,60 @@ impl A320Fuel {
},
];
+ // TODO: connect MSFS fuel pumps to power logic
+ const FUEL_PUMPS: [(usize, FuelPumpProperties); 5] = [
+ // Left main tank pump 1
+ (
+ 2,
+ FuelPumpProperties {
+ // TODO: implement Gen 1 line
+ // ElectricalBusType::AlternatingCurrent(1) or Gen1
+ powered_by: ElectricalBusType::Virtual("FUEL_PUMP_1_SUPPLY"),
+ consumption_current_ampere: 8.,
+ },
+ ),
+ // Left main tank pump 2
+ (
+ 5,
+ FuelPumpProperties {
+ powered_by: ElectricalBusType::Virtual("FUEL_PUMP_2_SUPPLY"),
+ consumption_current_ampere: 8.,
+ },
+ ),
+ // Right main tank pump 1
+ (
+ 3,
+ FuelPumpProperties {
+ // TODO: implement Gen 1 line
+ // ElectricalBusType::AlternatingCurrent(1) or Gen1
+ powered_by: ElectricalBusType::Virtual("FUEL_PUMP_1_SUPPLY"),
+ consumption_current_ampere: 8.,
+ },
+ ),
+ // Right main tank pump 2
+ (
+ 6,
+ FuelPumpProperties {
+ powered_by: ElectricalBusType::Virtual("FUEL_PUMP_2_SUPPLY"),
+ consumption_current_ampere: 8.,
+ },
+ ),
+ // APU fuel pump
+ (
+ 7,
+ FuelPumpProperties {
+ powered_by: ElectricalBusType::Virtual("FUEL_PUMP_APU_SUPPLY"),
+ consumption_current_ampere: 1.,
+ },
+ ),
+ ];
+
pub fn new(context: &mut InitContext) -> Self {
- let fuel_tanks = Self::A320_FUEL.map(|f| {
- FuelTank::new(
- context,
- f.fuel_tank_id,
- Vector3::new(f.position.0, f.position.1, f.position.2),
- false,
- )
- });
+ let fuel_tanks = Self::A320_FUEL.map(|f| f.into_fuel_tank(context, false));
+ let fuel_pumps =
+ Self::FUEL_PUMPS.map(|(id, properties)| FuelPump::new(context, id, properties));
A320Fuel {
- fuel_system: FuelSystem::new(context, fuel_tanks),
+ fuel_system: FuelSystem::new(context, fuel_tanks, fuel_pumps),
}
}
diff --git a/fbw-a32nx/src/wasm/systems/a320_systems_wasm/src/lib.rs b/fbw-a32nx/src/wasm/systems/a320_systems_wasm/src/lib.rs
index 6dc95e07487..47366c534f2 100644
--- a/fbw-a32nx/src/wasm/systems/a320_systems_wasm/src/lib.rs
+++ b/fbw-a32nx/src/wasm/systems/a320_systems_wasm/src/lib.rs
@@ -317,6 +317,7 @@ async fn systems(mut gauge: msfs::Gauge) -> Result<(), Box> {
.provides_aircraft_variable("FUEL TANK RIGHT AUX QUANTITY", "gallons", 0)?
.provides_aircraft_variable("FUEL TOTAL QUANTITY WEIGHT", "Pounds", 0)?
.provides_aircraft_variable("FUELSYSTEM LINE FUEL FLOW", "gallons per hour", 18)?
+ .provides_aircraft_variable_range("FUELSYSTEM PUMP ACTIVE", "Bool", 1..=7)?
.provides_aircraft_variable("GEAR ANIMATION POSITION", "Percent", 0)?
.provides_aircraft_variable("GEAR ANIMATION POSITION", "Percent", 1)?
.provides_aircraft_variable("GEAR ANIMATION POSITION", "Percent", 2)?
diff --git a/fbw-a380x/src/wasm/systems/a380_systems/src/fuel/fuel_quantity_management_system.rs b/fbw-a380x/src/wasm/systems/a380_systems/src/fuel/fuel_quantity_management_system.rs
index 2f7aac8a482..5f46b3f0f95 100644
--- a/fbw-a380x/src/wasm/systems/a380_systems/src/fuel/fuel_quantity_management_system.rs
+++ b/fbw-a380x/src/wasm/systems/a380_systems/src/fuel/fuel_quantity_management_system.rs
@@ -1,10 +1,9 @@
use std::{collections::HashMap, time::Duration};
use crate::systems::simulation::SimulationElement;
-use nalgebra::Vector3;
use serde::Deserialize;
use systems::{
- fuel::{self, FuelInfo, FuelSystem, FuelTank, RefuelRate},
+ fuel::{self, FuelInfo, FuelPump, FuelPumpProperties, FuelSystem, RefuelRate},
pneumatic::EngineState,
shared::{ElectricalBusType, ElectricalBuses},
simulation::{
@@ -245,7 +244,7 @@ impl RefuelApplication {
pub fn update(
&mut self,
context: &UpdateContext,
- fuel_system: &mut FuelSystem<11>,
+ fuel_system: &mut FuelSystem<11, 20>,
refuel_panel_input: &mut IntegratedRefuelPanel,
) {
// Automatic Refueling
@@ -474,7 +473,7 @@ impl RefuelDriver {
&mut self,
delta_time: Duration,
is_fast: bool,
- fuel_system: &mut FuelSystem<11>,
+ fuel_system: &mut FuelSystem<11, 20>,
refuel_panel_input: &mut IntegratedRefuelPanel,
desired_quantities: HashMap,
) {
@@ -542,7 +541,7 @@ impl RefuelDriver {
max_delta: Mass,
channel: [A380FuelTankType; 11],
desired_quantities: &HashMap,
- fuel_system: &mut FuelSystem<11>,
+ fuel_system: &mut FuelSystem<11, 20>,
) -> bool {
if max_delta <= Mass::default() {
return true;
@@ -575,7 +574,7 @@ impl RefuelDriver {
fn execute_instant_refuel(
&mut self,
- fuel_system: &mut FuelSystem<11>,
+ fuel_system: &mut FuelSystem<11, 20>,
refuel_panel_input: &mut IntegratedRefuelPanel,
desired_quantities: HashMap,
) {
@@ -598,21 +597,20 @@ impl RefuelDriver {
impl SimulationElement for RefuelDriver {}
pub struct A380FuelQuantityManagementSystem {
- fuel_system: FuelSystem<11>,
+ fuel_system: FuelSystem<11, 20>,
refuel_application: RefuelApplication,
integrated_refuel_panel: IntegratedRefuelPanel,
}
impl A380FuelQuantityManagementSystem {
- pub fn new(context: &mut InitContext, fuel_tanks_info: [FuelInfo; 11]) -> Self {
- let fuel_tanks = fuel_tanks_info.map(|f| {
- FuelTank::new(
- context,
- f.fuel_tank_id,
- Vector3::new(f.position.0, f.position.1, f.position.2),
- true,
- )
- });
- let fuel_system = FuelSystem::new(context, fuel_tanks);
+ pub fn new(
+ context: &mut InitContext,
+ fuel_tanks_info: [FuelInfo; 11],
+ fuel_pumps_info: [(usize, FuelPumpProperties); 20],
+ ) -> Self {
+ let fuel_tanks = fuel_tanks_info.map(|f| f.into_fuel_tank(context, true));
+ let fuel_pumps =
+ fuel_pumps_info.map(|(id, properties)| FuelPump::new(context, id, properties));
+ let fuel_system = FuelSystem::new(context, fuel_tanks, fuel_pumps);
Self {
// TODO: This needs to be refactored when CPIOM implementation is done
@@ -643,7 +641,7 @@ impl A380FuelQuantityManagementSystem {
&mut self.refuel_application
}
- pub fn fuel_system(&self) -> &FuelSystem<11> {
+ pub fn fuel_system(&self) -> &FuelSystem<11, 20> {
&self.fuel_system
}
}
diff --git a/fbw-a380x/src/wasm/systems/a380_systems/src/fuel/mod.rs b/fbw-a380x/src/wasm/systems/a380_systems/src/fuel/mod.rs
index 69ee4ad51b2..c05910babdf 100644
--- a/fbw-a380x/src/wasm/systems/a380_systems/src/fuel/mod.rs
+++ b/fbw-a380x/src/wasm/systems/a380_systems/src/fuel/mod.rs
@@ -4,7 +4,8 @@ mod fuel_quantity_management_system;
use fuel_quantity_management_system::A380FuelQuantityManagementSystem;
use nalgebra::Vector3;
use systems::{
- fuel::{FuelCG, FuelInfo, FuelPayload, FuelSystem},
+ fuel::{FuelCG, FuelInfo, FuelPayload, FuelPumpProperties, FuelSystem},
+ shared::ElectricalBusType,
simulation::{InitContext, SimulationElement, SimulationElementVisitor, UpdateContext},
};
use uom::si::f64::*;
@@ -135,11 +136,175 @@ impl A380Fuel {
},
];
+ const FUEL_PUMPS: [(usize, FuelPumpProperties); 20] = [
+ (
+ // Feed 1 main pump
+ 1,
+ FuelPumpProperties {
+ powered_by: ElectricalBusType::AlternatingCurrent(4),
+ consumption_current_ampere: 9.,
+ },
+ ),
+ (
+ // Feed 1 stby pump
+ 2,
+ FuelPumpProperties {
+ powered_by: ElectricalBusType::AlternatingCurrent(2),
+ consumption_current_ampere: 9.,
+ },
+ ),
+ (
+ // Feed 2 main pump
+ 3,
+ FuelPumpProperties {
+ powered_by: ElectricalBusType::AlternatingCurrentEssential, // TODO: + DC ESS
+ consumption_current_ampere: 9.,
+ },
+ ),
+ (
+ // Feed 2 stby pump
+ 4,
+ FuelPumpProperties {
+ powered_by: ElectricalBusType::AlternatingCurrent(3),
+ consumption_current_ampere: 9.,
+ },
+ ),
+ (
+ // Feed 3 main pump
+ 5,
+ FuelPumpProperties {
+ powered_by: ElectricalBusType::AlternatingCurrent(3),
+ consumption_current_ampere: 9.,
+ },
+ ),
+ (
+ // Feed 3 stby pump
+ 6,
+ FuelPumpProperties {
+ powered_by: ElectricalBusType::AlternatingCurrentEssential, // TODO: + DC ESS
+ consumption_current_ampere: 9.,
+ },
+ ),
+ (
+ // Feed 4 main pump
+ 7,
+ FuelPumpProperties {
+ powered_by: ElectricalBusType::AlternatingCurrent(2),
+ consumption_current_ampere: 9.,
+ },
+ ),
+ (
+ // Feed 4 stby pump
+ 8,
+ FuelPumpProperties {
+ powered_by: ElectricalBusType::AlternatingCurrent(4),
+ consumption_current_ampere: 9.,
+ },
+ ),
+ (
+ // Left outer pump
+ 9,
+ FuelPumpProperties {
+ powered_by: ElectricalBusType::AlternatingCurrent(2), // TODO: + DC 1
+ consumption_current_ampere: 8.,
+ },
+ ),
+ (
+ // Left mid fwd pump
+ 10,
+ FuelPumpProperties {
+ powered_by: ElectricalBusType::AlternatingCurrent(3), // TODO: + DC 2
+ consumption_current_ampere: 8.,
+ },
+ ),
+ (
+ // Left mid aft pump
+ 11,
+ FuelPumpProperties {
+ powered_by: ElectricalBusType::AlternatingCurrent(1), // TODO: + DC 1
+ consumption_current_ampere: 8.,
+ },
+ ),
+ (
+ // Left inner fwd pump
+ 12,
+ FuelPumpProperties {
+ powered_by: ElectricalBusType::AlternatingCurrent(4), // TODO: + DC 2
+ consumption_current_ampere: 8.,
+ },
+ ),
+ (
+ // Left inner aft pump
+ 17,
+ FuelPumpProperties {
+ powered_by: ElectricalBusType::AlternatingCurrent(2), // TODO: + DC 1
+ consumption_current_ampere: 8.,
+ },
+ ),
+ (
+ // Right outer pump
+ 14,
+ FuelPumpProperties {
+ powered_by: ElectricalBusType::AlternatingCurrent(2), // TODO: + DC 1
+ consumption_current_ampere: 8.,
+ },
+ ),
+ (
+ // Right mid fwd pump
+ 15,
+ FuelPumpProperties {
+ powered_by: ElectricalBusType::AlternatingCurrent(3), // TODO: + DC 2
+ consumption_current_ampere: 8.,
+ },
+ ),
+ (
+ // Right mid aft pump
+ 16,
+ FuelPumpProperties {
+ powered_by: ElectricalBusType::AlternatingCurrent(1), // TODO: + DC 1
+ consumption_current_ampere: 8.,
+ },
+ ),
+ (
+ // Right inner fwd pump
+ 13,
+ FuelPumpProperties {
+ powered_by: ElectricalBusType::AlternatingCurrent(4), // TODO: + DC 2
+ consumption_current_ampere: 8.,
+ },
+ ),
+ (
+ // Right inner aft pump
+ 18,
+ FuelPumpProperties {
+ powered_by: ElectricalBusType::AlternatingCurrent(2), // TODO: + DC 1
+ consumption_current_ampere: 8.,
+ },
+ ),
+ (
+ // Trim left pump
+ 19,
+ FuelPumpProperties {
+ powered_by: ElectricalBusType::AlternatingCurrentEssential, // TODO: + DC ESS
+ consumption_current_ampere: 5.,
+ },
+ ),
+ (
+ // Trim right pump
+ 20,
+ FuelPumpProperties {
+ powered_by: ElectricalBusType::AlternatingCurrent(2), // TODO: + DC 1
+ consumption_current_ampere: 5.,
+ },
+ ),
+ ];
+
pub fn new(context: &mut InitContext) -> Self {
A380Fuel {
fuel_quantity_management_system: A380FuelQuantityManagementSystem::new(
context,
Self::A380_FUEL,
+ Self::FUEL_PUMPS,
),
}
}
@@ -148,7 +313,7 @@ impl A380Fuel {
self.fuel_quantity_management_system.update(context);
}
- fn fuel_system(&self) -> &FuelSystem<11> {
+ fn fuel_system(&self) -> &FuelSystem<11, 20> {
self.fuel_quantity_management_system.fuel_system()
}
diff --git a/fbw-a380x/src/wasm/systems/a380_systems_wasm/src/lib.rs b/fbw-a380x/src/wasm/systems/a380_systems_wasm/src/lib.rs
index e1946cd2860..47a1c5ef4b6 100644
--- a/fbw-a380x/src/wasm/systems/a380_systems_wasm/src/lib.rs
+++ b/fbw-a380x/src/wasm/systems/a380_systems_wasm/src/lib.rs
@@ -457,6 +457,7 @@ async fn systems(mut gauge: msfs::Gauge) -> Result<(), Box> {
.provides_aircraft_variable("FUELSYSTEM TANK QUANTITY", "gallons", 10)?
.provides_aircraft_variable("FUELSYSTEM TANK QUANTITY", "gallons", 11)?
.provides_aircraft_variable("FUELSYSTEM LINE FUEL FLOW", "gallons per hour", 141)?
+ .provides_aircraft_variable_range("FUELSYSTEM PUMP ACTIVE", "Bool", 1..21)?
.provides_aircraft_variable("GEAR ANIMATION POSITION", "Percent", 0)?
.provides_aircraft_variable("GEAR ANIMATION POSITION", "Percent", 1)?
.provides_aircraft_variable("GEAR ANIMATION POSITION", "Percent", 2)?
diff --git a/fbw-common/src/wasm/systems/systems/src/fuel/mod.rs b/fbw-common/src/wasm/systems/systems/src/fuel/mod.rs
index 3bd42033518..48434257a44 100644
--- a/fbw-common/src/wasm/systems/systems/src/fuel/mod.rs
+++ b/fbw-common/src/wasm/systems/systems/src/fuel/mod.rs
@@ -1,10 +1,13 @@
-use crate::simulation::{
- InitContext, Read, Reader, SimulationElement, SimulationElementVisitor, SimulatorReader,
- SimulatorWriter, VariableIdentifier, Write, Writer,
+use crate::{
+ shared::{ConsumePower, ElectricalBusType, ElectricalBuses},
+ simulation::{
+ InitContext, Read, Reader, SimulationElement, SimulationElementVisitor, SimulatorReader,
+ SimulatorWriter, UpdateContext, VariableIdentifier, Write, Writer,
+ },
};
use nalgebra::Vector3;
use num_traits::Zero;
-use uom::si::{f64::Mass, mass::kilogram};
+use uom::si::{electric_current::ampere, f64::*, mass::kilogram};
pub const FUEL_GALLONS_TO_KG: f64 = 3.039075693483925;
@@ -37,12 +40,29 @@ pub trait FuelPayload {
pub trait FuelCG {
fn center_of_gravity(&self) -> Vector3;
}
+
+#[derive(Clone, Copy, Debug)]
+pub struct FuelPumpProperties {
+ pub powered_by: ElectricalBusType,
+ pub consumption_current_ampere: f64,
+}
+
#[derive(Debug)]
pub struct FuelInfo<'a> {
pub fuel_tank_id: &'a str,
pub position: (f64, f64, f64),
pub total_capacity_gallons: f64,
}
+impl FuelInfo<'_> {
+ pub fn into_fuel_tank(self, context: &mut InitContext, write: bool) -> FuelTank {
+ FuelTank::new(
+ context,
+ self.fuel_tank_id,
+ Vector3::new(self.position.0, self.position.1, self.position.2),
+ write,
+ )
+ }
+}
#[derive(Debug)]
pub struct FuelTank {
@@ -91,12 +111,9 @@ impl SimulationElement for FuelTank {
);
}
}
- fn accept(&mut self, visitor: &mut T) {
- visitor.visit(self);
- }
}
-pub struct FuelSystem {
+pub struct FuelSystem {
unlimited_fuel_id: VariableIdentifier,
unlimited_fuel: bool,
@@ -104,15 +121,21 @@ pub struct FuelSystem {
fuel_total_weight: Mass,
fuel_tanks: [FuelTank; N],
+ fuel_pumps: [FuelPump; PUMP_COUNT],
}
-impl FuelSystem {
- pub fn new(context: &mut InitContext, fuel_tanks: [FuelTank; N]) -> Self {
+impl FuelSystem {
+ pub fn new(
+ context: &mut InitContext,
+ fuel_tanks: [FuelTank; N],
+ fuel_pumps: [FuelPump; PUMP_COUNT],
+ ) -> Self {
FuelSystem {
unlimited_fuel_id: context.get_identifier("UNLIMITED FUEL".to_owned()),
unlimited_fuel: false,
fuel_total_weight_id: context.get_identifier("FUEL TOTAL QUANTITY WEIGHT".to_owned()),
fuel_total_weight: Mass::default(),
fuel_tanks,
+ fuel_pumps,
}
}
@@ -149,9 +172,10 @@ impl FuelSystem {
self.fuel_tanks[t].quantity()
}
}
-impl SimulationElement for FuelSystem {
+impl SimulationElement for FuelSystem {
fn accept(&mut self, visitor: &mut T) {
accept_iterable!(self.fuel_tanks, visitor);
+ accept_iterable!(self.fuel_pumps, visitor);
visitor.visit(self);
}
@@ -160,3 +184,40 @@ impl SimulationElement for FuelSystem {
self.fuel_total_weight = reader.read(&self.fuel_total_weight_id);
}
}
+
+#[derive(Debug)]
+pub struct FuelPump {
+ pump_id: VariableIdentifier,
+ properties: FuelPumpProperties,
+ available_potential: ElectricPotential,
+ running: bool,
+}
+impl FuelPump {
+ pub fn new(context: &mut InitContext, id: usize, properties: FuelPumpProperties) -> Self {
+ Self {
+ pump_id: context.get_identifier(format!("FUELSYSTEM PUMP ACTIVE:{id}")),
+ properties,
+ available_potential: ElectricPotential::default(),
+ running: false,
+ }
+ }
+}
+impl SimulationElement for FuelPump {
+ fn read(&mut self, reader: &mut SimulatorReader) {
+ self.running = reader.read(&self.pump_id);
+ }
+
+ fn receive_power(&mut self, buses: &impl ElectricalBuses) {
+ self.available_potential = buses.potential_of(self.properties.powered_by).raw();
+ }
+
+ fn consume_power(&mut self, _: &UpdateContext, power: &mut T) {
+ let consumed_power = if self.running {
+ self.available_potential
+ * ElectricCurrent::new::(self.properties.consumption_current_ampere)
+ } else {
+ Power::default()
+ };
+ power.consume_from_bus(self.properties.powered_by, consumed_power);
+ }
+}
diff --git a/fbw-common/src/wasm/systems/systems/src/shared/mod.rs b/fbw-common/src/wasm/systems/systems/src/shared/mod.rs
index 2a3d108a6bf..0b338ea1b38 100644
--- a/fbw-common/src/wasm/systems/systems/src/shared/mod.rs
+++ b/fbw-common/src/wasm/systems/systems/src/shared/mod.rs
@@ -389,6 +389,11 @@ pub enum ElectricalBusType {
/// As sub buses represent such a small area, their state is not exported towards
/// the simulator.
Sub(&'static str),
+
+ /// A virtual bus is a bus which exists to help to provide a more realistic simulation
+ /// but doesn't exist in the real plane.
+ /// It's used for example to simulate that a device is powered by multiple powersources.
+ Virtual(&'static str),
}
impl Display for ElectricalBusType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
@@ -407,6 +412,7 @@ impl Display for ElectricalBusType {
ElectricalBusType::DirectCurrentGndFltService => write!(f, "DC_GND_FLT_SVC"),
ElectricalBusType::DirectCurrentNamed(name) => write!(f, "{}", name),
ElectricalBusType::Sub(name) => write!(f, "SUB_{}", name),
+ ElectricalBusType::Virtual(name) => write!(f, "VIRTUAL_{name}"),
}
}
}
diff --git a/fbw-common/src/wasm/systems/systems_wasm/src/lib.rs b/fbw-common/src/wasm/systems/systems_wasm/src/lib.rs
index 56872764bea..f421a5e4c5d 100644
--- a/fbw-common/src/wasm/systems/systems_wasm/src/lib.rs
+++ b/fbw-common/src/wasm/systems/systems_wasm/src/lib.rs
@@ -150,6 +150,25 @@ impl<'a, 'b> MsfsSimulationBuilder<'a, 'b> {
Ok(self)
}
+ pub fn provides_aircraft_variable_range(
+ mut self,
+ name: &str,
+ units: &str,
+ indexes: impl IntoIterator- ,
+ ) -> Result> {
+ if let Some(registry) = &mut self.variable_registry {
+ for index in indexes {
+ registry.register(&Variable::Aircraft(
+ name.to_owned(),
+ units.to_owned(),
+ index,
+ ));
+ }
+ }
+
+ Ok(self)
+ }
+
pub fn provides_named_variable(mut self, name: &str) -> Result> {
if let Some(registry) = &mut self.variable_registry {
registry.register(&Variable::Named(name.to_owned(), false));