From daa56cb589e3351fb3d2a6e3667694eae94636b5 Mon Sep 17 00:00:00 2001
From: Fragtality <78614902+Fragtality@users.noreply.github.com>
Date: Thu, 19 Feb 2026 01:08:36 +0100
Subject: [PATCH 1/5] fix(gsx): Changes to support new Loader Behavior,
Handlers and Service Cancellation
---
.../FlyByWire_A320_NEO/gsx_handler.py | 88 ++++++++++
.../FlyByWire_A320_NEO/model/A320_NEO.xml | 2 +-
.../legacy_pages/A320_Neo_CDU_InitPage.ts | 2 +-
.../FlyByWire_A380_842/gsx_handler.py | 88 ++++++++++
.../model/A380_EXTERIOR.xml | 2 +-
.../EFB/Dashboard/Widgets/FlightWidget.tsx | 7 +-
.../Ground/Pages/Fuel/A320_251N/A320Fuel.tsx | 4 +-
.../Ground/Pages/Fuel/A380_842/A380Fuel.tsx | 4 +-
.../Pages/Payload/NarrowBody/A320Payload.tsx | 8 +-
.../Pages/Payload/WideBody/A380Payload.tsx | 8 +-
fbw-common/src/systems/shared/src/GsxSync.ts | 157 +++++++++---------
.../publishers/Extras/GsxSimVarPublisher.ts | 6 +
.../wasm/systems/systems/src/payload/mod.rs | 19 ++-
13 files changed, 302 insertions(+), 93 deletions(-)
create mode 100644 fbw-a32nx/src/base/flybywire-aircraft-a320-neo/SimObjects/AirPlanes/FlyByWire_A320_NEO/gsx_handler.py
create mode 100644 fbw-a380x/src/base/flybywire-aircraft-a380-842/SimObjects/AirPlanes/FlyByWire_A380_842/gsx_handler.py
diff --git a/fbw-a32nx/src/base/flybywire-aircraft-a320-neo/SimObjects/AirPlanes/FlyByWire_A320_NEO/gsx_handler.py b/fbw-a32nx/src/base/flybywire-aircraft-a320-neo/SimObjects/AirPlanes/FlyByWire_A320_NEO/gsx_handler.py
new file mode 100644
index 00000000000..1245f7b2456
--- /dev/null
+++ b/fbw-a32nx/src/base/flybywire-aircraft-a320-neo/SimObjects/AirPlanes/FlyByWire_A320_NEO/gsx_handler.py
@@ -0,0 +1,88 @@
+friendlyName = "FlyByWire A32NX Handler"
+chocksTest = "(L:A32NX_PARK_BRAKE_LEVER_POS,number) (L:A32NX_GND_EQP_IS_VISIBLE,number) ||"
+brakesTest = "(L:A32NX_PARK_BRAKE_LEVER_POS,number)"
+zfw = LVariable("A32NX_AIRFRAME_ZFW")
+
+def onAircraftEngaged(self):
+ pass
+
+def onAircraftDisengaged(self):
+ pass
+
+def onBeforeVehicleSelect(self):
+ pass
+
+def onBoardingRequested(self):
+ pass
+
+def onDeboardingRequested(self):
+ pass
+
+def onDepartureRequested(self):
+ pass
+
+def onCateringRequested(self):
+ pass
+
+def onWaterServiceRequested(self):
+ pass
+
+def onWaterServiceCompleted(self):
+ pass
+
+def onLavatoryServiceRequested(self):
+ pass
+
+def onDeicingAction(self):
+ pass
+
+def onJetwayConnected(self):
+ pass
+
+def onJetwayDisconnected(self):
+ pass
+
+def onBypassPinConnected(self):
+ pass
+
+def onBypassPinDisconnected(self):
+ pass
+
+def onWaterOperateDoor(self, value=True):
+ pass
+
+def onLavatoryOperateDoor(self, value=True):
+ pass
+
+def operateChocks(self):
+ pass
+
+def operateGpu(self):
+ pass
+
+def setExtPowerAvail(self):
+ pass
+
+def setFuelLevel(self, level):
+ pass
+
+def setPlannedFuel(self):
+ pass
+
+def getCurrentZFW(self):
+ return zfw.getValue()
+
+def fuelPumpInsist(self):
+ return 1
+
+def setPayload(self):
+ pass
+
+def removePayload(self):
+ pass
+
+def customTruckRequestedMessage(self):
+ pass
+
+def customTruckInPositionMessage(self):
+ pass
diff --git a/fbw-a32nx/src/base/flybywire-aircraft-a320-neo/SimObjects/AirPlanes/FlyByWire_A320_NEO/model/A320_NEO.xml b/fbw-a32nx/src/base/flybywire-aircraft-a320-neo/SimObjects/AirPlanes/FlyByWire_A320_NEO/model/A320_NEO.xml
index 6a8911901c3..233b1a68c1f 100644
--- a/fbw-a32nx/src/base/flybywire-aircraft-a320-neo/SimObjects/AirPlanes/FlyByWire_A320_NEO/model/A320_NEO.xml
+++ b/fbw-a32nx/src/base/flybywire-aircraft-a320-neo/SimObjects/AirPlanes/FlyByWire_A320_NEO/model/A320_NEO.xml
@@ -554,7 +554,7 @@
10
(A:SURFACE RELATIVE GROUND SPEED, feet per second) 0.1 > ! (>L:A32NX_IS_STATIONARY, bool)
- (A:SIM ON GROUND, bool) (L:A32NX_ENGINE_N1:1, Number) 3.5 < and (L:A32NX_ENGINE_N1:2, Number) 3.5 < and (A:LIGHT BEACON, bool) 0 == and (L:FSDT_GSX_DEPARTURE_STATE, number) 5 != and (>L:A32NX_GND_EQP_IS_VISIBLE, bool)
+ (A:SIM ON GROUND, bool) (L:A32NX_ENGINE_N1:1, Number) 3.5 < and (L:A32NX_ENGINE_N1:2, Number) 3.5 < and (L:A32NX_ENGINE_N1:3, Number) 3.5 < and (L:A32NX_ENGINE_N1:4, Number) 3.5 < and (L:A32NX_HYD_NW_STRG_DISC_ECAM_MEMO, bool) 0 == and (A:LIGHT BEACON, bool) 0 == and (L:FSDT_GSX_DEPARTURE_STATE, number) 5 != and (>L:A32NX_GND_EQP_IS_VISIBLE, bool)
diff --git a/fbw-a32nx/src/systems/instruments/src/MCDU/legacy_pages/A320_Neo_CDU_InitPage.ts b/fbw-a32nx/src/systems/instruments/src/MCDU/legacy_pages/A320_Neo_CDU_InitPage.ts
index 6ed407cbdf5..f4650bef856 100644
--- a/fbw-a32nx/src/systems/instruments/src/MCDU/legacy_pages/A320_Neo_CDU_InitPage.ts
+++ b/fbw-a32nx/src/systems/instruments/src/MCDU/legacy_pages/A320_Neo_CDU_InitPage.ts
@@ -430,7 +430,7 @@ export class CDUInitPage {
let zfwCg = undefined;
const a32nxBoarding = SimVar.GetSimVarValue('L:A32NX_BOARDING_STARTED_BY_USR', 'bool');
const gsxBoarding = SimVar.GetSimVarValue('L:FSDT_GSX_BOARDING_STATE', 'number');
- if (a32nxBoarding || (gsxBoarding >= 4 && gsxBoarding < 6)) {
+ if (a32nxBoarding || gsxBoarding == 4 || gsxBoarding == 5) {
zfw = NXUnits.kgToUser(SimVar.GetSimVarValue('L:A32NX_AIRFRAME_ZFW_DESIRED', 'number'));
zfwCg = SimVar.GetSimVarValue('L:A32NX_AIRFRAME_ZFW_CG_PERCENT_MAC_DESIRED', 'number');
} else if (Number.isFinite(getZfw()) && Number.isFinite(getZfwcg())) {
diff --git a/fbw-a380x/src/base/flybywire-aircraft-a380-842/SimObjects/AirPlanes/FlyByWire_A380_842/gsx_handler.py b/fbw-a380x/src/base/flybywire-aircraft-a380-842/SimObjects/AirPlanes/FlyByWire_A380_842/gsx_handler.py
new file mode 100644
index 00000000000..1245f7b2456
--- /dev/null
+++ b/fbw-a380x/src/base/flybywire-aircraft-a380-842/SimObjects/AirPlanes/FlyByWire_A380_842/gsx_handler.py
@@ -0,0 +1,88 @@
+friendlyName = "FlyByWire A32NX Handler"
+chocksTest = "(L:A32NX_PARK_BRAKE_LEVER_POS,number) (L:A32NX_GND_EQP_IS_VISIBLE,number) ||"
+brakesTest = "(L:A32NX_PARK_BRAKE_LEVER_POS,number)"
+zfw = LVariable("A32NX_AIRFRAME_ZFW")
+
+def onAircraftEngaged(self):
+ pass
+
+def onAircraftDisengaged(self):
+ pass
+
+def onBeforeVehicleSelect(self):
+ pass
+
+def onBoardingRequested(self):
+ pass
+
+def onDeboardingRequested(self):
+ pass
+
+def onDepartureRequested(self):
+ pass
+
+def onCateringRequested(self):
+ pass
+
+def onWaterServiceRequested(self):
+ pass
+
+def onWaterServiceCompleted(self):
+ pass
+
+def onLavatoryServiceRequested(self):
+ pass
+
+def onDeicingAction(self):
+ pass
+
+def onJetwayConnected(self):
+ pass
+
+def onJetwayDisconnected(self):
+ pass
+
+def onBypassPinConnected(self):
+ pass
+
+def onBypassPinDisconnected(self):
+ pass
+
+def onWaterOperateDoor(self, value=True):
+ pass
+
+def onLavatoryOperateDoor(self, value=True):
+ pass
+
+def operateChocks(self):
+ pass
+
+def operateGpu(self):
+ pass
+
+def setExtPowerAvail(self):
+ pass
+
+def setFuelLevel(self, level):
+ pass
+
+def setPlannedFuel(self):
+ pass
+
+def getCurrentZFW(self):
+ return zfw.getValue()
+
+def fuelPumpInsist(self):
+ return 1
+
+def setPayload(self):
+ pass
+
+def removePayload(self):
+ pass
+
+def customTruckRequestedMessage(self):
+ pass
+
+def customTruckInPositionMessage(self):
+ pass
diff --git a/fbw-a380x/src/base/flybywire-aircraft-a380-842/SimObjects/AirPlanes/FlyByWire_A380_842/model/A380_EXTERIOR.xml b/fbw-a380x/src/base/flybywire-aircraft-a380-842/SimObjects/AirPlanes/FlyByWire_A380_842/model/A380_EXTERIOR.xml
index b19991f374b..821a3511783 100755
--- a/fbw-a380x/src/base/flybywire-aircraft-a380-842/SimObjects/AirPlanes/FlyByWire_A380_842/model/A380_EXTERIOR.xml
+++ b/fbw-a380x/src/base/flybywire-aircraft-a380-842/SimObjects/AirPlanes/FlyByWire_A380_842/model/A380_EXTERIOR.xml
@@ -689,7 +689,7 @@
10
(A:SURFACE RELATIVE GROUND SPEED, feet per second) 0.1 > ! (>L:A32NX_IS_STATIONARY, bool)
- (A:SIM ON GROUND, bool) (L:A32NX_ENGINE_N1:1, Number) 3.5 < and (L:A32NX_ENGINE_N1:2, Number) 3.5 < and (L:A32NX_HYD_NW_STRG_DISC_ECAM_MEMO, bool) 0 == and (A:LIGHT BEACON, bool) 0 == and (>L:A32NX_GND_EQP_IS_VISIBLE, bool)
+ (A:SIM ON GROUND, bool) (L:A32NX_ENGINE_N1:1, Number) 3.5 < and (L:A32NX_ENGINE_N1:2, Number) 3.5 < and (L:A32NX_HYD_NW_STRG_DISC_ECAM_MEMO, bool) 0 == and (A:LIGHT BEACON, bool) 0 == and (L:FSDT_GSX_DEPARTURE_STATE, number) 5 != and (>L:A32NX_GND_EQP_IS_VISIBLE, bool)
diff --git a/fbw-common/src/systems/instruments/src/EFB/Dashboard/Widgets/FlightWidget.tsx b/fbw-common/src/systems/instruments/src/EFB/Dashboard/Widgets/FlightWidget.tsx
index c9970d5b985..c445e771a26 100644
--- a/fbw-common/src/systems/instruments/src/EFB/Dashboard/Widgets/FlightWidget.tsx
+++ b/fbw-common/src/systems/instruments/src/EFB/Dashboard/Widgets/FlightWidget.tsx
@@ -101,7 +101,12 @@ export const FlightWidget = () => {
dispatch(setSimbriefDataPending(true));
const gsxInProgress =
- (gsxDeBoardingState >= 4 && gsxDeBoardingState < 6) || (gsxBoardingState >= 4 && gsxBoardingState < 6);
+ gsxDeBoardingState == 4 ||
+ gsxDeBoardingState == 5 ||
+ gsxDeBoardingState == 7 ||
+ gsxBoardingState == 4 ||
+ gsxBoardingState == 5 ||
+ gsxBoardingState == 7;
const generalBoardingInProgress = gsxPayloadSyncEnabled ? gsxInProgress : boardingStarted;
if (generalBoardingInProgress || refuelStartedByUser) {
diff --git a/fbw-common/src/systems/instruments/src/EFB/Ground/Pages/Fuel/A320_251N/A320Fuel.tsx b/fbw-common/src/systems/instruments/src/EFB/Ground/Pages/Fuel/A320_251N/A320Fuel.tsx
index 1dcb994d3e9..ec020ef2eeb 100644
--- a/fbw-common/src/systems/instruments/src/EFB/Ground/Pages/Fuel/A320_251N/A320Fuel.tsx
+++ b/fbw-common/src/systems/instruments/src/EFB/Ground/Pages/Fuel/A320_251N/A320Fuel.tsx
@@ -147,7 +147,9 @@ export const A320Fuel: React.FC = ({
}, [simbriefDataLoaded, simbriefPlanRamp, totalTarget, refuelStartedByUser]);
const gsxRefuelActive = () =>
- gsxRefuelState === GsxServiceStates.REQUESTED || gsxRefuelState === GsxServiceStates.ACTIVE;
+ gsxRefuelState === GsxServiceStates.REQUESTED ||
+ gsxRefuelState === GsxServiceStates.ACTIVE ||
+ gsxRefuelState === GsxServiceStates.COMPLETING;
const gsxRefuelCallable = () => gsxRefuelState === GsxServiceStates.CALLABLE;
diff --git a/fbw-common/src/systems/instruments/src/EFB/Ground/Pages/Fuel/A380_842/A380Fuel.tsx b/fbw-common/src/systems/instruments/src/EFB/Ground/Pages/Fuel/A380_842/A380Fuel.tsx
index 6a55688bae9..b92bb0d500e 100644
--- a/fbw-common/src/systems/instruments/src/EFB/Ground/Pages/Fuel/A380_842/A380Fuel.tsx
+++ b/fbw-common/src/systems/instruments/src/EFB/Ground/Pages/Fuel/A380_842/A380Fuel.tsx
@@ -192,7 +192,9 @@ export const A380Fuel: React.FC = ({
}, [simbriefDataLoaded, simbriefPlanRamp, fuelDesiredKg, refuelStartedByUser]);
const gsxRefuelActive = () =>
- gsxRefuelState === GsxServiceStates.REQUESTED || gsxRefuelState === GsxServiceStates.ACTIVE;
+ gsxRefuelState === GsxServiceStates.REQUESTED ||
+ gsxRefuelState === GsxServiceStates.ACTIVE ||
+ gsxRefuelState === GsxServiceStates.COMPLETING;
const gsxRefuelCallable = () => gsxRefuelState === GsxServiceStates.CALLABLE;
diff --git a/fbw-common/src/systems/instruments/src/EFB/Ground/Pages/Payload/NarrowBody/A320Payload.tsx b/fbw-common/src/systems/instruments/src/EFB/Ground/Pages/Payload/NarrowBody/A320Payload.tsx
index 1f4e010b8f2..3052bc91969 100644
--- a/fbw-common/src/systems/instruments/src/EFB/Ground/Pages/Payload/NarrowBody/A320Payload.tsx
+++ b/fbw-common/src/systems/instruments/src/EFB/Ground/Pages/Payload/NarrowBody/A320Payload.tsx
@@ -160,7 +160,12 @@ export const A320Payload: React.FC = ({
const [gsxBoardingState] = useSimVar('L:FSDT_GSX_BOARDING_STATE', 'Number', 227);
const [gsxDeBoardingState] = useSimVar('L:FSDT_GSX_DEBOARDING_STATE', 'Number', 229);
const gsxInProgress = () =>
- (gsxDeBoardingState >= 4 && gsxDeBoardingState < 6) || (gsxBoardingState >= 4 && gsxBoardingState < 6);
+ gsxDeBoardingState == 4 ||
+ gsxDeBoardingState == 5 ||
+ gsxDeBoardingState == 7 ||
+ gsxBoardingState == 4 ||
+ gsxBoardingState == 5 ||
+ gsxBoardingState == 7;
const gsxStates = {
AVAILABLE: 1,
NOT_AVAILABLE: 2,
@@ -168,6 +173,7 @@ export const A320Payload: React.FC = ({
REQUESTED: 4,
PERFORMING: 5,
COMPLETED: 6,
+ COMPLETING: 7,
};
const dispatch = useAppDispatch();
diff --git a/fbw-common/src/systems/instruments/src/EFB/Ground/Pages/Payload/WideBody/A380Payload.tsx b/fbw-common/src/systems/instruments/src/EFB/Ground/Pages/Payload/WideBody/A380Payload.tsx
index 73f73befda8..7d06d9973a0 100644
--- a/fbw-common/src/systems/instruments/src/EFB/Ground/Pages/Payload/WideBody/A380Payload.tsx
+++ b/fbw-common/src/systems/instruments/src/EFB/Ground/Pages/Payload/WideBody/A380Payload.tsx
@@ -304,7 +304,12 @@ export const A380Payload: React.FC = ({
const [gsxBoardingState] = useSimVar('L:FSDT_GSX_BOARDING_STATE', 'Number', 227);
const [gsxDeBoardingState] = useSimVar('L:FSDT_GSX_DEBOARDING_STATE', 'Number', 229);
const gsxInProgress = () =>
- (gsxDeBoardingState >= 4 && gsxDeBoardingState < 6) || (gsxBoardingState >= 4 && gsxBoardingState < 6);
+ gsxDeBoardingState == 4 ||
+ gsxDeBoardingState == 5 ||
+ gsxDeBoardingState == 7 ||
+ gsxBoardingState == 4 ||
+ gsxBoardingState == 5 ||
+ gsxBoardingState == 7;
const gsxStates = {
AVAILABLE: 1,
NOT_AVAILABLE: 2,
@@ -312,6 +317,7 @@ export const A380Payload: React.FC = ({
REQUESTED: 4,
PERFORMING: 5,
COMPLETED: 6,
+ COMPLETING: 7,
};
const dispatch = useAppDispatch();
diff --git a/fbw-common/src/systems/shared/src/GsxSync.ts b/fbw-common/src/systems/shared/src/GsxSync.ts
index b2aa3e3c3ac..c3a6e56c1b4 100644
--- a/fbw-common/src/systems/shared/src/GsxSync.ts
+++ b/fbw-common/src/systems/shared/src/GsxSync.ts
@@ -27,6 +27,7 @@ export enum GsxServiceStates {
REQUESTED = 4, //service has been requested
ACTIVE = 5, //service is being performed
COMPLETED = 6, //service has been completed
+ COMPLETING = 7, //service is completing (was canceled gracefully in the Menu)
}
enum RefuelRate {
@@ -65,6 +66,7 @@ abstract class GsxSync implements Instrument {
protected readonly couatlStarted = ConsumerSubject.create(null, 0);
protected readonly stateJetway = ConsumerSubject.create(null, 1);
protected readonly stateBoard = ConsumerSubject.create(null, 1);
+ protected readonly stateDeboard = ConsumerSubject.create(null, 1);
protected readonly stateDeparture = ConsumerSubject.create(null, 1);
protected readonly stateGpu = ConsumerSubject.create(null, 1);
protected isRefuelActive = false;
@@ -75,6 +77,11 @@ abstract class GsxSync implements Instrument {
protected readonly fuelHose = ConsumerSubject.create(null, 0);
protected readonly refuelStartedByUser = ConsumerSubject.create(null, false);
protected initialIngameFrame = false;
+ protected readonly cargoDoorTarget = ConsumerSubject.create(null, 0);
+ protected readonly toggleCargo1 = ConsumerSubject.create(null, 0);
+ protected readonly toggleCargo2 = ConsumerSubject.create(null, 0);
+ protected readonly attachedLoader1 = ConsumerSubject.create(null, 0);
+ protected readonly attachedLoader2 = ConsumerSubject.create(null, 0);
constructor(
protected readonly bus: EventBus,
@@ -98,10 +105,25 @@ abstract class GsxSync implements Instrument {
this.couatlStarted.sub(this.onCouatlStarted.bind(this));
this.stateJetway.setConsumer(this.sub.on('gsx_jetway_state'));
this.stateBoard.setConsumer(this.sub.on('gsx_boarding_state'));
+ this.stateDeboard.setConsumer(this.sub.on('gsx_deboarding_state'));
this.stateDeparture.setConsumer(this.sub.on('gsx_departure_state'));
this.stateGpu.setConsumer(this.sub.on('gsx_gpu_state'));
this.fuelHose.setConsumer(this.sub.on('gsx_fuelhose_connected'));
this.refuelStartedByUser.setConsumer(this.sub.on('a32nx_refuel_started_by_user'));
+ this.cargoDoorTarget.setConsumer(this.sub.on(`msfs_interactive_point_goal_${this.getCargoDoorIndex()}`));
+ this.toggleCargo1.setConsumer(this.sub.on('gsx_aircraft_cargo_1_toggle'));
+ this.toggleCargo2.setConsumer(this.sub.on('gsx_aircraft_cargo_2_toggle'));
+ this.attachedLoader1.setConsumer(this.sub.on('gsx_aircraft_loader_1_attached'));
+ this.attachedLoader2.setConsumer(this.sub.on('gsx_aircraft_loader_2_attached'));
+
+ this.stateBoard.sub(this.onBoardingCompleted.bind(this));
+ this.stateDeboard.sub(this.onBoardingCompleted.bind(this));
+ this.stateDeparture.sub(this.onPushbackActive.bind(this));
+
+ this.toggleCargo1.sub(this.onToggleCargo.bind(this));
+ this.toggleCargo2.sub(this.onToggleCargo.bind(this));
+ this.attachedLoader1.sub(this.onLoaderAttached.bind(this));
+ this.attachedLoader2.sub(this.onLoaderAttached.bind(this));
this.fuelHose.sub(this.onFuelHoseConnected.bind(this));
this.refuelStartedByUser.sub(this.onRefuelStartedByUser.bind(this));
@@ -223,6 +245,7 @@ abstract class GsxSync implements Instrument {
const jetwayState = this.stateJetway.get();
const gpuState = this.stateGpu.get();
const boardState = this.stateBoard.get();
+ const deboardState = this.stateDeboard.get();
const departureState = this.stateDeparture.get();
let action = PowerAction.NOOP;
@@ -232,10 +255,11 @@ abstract class GsxSync implements Instrument {
if (
boardState !== GsxServiceStates.REQUESTED &&
boardState !== GsxServiceStates.ACTIVE &&
+ boardState !== GsxServiceStates.COMPLETING &&
departureState >= GsxServiceStates.REQUESTED
) {
action = PowerAction.DISCONNECT;
- // pushback is active (in it wasn't catched before)
+ // pushback is active (if it wasn't catched before)
} else if (departureState === GsxServiceStates.ACTIVE) {
action = PowerAction.DISCONNECT;
// jetway and gpu both not connected
@@ -249,7 +273,9 @@ abstract class GsxSync implements Instrument {
// external is not available - check if connect is needed
} else if (
//jetway or gpu connected
- (jetwayState >= GsxServiceStates.REQUESTED || gpuState === GsxServiceStates.ACTIVE) &&
+ (jetwayState >= GsxServiceStates.REQUESTED ||
+ gpuState === GsxServiceStates.ACTIVE ||
+ deboardState === GsxServiceStates.ACTIVE) &&
departureState < GsxServiceStates.REQUESTED
) {
action = PowerAction.CONNECT;
@@ -280,6 +306,53 @@ abstract class GsxSync implements Instrument {
}
}
}
+
+ protected isCargoOpen(): boolean {
+ return this.cargoDoorTarget.get() !== DoorTarget.CLOSED;
+ }
+
+ protected abstract getCargoDoorIndex(): number;
+
+ protected setCargoDoor(goal: number, index: number): void {
+ if (index == null) {
+ index = this.getCargoDoorIndex();
+ }
+ SimVar.SetSimVarValue(`A:INTERACTIVE POINT GOAL:${index}`, SimVarValueType.PercentOver100, goal);
+ }
+
+ protected onBoardingCompleted(state: number): void {
+ //just to be safe, check again when boarding was completed
+ if (state === GsxServiceStates.COMPLETED && this.isCargoOpen()) {
+ this.setCargoDoor(DoorTarget.CLOSED, this.getCargoDoorIndex());
+ }
+ }
+
+ protected onPushbackActive(pushState: number): void {
+ //just to be safe, check doors again when pushback is active - maybe something bad happened on boarding
+ if (
+ this.isCargoOpen() &&
+ (pushState === GsxServiceStates.ACTIVE ||
+ (pushState === GsxServiceStates.REQUESTED && this.stateBoard.get() !== GsxServiceStates.ACTIVE))
+ ) {
+ this.setCargoDoor(DoorTarget.CLOSED, this.getCargoDoorIndex());
+ }
+ }
+
+ protected onToggleCargo(toggle: number) {
+ //received first toggle from gsx - only used for opening the doors
+ if (toggle !== GsxStates.FALSE && !this.isCargoOpen()) {
+ this.setCargoDoor(DoorTarget.OPEN, this.getCargoDoorIndex());
+ }
+ }
+
+ protected onLoaderAttached(attached: number) {
+ if (attached === GsxStates.TRUE && !this.isCargoOpen()) {
+ this.setCargoDoor(DoorTarget.OPEN, this.getCargoDoorIndex());
+ }
+ if (attached === GsxStates.FALSE && this.isCargoOpen()) {
+ this.setCargoDoor(DoorTarget.CLOSED, this.getCargoDoorIndex());
+ }
+ }
}
export class GsxSyncA32NX extends GsxSync {
@@ -305,39 +378,17 @@ export class GsxSyncA32NX extends GsxSync {
SimVar.SetSimVarValue(`L:A32NX_OVHD_ELEC_EXT_PWR_PB_IS_ON`, SimVarValueType.Bool, state);
}
}
+
+ protected getCargoDoorIndex(): number {
+ return 5;
+ }
}
export class GsxSyncA380X extends GsxSync {
- protected readonly toggleCargo1 = ConsumerSubject.create(null, 0);
- protected readonly toggleCargo2 = ConsumerSubject.create(null, 0);
- protected readonly stateDeboard = ConsumerSubject.create(null, 1);
- protected readonly cargoPercentBoard = ConsumerSubject.create(null, 0);
- protected readonly cargoPercentDeboard = ConsumerSubject.create(null, 0);
- protected readonly cargoTimer = new DebounceTimer();
- protected readonly cargoDoorTarget = ConsumerSubject.create(null, 0);
-
constructor(bus: EventBus) {
super(bus, 4, DEFUEL_DIFF_TARGET_A380);
}
- protected initSubscriptions(): void {
- super.initSubscriptions();
- this.toggleCargo1.setConsumer(this.sub.on('gsx_aircraft_cargo_1_toggle'));
- this.toggleCargo2.setConsumer(this.sub.on('gsx_aircraft_cargo_2_toggle'));
- this.stateDeboard.setConsumer(this.sub.on('gsx_deboarding_state'));
- this.cargoPercentBoard.setConsumer(this.sub.on('gsx_boarding_cargo_percent'));
- this.cargoPercentDeboard.setConsumer(this.sub.on('gsx_deboarding_cargo_percent'));
- this.cargoDoorTarget.setConsumer(this.sub.on('msfs_interactive_point_goal_16'));
-
- this.toggleCargo1.sub(this.onToggleCargo.bind(this));
- this.toggleCargo2.sub(this.onToggleCargo.bind(this));
- this.stateBoard.sub(this.onBoardingCompleted.bind(this));
- this.stateDeboard.sub(this.onBoardingCompleted.bind(this));
- this.cargoPercentBoard.sub(this.onCargoBoardCompleted.bind(this));
- this.cargoPercentDeboard.sub(this.onCargoDeboardCompleted.bind(this));
- this.stateDeparture.sub(this.onPushbackActive.bind(this));
- }
-
protected getFob(): number {
return SimVar.GetSimVarValueFast('L:A32NX_TOTAL_FUEL_QUANTITY', SimVarValueType.Number);
}
@@ -354,53 +405,7 @@ export class GsxSyncA380X extends GsxSync {
SimVar.SetSimVarValue(`L:A32NX_OVHD_ELEC_EXT_PWR_${index}_PB_IS_ON`, SimVarValueType.Bool, state);
}
- protected isCargoOpen(): boolean {
- return this.cargoDoorTarget.get() !== DoorTarget.CLOSED;
- }
-
- protected setCargoDoor(goal: number, index: number = 16): void {
- SimVar.SetSimVarValue(`A:INTERACTIVE POINT GOAL:${index}`, SimVarValueType.PercentOver100, goal);
- }
-
- protected onToggleCargo(toggle: number) {
- //received first toggle from gsx - only used for opening the doors
- if (toggle !== GsxStates.FALSE && !this.isCargoOpen()) {
- this.setCargoDoor(DoorTarget.OPEN);
- }
- }
-
- protected onCargoBoardCompleted(percent: number): void {
- this.startCargoTimer(percent, DELAY_CARGO_CLOSE);
- }
-
- protected onCargoDeboardCompleted(percent: number): void {
- this.startCargoTimer(percent, DELAY_CARGO_CLOSE);
- }
-
- protected startCargoTimer(percent: number, delay: number): void {
- //close doors with a certain delay, after (un)loading was completed (==100%)
- if (percent === 100 && !this.cargoTimer.isPending() && this.isCargoOpen()) {
- this.fuelTimer.schedule(() => {
- this.setCargoDoor(DoorTarget.CLOSED);
- }, delay);
- }
- }
-
- protected onBoardingCompleted(state: number): void {
- //just to be safe, check again when boarding was completed
- if (state === GsxServiceStates.COMPLETED && this.isCargoOpen()) {
- this.setCargoDoor(DoorTarget.CLOSED);
- }
- }
-
- protected onPushbackActive(pushState: number): void {
- //just to be safe, check again when pushback is active - maybe something bad happened on boarding
- if (
- this.isCargoOpen() &&
- (pushState === GsxServiceStates.ACTIVE ||
- (pushState === GsxServiceStates.REQUESTED && this.stateBoard.get() !== GsxServiceStates.ACTIVE))
- ) {
- this.setCargoDoor(DoorTarget.CLOSED);
- }
+ protected getCargoDoorIndex(): number {
+ return 16;
}
}
diff --git a/fbw-common/src/systems/shared/src/publishers/Extras/GsxSimVarPublisher.ts b/fbw-common/src/systems/shared/src/publishers/Extras/GsxSimVarPublisher.ts
index ec3fb141fa1..39a81cba5d6 100644
--- a/fbw-common/src/systems/shared/src/publishers/Extras/GsxSimVarPublisher.ts
+++ b/fbw-common/src/systems/shared/src/publishers/Extras/GsxSimVarPublisher.ts
@@ -8,6 +8,10 @@ export interface GsxSimVarEvents {
gsx_aircraft_cargo_1_toggle: number;
/** AFT Cargo Door Toggle - true => non-zero*/
gsx_aircraft_cargo_2_toggle: number;
+ /** FWD Cargo Loader attached - true => non-zero*/
+ gsx_aircraft_loader_1_attached: number;
+ /** AFT Cargo Loader attached - true => non-zero*/
+ gsx_aircraft_loader_2_attached: number;
/** GSX Fuelhose Connected - true => non-zero*/
gsx_fuelhose_connected: number;
/** GSX Refuel Service - 4 => requested, 5 => active */
@@ -36,6 +40,8 @@ export class GsxSimVarPublisher extends SimVarPublisher {
private static readonly simVars = new Map([
['gsx_aircraft_cargo_1_toggle', { name: 'L:FSDT_GSX_AIRCRAFT_CARGO_1_TOGGLE', type: SimVarValueType.Number }],
['gsx_aircraft_cargo_2_toggle', { name: 'L:FSDT_GSX_AIRCRAFT_CARGO_2_TOGGLE', type: SimVarValueType.Number }],
+ ['gsx_aircraft_loader_1_attached', { name: 'L:FSDT_GSX_LOADER_EXIT_0', type: SimVarValueType.Number }],
+ ['gsx_aircraft_loader_2_attached', { name: 'L:FSDT_GSX_LOADER_EXIT_1', type: SimVarValueType.Number }],
['gsx_jetway_state', { name: 'L:FSDT_GSX_JETWAY', type: SimVarValueType.Number }],
['gsx_boarding_state', { name: 'L:FSDT_GSX_BOARDING_STATE', type: SimVarValueType.Number }],
['gsx_deboarding_state', { name: 'L:FSDT_GSX_DEBOARDING_STATE', type: SimVarValueType.Number }],
diff --git a/fbw-common/src/wasm/systems/systems/src/payload/mod.rs b/fbw-common/src/wasm/systems/systems/src/payload/mod.rs
index d1194ab035d..8a621a30918 100644
--- a/fbw-common/src/wasm/systems/systems/src/payload/mod.rs
+++ b/fbw-common/src/wasm/systems/systems/src/payload/mod.rs
@@ -1087,6 +1087,7 @@ pub enum GsxState {
Requested,
Performing,
Completed,
+ Completing,
}
impl From for GsxState {
fn from(value: f64) -> Self {
@@ -1098,6 +1099,7 @@ impl From for GsxState {
4 => GsxState::Requested,
5 => GsxState::Performing,
6 => GsxState::Completed,
+ 7 => GsxState::Completing,
i => panic!("Cannot convert from {} to GsxState.", i),
}
}
@@ -1248,7 +1250,10 @@ impl GsxDriver {
boarding_sounds.play_sound_pax_boarding(self.boarding_state() == GsxState::Performing);
boarding_sounds.play_sound_pax_deboarding(self.deboarding_state() == GsxState::Performing);
boarding_sounds.play_sound_pax_ambience(self.has_pax(passenger_deck));
- boarding_sounds.play_sound_pax_complete(self.boarding_state() == GsxState::Completed)
+ boarding_sounds.play_sound_pax_complete(
+ self.boarding_state() == GsxState::Completed
+ || self.boarding_state() == GsxState::Completing,
+ )
}
fn update_boarding(
@@ -1257,14 +1262,10 @@ impl GsxDriver {
cargo_deck: &mut CargoDeck,
) {
match self.boarding_state() {
- GsxState::None
- | GsxState::Available
- | GsxState::NotAvailable
- | GsxState::Bypassed
- | GsxState::Requested => {
+ GsxState::None | GsxState::NotAvailable | GsxState::Bypassed | GsxState::Requested => {
self.performing_board = false;
}
- GsxState::Completed => {
+ GsxState::Available | GsxState::Completed | GsxState::Completing => {
if self.performing_board {
passenger_deck.spawn_all_pax();
cargo_deck.spawn_all_cargo();
@@ -1285,7 +1286,7 @@ impl GsxDriver {
cargo_deck: &mut CargoDeck,
) {
match self.deboarding_state() {
- GsxState::None | GsxState::Available | GsxState::NotAvailable | GsxState::Bypassed => {
+ GsxState::None | GsxState::NotAvailable | GsxState::Bypassed => {
self.deboarding_total = 0;
self.performing_deboard = false;
}
@@ -1296,7 +1297,7 @@ impl GsxDriver {
self.deboarding_total = passenger_deck.total_pax_num();
self.performing_deboard = false;
}
- GsxState::Completed => {
+ GsxState::Available | GsxState::Completed | GsxState::Completing => {
if self.performing_deboard {
passenger_deck.spawn_all_pax();
cargo_deck.spawn_all_cargo();
From 0a7b52d6f57c3e7e635dc29b8d80287aa39534cb Mon Sep 17 00:00:00 2001
From: Fragtality <78614902+Fragtality@users.noreply.github.com>
Date: Thu, 19 Feb 2026 01:11:44 +0100
Subject: [PATCH 2/5] Fixed Changelog
---
.github/CHANGELOG.md | 1 +
1 file changed, 1 insertion(+)
diff --git a/.github/CHANGELOG.md b/.github/CHANGELOG.md
index 9a3c9157587..c7bb1596b64 100644
--- a/.github/CHANGELOG.md
+++ b/.github/CHANGELOG.md
@@ -78,6 +78,7 @@
1. [FMS] Fixed incorrect course for enroute holds and direct tos - @tracernz (Mike)
1. [FMS] Show true bearings correctly in various FMS pages on the MCDU/MFD - @tracernz (Mike)
1. [A380X/FWS] Improve various ABN SENSED procedure accuracy - @Jonny23787 (Jonathan)
+1. [GSX] Changes to support new Loader Behavior, Handlers and Service Cancellation for A380X/A32NX - @Fragtality (Fragtality)
## 0.14.0
From 7a87a420840e059c15ca02b53c9462a3d7ebaa29 Mon Sep 17 00:00:00 2001
From: Fragtality <78614902+Fragtality@users.noreply.github.com>
Date: Thu, 19 Feb 2026 01:28:08 +0100
Subject: [PATCH 3/5] Fixed XML Chock Condition
---
.../SimObjects/AirPlanes/FlyByWire_A320_NEO/model/A320_NEO.xml | 2 +-
.../AirPlanes/FlyByWire_A380_842/model/A380_EXTERIOR.xml | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/fbw-a32nx/src/base/flybywire-aircraft-a320-neo/SimObjects/AirPlanes/FlyByWire_A320_NEO/model/A320_NEO.xml b/fbw-a32nx/src/base/flybywire-aircraft-a320-neo/SimObjects/AirPlanes/FlyByWire_A320_NEO/model/A320_NEO.xml
index 233b1a68c1f..103876be945 100644
--- a/fbw-a32nx/src/base/flybywire-aircraft-a320-neo/SimObjects/AirPlanes/FlyByWire_A320_NEO/model/A320_NEO.xml
+++ b/fbw-a32nx/src/base/flybywire-aircraft-a320-neo/SimObjects/AirPlanes/FlyByWire_A320_NEO/model/A320_NEO.xml
@@ -554,7 +554,7 @@
10
(A:SURFACE RELATIVE GROUND SPEED, feet per second) 0.1 > ! (>L:A32NX_IS_STATIONARY, bool)
- (A:SIM ON GROUND, bool) (L:A32NX_ENGINE_N1:1, Number) 3.5 < and (L:A32NX_ENGINE_N1:2, Number) 3.5 < and (L:A32NX_ENGINE_N1:3, Number) 3.5 < and (L:A32NX_ENGINE_N1:4, Number) 3.5 < and (L:A32NX_HYD_NW_STRG_DISC_ECAM_MEMO, bool) 0 == and (A:LIGHT BEACON, bool) 0 == and (L:FSDT_GSX_DEPARTURE_STATE, number) 5 != and (>L:A32NX_GND_EQP_IS_VISIBLE, bool)
+ (A:SIM ON GROUND, bool) (L:A32NX_ENGINE_N1:1, Number) 3.5 < and (L:A32NX_ENGINE_N1:2, Number) 3.5 < and (L:A32NX_HYD_NW_STRG_DISC_ECAM_MEMO, bool) 0 == and (A:LIGHT BEACON, bool) 0 == and (L:FSDT_GSX_DEPARTURE_STATE, number) 5 != and (>L:A32NX_GND_EQP_IS_VISIBLE, bool)
diff --git a/fbw-a380x/src/base/flybywire-aircraft-a380-842/SimObjects/AirPlanes/FlyByWire_A380_842/model/A380_EXTERIOR.xml b/fbw-a380x/src/base/flybywire-aircraft-a380-842/SimObjects/AirPlanes/FlyByWire_A380_842/model/A380_EXTERIOR.xml
index 821a3511783..d6bbda5886f 100755
--- a/fbw-a380x/src/base/flybywire-aircraft-a380-842/SimObjects/AirPlanes/FlyByWire_A380_842/model/A380_EXTERIOR.xml
+++ b/fbw-a380x/src/base/flybywire-aircraft-a380-842/SimObjects/AirPlanes/FlyByWire_A380_842/model/A380_EXTERIOR.xml
@@ -689,7 +689,7 @@
10
(A:SURFACE RELATIVE GROUND SPEED, feet per second) 0.1 > ! (>L:A32NX_IS_STATIONARY, bool)
- (A:SIM ON GROUND, bool) (L:A32NX_ENGINE_N1:1, Number) 3.5 < and (L:A32NX_ENGINE_N1:2, Number) 3.5 < and (L:A32NX_HYD_NW_STRG_DISC_ECAM_MEMO, bool) 0 == and (A:LIGHT BEACON, bool) 0 == and (L:FSDT_GSX_DEPARTURE_STATE, number) 5 != and (>L:A32NX_GND_EQP_IS_VISIBLE, bool)
+ (A:SIM ON GROUND, bool) (L:A32NX_ENGINE_N1:1, Number) 3.5 < and (L:A32NX_ENGINE_N1:2, Number) 3.5 < and (L:A32NX_ENGINE_N1:3, Number) 3.5 < and (L:A32NX_ENGINE_N1:4, Number) 3.5 < and (L:A32NX_HYD_NW_STRG_DISC_ECAM_MEMO, bool) 0 == and (A:LIGHT BEACON, bool) 0 == and (L:FSDT_GSX_DEPARTURE_STATE, number) 5 != and (>L:A32NX_GND_EQP_IS_VISIBLE, bool)
From d3cefc68d5546467e57a3a975bd0fbf2da7eea36 Mon Sep 17 00:00:00 2001
From: Fragtality <78614902+Fragtality@users.noreply.github.com>
Date: Thu, 19 Feb 2026 16:01:59 +0100
Subject: [PATCH 4/5] Changed GSX Power Sync to use connected State instead of
Service State
---
fbw-common/src/systems/shared/src/GsxSync.ts | 8 ++++----
.../shared/src/publishers/Extras/GsxSimVarPublisher.ts | 3 +++
2 files changed, 7 insertions(+), 4 deletions(-)
diff --git a/fbw-common/src/systems/shared/src/GsxSync.ts b/fbw-common/src/systems/shared/src/GsxSync.ts
index c3a6e56c1b4..348b0883d79 100644
--- a/fbw-common/src/systems/shared/src/GsxSync.ts
+++ b/fbw-common/src/systems/shared/src/GsxSync.ts
@@ -68,7 +68,7 @@ abstract class GsxSync implements Instrument {
protected readonly stateBoard = ConsumerSubject.create(null, 1);
protected readonly stateDeboard = ConsumerSubject.create(null, 1);
protected readonly stateDeparture = ConsumerSubject.create(null, 1);
- protected readonly stateGpu = ConsumerSubject.create(null, 1);
+ protected readonly stateGpu = ConsumerSubject.create(null, 0);
protected isRefuelActive = false;
protected isDefuel = false;
protected readonly fuelTimer = new DebounceTimer();
@@ -107,7 +107,7 @@ abstract class GsxSync implements Instrument {
this.stateBoard.setConsumer(this.sub.on('gsx_boarding_state'));
this.stateDeboard.setConsumer(this.sub.on('gsx_deboarding_state'));
this.stateDeparture.setConsumer(this.sub.on('gsx_departure_state'));
- this.stateGpu.setConsumer(this.sub.on('gsx_gpu_state'));
+ this.stateGpu.setConsumer(this.sub.on('gsx_gpu_connected'));
this.fuelHose.setConsumer(this.sub.on('gsx_fuelhose_connected'));
this.refuelStartedByUser.setConsumer(this.sub.on('a32nx_refuel_started_by_user'));
this.cargoDoorTarget.setConsumer(this.sub.on(`msfs_interactive_point_goal_${this.getCargoDoorIndex()}`));
@@ -266,7 +266,7 @@ abstract class GsxSync implements Instrument {
} else if (
jetwayState >= GsxServiceStates.CALLABLE &&
jetwayState <= GsxServiceStates.BYPASSED &&
- gpuState !== GsxServiceStates.ACTIVE
+ gpuState !== GsxStates.CONNECTED
) {
action = PowerAction.DISCONNECT;
}
@@ -274,7 +274,7 @@ abstract class GsxSync implements Instrument {
} else if (
//jetway or gpu connected
(jetwayState >= GsxServiceStates.REQUESTED ||
- gpuState === GsxServiceStates.ACTIVE ||
+ gpuState === GsxStates.CONNECTED ||
deboardState === GsxServiceStates.ACTIVE) &&
departureState < GsxServiceStates.REQUESTED
) {
diff --git a/fbw-common/src/systems/shared/src/publishers/Extras/GsxSimVarPublisher.ts b/fbw-common/src/systems/shared/src/publishers/Extras/GsxSimVarPublisher.ts
index 39a81cba5d6..30b755a440f 100644
--- a/fbw-common/src/systems/shared/src/publishers/Extras/GsxSimVarPublisher.ts
+++ b/fbw-common/src/systems/shared/src/publishers/Extras/GsxSimVarPublisher.ts
@@ -26,6 +26,8 @@ export interface GsxSimVarEvents {
gsx_departure_state: number;
/** GSX GPU Service - 4 => requested, 5 => active */
gsx_gpu_state: number;
+ /** GSX GPU Connected - true => non-zero*/
+ gsx_gpu_connected: number;
/** GSX Boarding Cargo loaded 0-100% */
gsx_boarding_cargo_percent: number;
/** GSX Deboarding Cargo loaded 0-100% */
@@ -47,6 +49,7 @@ export class GsxSimVarPublisher extends SimVarPublisher {
['gsx_deboarding_state', { name: 'L:FSDT_GSX_DEBOARDING_STATE', type: SimVarValueType.Number }],
['gsx_departure_state', { name: 'L:FSDT_GSX_DEPARTURE_STATE', type: SimVarValueType.Number }],
['gsx_gpu_state', { name: 'L:FSDT_GSX_GPU_STATE', type: SimVarValueType.Number }],
+ ['gsx_gpu_connected', { name: 'L:FSDT_GSX_GPU_CONNECTED', type: SimVarValueType.Number }],
['gsx_boarding_cargo_percent', { name: 'L:FSDT_GSX_BOARDING_CARGO_PERCENT', type: SimVarValueType.Number }],
['gsx_deboarding_cargo_percent', { name: 'L:FSDT_GSX_DEBOARDING_CARGO_PERCENT', type: SimVarValueType.Number }],
['gsx_refuel_state', { name: 'L:FSDT_GSX_REFUELING_STATE', type: SimVarValueType.Number }],
From 00825bb4d7b281a1eeeb95c037060a8952648f31 Mon Sep 17 00:00:00 2001
From: Fragtality <78614902+Fragtality@users.noreply.github.com>
Date: Sun, 22 Feb 2026 20:09:42 +0100
Subject: [PATCH 5/5] Reduced overrides in GSX Handler (ofc there are caveats)
/ Reworked GSX Power Sync / Changes to MSFS Power Sync
---
.github/CHANGELOG.md | 3 +-
.../FlyByWire_A320_NEO/gsx_handler.py | 88 ++------
.../FlyByWire_A380_842/gsx_handler.py | 90 ++------
.../instruments/src/EFB/Settings/sync.ts | 12 ++
.../src/systems/shared/src/GPUManagement.ts | 26 ++-
fbw-common/src/systems/shared/src/GsxSync.ts | 202 +++++++++++-------
6 files changed, 191 insertions(+), 230 deletions(-)
diff --git a/.github/CHANGELOG.md b/.github/CHANGELOG.md
index c7bb1596b64..a17e338b604 100644
--- a/.github/CHANGELOG.md
+++ b/.github/CHANGELOG.md
@@ -78,7 +78,8 @@
1. [FMS] Fixed incorrect course for enroute holds and direct tos - @tracernz (Mike)
1. [FMS] Show true bearings correctly in various FMS pages on the MCDU/MFD - @tracernz (Mike)
1. [A380X/FWS] Improve various ABN SENSED procedure accuracy - @Jonny23787 (Jonathan)
-1. [GSX] Changes to support new Loader Behavior, Handlers and Service Cancellation for A380X/A32NX - @Fragtality (Fragtality)
+1. [GSX] Changes to support new Features: Loader Behavior, Python Handlers and Service Cancellation - @Fragtality (Fragtality)
+1. [GSX] Reworked Ground Power Synch with Jetway/GSX GPU - @Fragtality (Fragtality)
## 0.14.0
diff --git a/fbw-a32nx/src/base/flybywire-aircraft-a320-neo/SimObjects/AirPlanes/FlyByWire_A320_NEO/gsx_handler.py b/fbw-a32nx/src/base/flybywire-aircraft-a320-neo/SimObjects/AirPlanes/FlyByWire_A320_NEO/gsx_handler.py
index 1245f7b2456..7c3d750a0e9 100644
--- a/fbw-a32nx/src/base/flybywire-aircraft-a320-neo/SimObjects/AirPlanes/FlyByWire_A320_NEO/gsx_handler.py
+++ b/fbw-a32nx/src/base/flybywire-aircraft-a320-neo/SimObjects/AirPlanes/FlyByWire_A320_NEO/gsx_handler.py
@@ -1,40 +1,8 @@
friendlyName = "FlyByWire A32NX Handler"
+# Ensuring that Chocks and Brakes Tests are not overriden by an User-Profile
chocksTest = "(L:A32NX_PARK_BRAKE_LEVER_POS,number) (L:A32NX_GND_EQP_IS_VISIBLE,number) ||"
brakesTest = "(L:A32NX_PARK_BRAKE_LEVER_POS,number)"
-zfw = LVariable("A32NX_AIRFRAME_ZFW")
-
-def onAircraftEngaged(self):
- pass
-
-def onAircraftDisengaged(self):
- pass
-
-def onBeforeVehicleSelect(self):
- pass
-
-def onBoardingRequested(self):
- pass
-
-def onDeboardingRequested(self):
- pass
-
-def onDepartureRequested(self):
- pass
-
-def onCateringRequested(self):
- pass
-
-def onWaterServiceRequested(self):
- pass
-
-def onWaterServiceCompleted(self):
- pass
-
-def onLavatoryServiceRequested(self):
- pass
-
-def onDeicingAction(self):
- pass
+fuelSync = LVariable("A32NX_GSX_FUEL_SYNC_ENABLED")
def onJetwayConnected(self):
pass
@@ -42,47 +10,23 @@ def onJetwayConnected(self):
def onJetwayDisconnected(self):
pass
-def onBypassPinConnected(self):
- pass
-
-def onBypassPinDisconnected(self):
- pass
-
-def onWaterOperateDoor(self, value=True):
- pass
-
-def onLavatoryOperateDoor(self, value=True):
- pass
-
-def operateChocks(self):
- pass
-
-def operateGpu(self):
- pass
-
def setExtPowerAvail(self):
pass
-def setFuelLevel(self, level):
- pass
-
-def setPlannedFuel(self):
- pass
-
-def getCurrentZFW(self):
- return zfw.getValue()
-
-def fuelPumpInsist(self):
- return 1
-
-def setPayload(self):
- pass
-
-def removePayload(self):
- pass
-
def customTruckRequestedMessage(self):
- pass
+ if fuelSync.getValue() != 0:
+ return "Fuel Truck requested - load OFP/set planned Fuel in FlyPad"
+ else:
+ return self._super_customTruckRequestedMessage()
+
+def customRefuelMessage(self):
+ if fuelSync.getValue() != 0:
+ return "GSX Refuel in Progress"
+ else:
+ return self._super_customRefuelMessage()
def customTruckInPositionMessage(self):
- pass
+ if fuelSync.getValue() != 0:
+ return "Fuel Truck in Position - Refuel starts automatically"
+ else:
+ return self._super_customTruckInPositionMessage()
diff --git a/fbw-a380x/src/base/flybywire-aircraft-a380-842/SimObjects/AirPlanes/FlyByWire_A380_842/gsx_handler.py b/fbw-a380x/src/base/flybywire-aircraft-a380-842/SimObjects/AirPlanes/FlyByWire_A380_842/gsx_handler.py
index 1245f7b2456..2591fadae7e 100644
--- a/fbw-a380x/src/base/flybywire-aircraft-a380-842/SimObjects/AirPlanes/FlyByWire_A380_842/gsx_handler.py
+++ b/fbw-a380x/src/base/flybywire-aircraft-a380-842/SimObjects/AirPlanes/FlyByWire_A380_842/gsx_handler.py
@@ -1,40 +1,8 @@
-friendlyName = "FlyByWire A32NX Handler"
+friendlyName = "FlyByWire A380X Handler"
+# Ensuring that Chocks and Brakes Tests are not overriden by an User-Profile
chocksTest = "(L:A32NX_PARK_BRAKE_LEVER_POS,number) (L:A32NX_GND_EQP_IS_VISIBLE,number) ||"
brakesTest = "(L:A32NX_PARK_BRAKE_LEVER_POS,number)"
-zfw = LVariable("A32NX_AIRFRAME_ZFW")
-
-def onAircraftEngaged(self):
- pass
-
-def onAircraftDisengaged(self):
- pass
-
-def onBeforeVehicleSelect(self):
- pass
-
-def onBoardingRequested(self):
- pass
-
-def onDeboardingRequested(self):
- pass
-
-def onDepartureRequested(self):
- pass
-
-def onCateringRequested(self):
- pass
-
-def onWaterServiceRequested(self):
- pass
-
-def onWaterServiceCompleted(self):
- pass
-
-def onLavatoryServiceRequested(self):
- pass
-
-def onDeicingAction(self):
- pass
+fuelSync = LVariable("A32NX_GSX_FUEL_SYNC_ENABLED")
def onJetwayConnected(self):
pass
@@ -42,47 +10,23 @@ def onJetwayConnected(self):
def onJetwayDisconnected(self):
pass
-def onBypassPinConnected(self):
- pass
-
-def onBypassPinDisconnected(self):
- pass
-
-def onWaterOperateDoor(self, value=True):
- pass
-
-def onLavatoryOperateDoor(self, value=True):
- pass
-
-def operateChocks(self):
- pass
-
-def operateGpu(self):
- pass
-
def setExtPowerAvail(self):
pass
-def setFuelLevel(self, level):
- pass
-
-def setPlannedFuel(self):
- pass
-
-def getCurrentZFW(self):
- return zfw.getValue()
-
-def fuelPumpInsist(self):
- return 1
-
-def setPayload(self):
- pass
-
-def removePayload(self):
- pass
-
def customTruckRequestedMessage(self):
- pass
+ if fuelSync.getValue() != 0:
+ return "Fuel Truck requested - set planned Fuel in FlyPad"
+ else:
+ return self._super_customTruckRequestedMessage()
+
+def customRefuelMessage(self):
+ if fuelSync.getValue() != 0:
+ return "GSX Refuel in Progress"
+ else:
+ return self._super_customRefuelMessage()
def customTruckInPositionMessage(self):
- pass
+ if fuelSync.getValue() != 0:
+ return "Fuel Truck in Position - Refuel starts automatically"
+ else:
+ return self._super_customTruckInPositionMessage()
diff --git a/fbw-common/src/systems/instruments/src/EFB/Settings/sync.ts b/fbw-common/src/systems/instruments/src/EFB/Settings/sync.ts
index ef3f9836d6f..c5a91babe4b 100644
--- a/fbw-common/src/systems/instruments/src/EFB/Settings/sync.ts
+++ b/fbw-common/src/systems/instruments/src/EFB/Settings/sync.ts
@@ -122,12 +122,24 @@ export const globalSyncedSettings: SyncedSettingDefinition[] = [
localVarUnit: 'bool',
defaultValue: '0',
},
+ {
+ configKey: 'GSX_FUEL_SYNC',
+ localVarName: 'L:A32NX_GSX_FUEL_SYNC_ENABLED',
+ localVarUnit: 'bool',
+ defaultValue: '0',
+ },
{
configKey: 'GSX_PAYLOAD_SYNC',
localVarName: 'L:A32NX_GSX_PAYLOAD_SYNC_ENABLED',
localVarUnit: 'bool',
defaultValue: '0',
},
+ {
+ configKey: 'GSX_POWER_SYNC',
+ localVarName: 'L:A32NX_GSX_POWER_SYNC_ENABLED',
+ localVarUnit: 'bool',
+ defaultValue: '0',
+ },
{
configKey: 'CONFIG_USING_METRIC_UNIT',
localVarName: 'L:A32NX_EFB_USING_METRIC_UNIT',
diff --git a/fbw-common/src/systems/shared/src/GPUManagement.ts b/fbw-common/src/systems/shared/src/GPUManagement.ts
index b2fcbb7ae91..cc6db7edab3 100644
--- a/fbw-common/src/systems/shared/src/GPUManagement.ts
+++ b/fbw-common/src/systems/shared/src/GPUManagement.ts
@@ -36,6 +36,8 @@ export class GPUManagement implements Instrument {
private readonly ExtPowerAvailStates = new Map>();
+ private readonly msfsSyncEnabled = ConsumerSubject.create(this.sub.on('msfs_power_sync_state'), true);
+
// state 2 is cockpit, state 3 is external
private readonly isIngame = MappedSubject.create(
([gameState, cameraState]) => gameState === GameState.ingame && (cameraState === 2 || cameraState === 3),
@@ -63,11 +65,17 @@ export class GPUManagement implements Instrument {
public init(): void {
Wait.awaitSubscribable(this.isIngame, (state) => state, true).then(() => {
this.sub.on('gpu_toggle').handle(this.toggleGPU.bind(this));
- this.gpuHookedUp.sub((v) => this.setEXTpower(v));
+ this.sub.on('set_ext_power').handle(this.onExtPowerEvent.bind(this));
+ this.gpuHookedUp.sub((v) => {
+ if (this.msfsSyncEnabled.get() === true) this.setEXTpower(v);
+ });
this.groundVelocity.sub((v) => {
// disable ext power when aircraft starts moving
if (v > 0.3 && this.anyGPUAvail()) {
- this.toggleGPU();
+ this.setEXTpower(false);
+ if (this.gpuHookedUp.get()) {
+ this.toggleMSFSGpu();
+ }
}
});
this.initialIngameFrame = true;
@@ -87,14 +95,14 @@ export class GPUManagement implements Instrument {
private toggleGPU(): void {
if (!this.anyGPUAvail()) {
- if (this.anyMSFSGPUAvail()) {
+ if (this.anyMSFSGPUAvail() || this.msfsSyncEnabled.get() === false) {
// if msfs ground power is avail we are at a powered stand
this.setEXTpower(true);
} else {
this.toggleMSFSGpu(); // if msfs ground power is not avail we call for gpu cart
}
} else {
- if (this.gpuHookedUp.get()) {
+ if (this.gpuHookedUp.get() && this.msfsSyncEnabled.get() === true) {
this.toggleMSFSGpu();
} else {
this.setEXTpower(false);
@@ -102,6 +110,14 @@ export class GPUManagement implements Instrument {
}
}
+ private onExtPowerEvent(state: boolean): void {
+ if (!this.anyGPUAvail() && state) {
+ this.setEXTpower(true);
+ } else if (this.anyGPUAvail() && !state) {
+ this.setEXTpower(false);
+ }
+ }
+
private toggleMSFSGpu(): void {
SimVar.SetSimVarValue('K:REQUEST_POWER_SUPPLY', 'Bool', true);
}
@@ -140,4 +156,6 @@ export class GPUManagement implements Instrument {
export interface GPUControlEvents {
/** event to toggle the GPU*/
gpu_toggle: unknown;
+ set_ext_power: boolean;
+ msfs_power_sync_state: boolean;
}
diff --git a/fbw-common/src/systems/shared/src/GsxSync.ts b/fbw-common/src/systems/shared/src/GsxSync.ts
index 348b0883d79..370270d6554 100644
--- a/fbw-common/src/systems/shared/src/GsxSync.ts
+++ b/fbw-common/src/systems/shared/src/GsxSync.ts
@@ -11,7 +11,13 @@ import {
SimVarValueType,
Wait,
} from '@microsoft/msfs-sdk';
-import { GroundSupportEvents, GsxSimVarEvents, MsfsFlightModelEvents, NXDataStore } from '@flybywiresim/fbw-sdk';
+import {
+ GroundSupportEvents,
+ GsxSimVarEvents,
+ MsfsFlightModelEvents,
+ GPUControlEvents,
+ NXDataStore,
+} from '@flybywiresim/fbw-sdk';
export enum GsxStates {
FALSE = 0,
@@ -21,6 +27,7 @@ export enum GsxStates {
}
export enum GsxServiceStates {
+ UNKNOWN = 0, //service state is unknown (i.e. GSX not started / initialized)
CALLABLE = 1, //service can be called
UNVAILABLE = 2, //service is not available
BYPASSED = 3, //service has been bypassed
@@ -47,13 +54,6 @@ enum DoorTarget {
OPEN = 1,
}
-enum PowerAction {
- NOOP = -1,
- DISCONNECT = 0,
- CONNECT = 1,
-}
-
-const DELAY_CARGO_CLOSE = 60000;
const DELAY_REFUEL_RESTART = 2000;
const DELAY_RATE_RESTORE = DELAY_REFUEL_RESTART + 1000;
const DELAY_FUEL_START = 500;
@@ -62,13 +62,16 @@ const DEFUEL_DIFF_TARGET_A380 = 2500;
abstract class GsxSync implements Instrument {
protected readonly sub = this.bus.getSubscriber();
+ protected readonly pub = this.bus.getPublisher();
protected readonly extPowerAvailStates = new Map>();
protected readonly couatlStarted = ConsumerSubject.create(null, 0);
- protected readonly stateJetway = ConsumerSubject.create(null, 1);
+ protected readonly stateJetway = ConsumerSubject.create(null, 0);
protected readonly stateBoard = ConsumerSubject.create(null, 1);
protected readonly stateDeboard = ConsumerSubject.create(null, 1);
protected readonly stateDeparture = ConsumerSubject.create(null, 1);
- protected readonly stateGpu = ConsumerSubject.create(null, 0);
+ protected readonly gpuConnection = ConsumerSubject.create(null, 0);
+ protected lastJetwayState = 0;
+ protected lastGpuConnection = 0;
protected isRefuelActive = false;
protected isDefuel = false;
protected readonly fuelTimer = new DebounceTimer();
@@ -107,7 +110,7 @@ abstract class GsxSync implements Instrument {
this.stateBoard.setConsumer(this.sub.on('gsx_boarding_state'));
this.stateDeboard.setConsumer(this.sub.on('gsx_deboarding_state'));
this.stateDeparture.setConsumer(this.sub.on('gsx_departure_state'));
- this.stateGpu.setConsumer(this.sub.on('gsx_gpu_connected'));
+ this.gpuConnection.setConsumer(this.sub.on('gsx_gpu_connected'));
this.fuelHose.setConsumer(this.sub.on('gsx_fuelhose_connected'));
this.refuelStartedByUser.setConsumer(this.sub.on('a32nx_refuel_started_by_user'));
this.cargoDoorTarget.setConsumer(this.sub.on(`msfs_interactive_point_goal_${this.getCargoDoorIndex()}`));
@@ -116,8 +119,8 @@ abstract class GsxSync implements Instrument {
this.attachedLoader1.setConsumer(this.sub.on('gsx_aircraft_loader_1_attached'));
this.attachedLoader2.setConsumer(this.sub.on('gsx_aircraft_loader_2_attached'));
- this.stateBoard.sub(this.onBoardingCompleted.bind(this));
- this.stateDeboard.sub(this.onBoardingCompleted.bind(this));
+ this.stateBoard.sub(this.onLoadingCompleted.bind(this));
+ this.stateDeboard.sub(this.onLoadingCompleted.bind(this));
this.stateDeparture.sub(this.onPushbackActive.bind(this));
this.toggleCargo1.sub(this.onToggleCargo.bind(this));
@@ -128,18 +131,29 @@ abstract class GsxSync implements Instrument {
this.fuelHose.sub(this.onFuelHoseConnected.bind(this));
this.refuelStartedByUser.sub(this.onRefuelStartedByUser.bind(this));
- this.stateJetway.sub(this.evaluateGsxPowerSource.bind(this));
- this.stateGpu.sub(this.evaluateGsxPowerSource.bind(this));
- this.stateDeparture.sub(this.evaluateGsxPowerSource.bind(this));
+ this.stateJetway.sub(this.onJetwayChange.bind(this));
+ this.gpuConnection.sub(this.onGpuConnected.bind(this));
+ this.stateDeparture.sub(this.onDepartureChange.bind(this));
+ this.stateDeboard.sub(this.onDeboardChange.bind(this));
}
public onUpdate(): void {
if (this.initialIngameFrame) {
- this.onCouatlStarted(SimVar.GetSimVarValueFast('L:FSDT_GSX_COUATL_STARTED', SimVarValueType.Number));
+ NXDataStore.subscribeLegacy(SyncServices.POWER, (key, value) => this.onSyncSettingChanged(key, value));
this.initialIngameFrame = false;
}
}
+ protected onSyncSettingChanged(key: string, value: string): void {
+ if (key === SyncServices.POWER) {
+ if (value === '1') {
+ this.pub.pub('msfs_power_sync_state', false);
+ } else {
+ this.pub.pub('msfs_power_sync_state', true);
+ }
+ }
+ }
+
protected isSyncEnabled(service: SyncServices): boolean {
return NXDataStore.getLegacy(service, '0') === '1';
}
@@ -159,7 +173,16 @@ abstract class GsxSync implements Instrument {
protected onCouatlStarted(state: number): void {
if (state === GsxStates.TRUE) {
//gsx-ism: we don't want gsx progressive fuel when the aircraft progressively refuels
- SimVar.SetSimVarValue('L:FSDT_GSX_SET_PROGRESS_REFUEL', SimVarValueType.Number, -1);
+ if (this.isSyncEnabled(SyncServices.FUEL) == true) {
+ SimVar.SetSimVarValue('L:FSDT_GSX_SET_PROGRESS_REFUEL', SimVarValueType.Number, -1);
+ }
+
+ //disable sync to msfs
+ if (this.isSyncEnabled(SyncServices.POWER) == true) {
+ this.pub.pub('msfs_power_sync_state', false);
+ }
+ } else {
+ this.pub.pub('msfs_power_sync_state', true);
}
}
@@ -174,9 +197,7 @@ abstract class GsxSync implements Instrument {
protected abstract setDesiredFuel(desiredFuel: number): void;
protected onFuelHoseConnected(hose: number): void {
- if (!this.isSyncEnabled(SyncServices.FUEL)) {
- return;
- }
+ if (this.isSyncEnabled(SyncServices.FUEL) == false) return;
//start De/Refuel when Hose is connected
if (hose === GsxStates.CONNECTED && !this.refuelStartedByUser.get() && !this.isRefuelActive) {
@@ -210,9 +231,7 @@ abstract class GsxSync implements Instrument {
}
protected onRefuelStartedByUser(refuel: boolean): void {
- if (!this.isSyncEnabled(SyncServices.FUEL)) {
- return;
- }
+ if (this.isSyncEnabled(SyncServices.FUEL) == false) return;
//defuel has finished - instant refuel to desired to get the truck triggered to leave
if (!refuel && this.fuelHose.get() === GsxStates.CONNECTED && this.isDefuel) {
@@ -236,58 +255,71 @@ abstract class GsxSync implements Instrument {
}
}
- protected evaluateGsxPowerSource(): void {
- if (!this.isSyncEnabled(SyncServices.POWER)) {
- return;
+ protected onJetwayChange(state: number): void {
+ if (
+ this.isSyncEnabled(SyncServices.POWER) == true &&
+ this.lastJetwayState !== state &&
+ state > GsxServiceStates.UNKNOWN &&
+ this.couatlStarted.get() === GsxStates.TRUE
+ ) {
+ //sync Power to Jetway Connectionn (as of GSX)
+ if (state === GsxServiceStates.ACTIVE && !this.isExtPowerAvail()) {
+ this.setExtPower(true);
+ } else if (
+ state !== GsxServiceStates.ACTIVE &&
+ this.isExtPowerAvail() &&
+ this.gpuConnection.get() === GsxStates.DISCONNECTED
+ ) {
+ this.setExtPower(false);
+ }
}
- const extAvail = this.isExtPowerAvail();
- const jetwayState = this.stateJetway.get();
- const gpuState = this.stateGpu.get();
- const boardState = this.stateBoard.get();
- const deboardState = this.stateDeboard.get();
- const departureState = this.stateDeparture.get();
- let action = PowerAction.NOOP;
-
- // external is available (as of internal State) - check if disconnect is needed
- if (extAvail) {
- // pushback was requested (when boarding not running)
- if (
- boardState !== GsxServiceStates.REQUESTED &&
- boardState !== GsxServiceStates.ACTIVE &&
- boardState !== GsxServiceStates.COMPLETING &&
- departureState >= GsxServiceStates.REQUESTED
- ) {
- action = PowerAction.DISCONNECT;
- // pushback is active (if it wasn't catched before)
- } else if (departureState === GsxServiceStates.ACTIVE) {
- action = PowerAction.DISCONNECT;
- // jetway and gpu both not connected
+ this.lastJetwayState = state;
+ }
+
+ protected onGpuConnected(state: number): void {
+ if (
+ this.isSyncEnabled(SyncServices.POWER) == true &&
+ this.lastGpuConnection !== state &&
+ this.couatlStarted.get() === GsxStates.TRUE
+ ) {
+ //sync Power to GSX GPU Connectionn
+ if (state === GsxStates.CONNECTED && !this.isExtPowerAvail()) {
+ this.setExtPower(true);
} else if (
- jetwayState >= GsxServiceStates.CALLABLE &&
- jetwayState <= GsxServiceStates.BYPASSED &&
- gpuState !== GsxStates.CONNECTED
+ state === GsxStates.DISCONNECTED &&
+ this.isExtPowerAvail() &&
+ this.stateJetway.get() !== GsxServiceStates.ACTIVE
) {
- action = PowerAction.DISCONNECT;
+ this.setExtPower(false);
}
- // external is not available - check if connect is needed
- } else if (
- //jetway or gpu connected
- (jetwayState >= GsxServiceStates.REQUESTED ||
- gpuState === GsxStates.CONNECTED ||
- deboardState === GsxServiceStates.ACTIVE) &&
- departureState < GsxServiceStates.REQUESTED
- ) {
- action = PowerAction.CONNECT;
}
+ this.lastGpuConnection = state;
+ }
- if (action == PowerAction.CONNECT) {
- this.setExtPower(true);
- } else if (action == PowerAction.DISCONNECT) {
+ protected onDepartureChange(state: number): void {
+ if (this.isSyncEnabled(SyncServices.POWER) == false) return;
+
+ //remove Power when Pushback is requested or gets active
+ if ((state === GsxServiceStates.REQUESTED || state === GsxServiceStates.ACTIVE) && this.isExtPowerAvail()) {
this.setExtPower(false);
}
}
+ protected onDeboardChange(state: number): void {
+ if (this.isSyncEnabled(SyncServices.POWER) == false) return;
+
+ //set Power when Deboard is active and jetway state is not valid (gsx-ism on arrival or User didn't request GSX GPU or set Power via FlyPad)
+ if (
+ state === GsxServiceStates.ACTIVE &&
+ this.stateJetway.get() !== GsxServiceStates.UNVAILABLE &&
+ this.stateJetway.get() === GsxServiceStates.ACTIVE &&
+ !this.isExtPowerAvail()
+ ) {
+ this.setExtPower(true);
+ }
+ }
+
protected isExtPowerAvail(): boolean {
let state = false;
for (let index = 1; index <= this.numberOfGPUs; index++) {
@@ -296,14 +328,13 @@ abstract class GsxSync implements Instrument {
return state;
}
- protected abstract setOvhdPushBtn(index: number, state: boolean): void;
+ protected abstract isPowerConnected(): boolean;
protected setExtPower(connect: boolean): void {
- for (let index = 1; index <= this.numberOfGPUs; index++) {
- SimVar.SetSimVarValue(`L:A32NX_EXT_PWR_AVAIL:${index}`, SimVarValueType.Bool, connect);
- if (!connect) {
- this.setOvhdPushBtn(index, connect);
- }
+ if (connect && !this.isExtPowerAvail()) {
+ this.pub.pub('set_ext_power', true);
+ } else if (!this.isPowerConnected() && this.isExtPowerAvail()) {
+ this.pub.pub('set_ext_power', false);
}
}
@@ -311,6 +342,10 @@ abstract class GsxSync implements Instrument {
return this.cargoDoorTarget.get() !== DoorTarget.CLOSED;
}
+ protected isLoaderAttached(): boolean {
+ return this.attachedLoader1.get() === GsxStates.CONNECTED || this.attachedLoader2.get() === GsxStates.CONNECTED;
+ }
+
protected abstract getCargoDoorIndex(): number;
protected setCargoDoor(goal: number, index: number): void {
@@ -320,9 +355,9 @@ abstract class GsxSync implements Instrument {
SimVar.SetSimVarValue(`A:INTERACTIVE POINT GOAL:${index}`, SimVarValueType.PercentOver100, goal);
}
- protected onBoardingCompleted(state: number): void {
- //just to be safe, check again when boarding was completed
- if (state === GsxServiceStates.COMPLETED && this.isCargoOpen()) {
+ protected onLoadingCompleted(state: number): void {
+ //check if doors can be closed when boarding/deboarding was completed
+ if (state === GsxServiceStates.COMPLETED && this.isCargoOpen() && !this.isLoaderAttached()) {
this.setCargoDoor(DoorTarget.CLOSED, this.getCargoDoorIndex());
}
}
@@ -360,6 +395,10 @@ export class GsxSyncA32NX extends GsxSync {
super(bus, 1, DEFUEL_DIFF_TARGET_A320);
}
+ protected override initSubscriptions(): void {
+ super.initSubscriptions();
+ }
+
protected getFob(): number {
return SimVar.GetSimVarValueFast('L:A32NX_TOTAL_FUEL_QUANTITY', SimVarValueType.Number);
}
@@ -373,10 +412,8 @@ export class GsxSyncA32NX extends GsxSync {
SimVar.SetSimVarValue('L:A32NX_FUEL_RIGHT_MAIN_DESIRED', SimVarValueType.Number, desiredFuel);
}
- protected setOvhdPushBtn(index: number, state: boolean): void {
- if (index === 1) {
- SimVar.SetSimVarValue(`L:A32NX_OVHD_ELEC_EXT_PWR_PB_IS_ON`, SimVarValueType.Bool, state);
- }
+ protected isPowerConnected(): boolean {
+ return SimVar.GetSimVarValue(`L:A32NX_OVHD_ELEC_EXT_PWR_PB_IS_ON`, SimVarValueType.Bool) == true;
}
protected getCargoDoorIndex(): number {
@@ -401,8 +438,13 @@ export class GsxSyncA380X extends GsxSync {
SimVar.SetSimVarValue('L:A32NX_FUEL_DESIRED', 'kilograms', desiredFuel);
}
- protected setOvhdPushBtn(index: number, state: boolean): void {
- SimVar.SetSimVarValue(`L:A32NX_OVHD_ELEC_EXT_PWR_${index}_PB_IS_ON`, SimVarValueType.Bool, state);
+ protected isPowerConnected(): boolean {
+ for (let index = 1; index <= this.numberOfGPUs; index++) {
+ if (SimVar.GetSimVarValue(`L:A32NX_OVHD_ELEC_EXT_PWR_${index}_PB_IS_ON`, SimVarValueType.Bool) == true) {
+ return true;
+ }
+ }
+ return false;
}
protected getCargoDoorIndex(): number {