Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: GSX Integration #7695

Merged
merged 23 commits into from Feb 11, 2023
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
275 changes: 177 additions & 98 deletions flybywire-aircraft-a320-neo/html_ui/Pages/A32NX_Core/A32NX_Boarding.js
Expand Up @@ -25,6 +25,10 @@ class A32NX_Boarding {
const payloadConstruct = new A32NX_PayloadConstructor();
this.paxStations = payloadConstruct.paxStations;
this.cargoStations = payloadConstruct.cargoStations;

// GSX Helpers
this.passengersLeftToFillOrEmpty = 0;
this.prevBoardedOrDeboarded = 0;
}

async init() {
Expand Down Expand Up @@ -86,139 +90,214 @@ class A32NX_Boarding {
}
}

isGsxBoarding(boardState, deboardState) {
return boardState === 5 || deboardState === 5;
}

async update(_deltaTime) {
this.time += _deltaTime;

const boardingStartedByUser = SimVar.GetSimVarValue("L:A32NX_BOARDING_STARTED_BY_USR", "Bool");
const boardingRate = NXDataStore.get("CONFIG_BOARDING_RATE", 'REAL');
const gsxPayloadSyncEnabled = NXDataStore.get("GSX_PAYLOAD_SYNC", 0);

if (!boardingStartedByUser) {
return;
}
if (gsxPayloadSyncEnabled === '1') {
const gsxBoardState = Math.round(SimVar.GetSimVarValue("L:FSDT_GSX_BOARDING_STATE", "Number"));
const gsxDeBoardState = Math.round(SimVar.GetSimVarValue("L:FSDT_GSX_DEBOARDING_STATE", "Number"));

if ((!airplaneCanBoard() && boardingRate == 'REAL') || (!airplaneCanBoard() && boardingRate == 'FAST')) {
return;
}
// Just in-case payload menu isn't open on EFB, if Deboard requested set pax and cargo target to 0
if (gsxDeBoardState === 4) {
for (const paxStation of Object.values(this.paxStations).reverse()) {
SimVar.SetSimVarValue(`L:${paxStation.simVar}_DESIRED`, "Number", parseInt(0));
}

const currentPax = Object.values(this.paxStations).map((station) => SimVar.GetSimVarValue(`L:${station.simVar}`, "Number")).reduce((acc, cur) => acc + cur);
const paxTarget = Object.values(this.paxStations).map((station) => SimVar.GetSimVarValue(`L:${station.simVar}_DESIRED`, "Number")).reduce((acc, cur) => acc + cur);
const currentLoad = Object.values(this.cargoStations).map((station) => SimVar.GetSimVarValue(`L:${station.simVar}`, "Number")).reduce((acc, cur) => acc + cur);
const loadTarget = Object.values(this.cargoStations).map((station) => SimVar.GetSimVarValue(`L:${station.simVar}_DESIRED`, "Number")).reduce((acc, cur) => acc + cur);
for (const loadStation of Object.values(this.cargoStations)) {
SimVar.SetSimVarValue(`L:${loadStation.simVar}_DESIRED`, "Number", parseInt(0));
}
}

let isAllPaxStationFilled = true;
for (const _station of Object.values(this.paxStations)) {
const stationCurrentPax = SimVar.GetSimVarValue(`L:${_station.simVar}`, "Number");
const stationCurrentPaxTarget = SimVar.GetSimVarValue(`L:${_station.simVar}_DESIRED`, "Number");
if (gsxBoardState === 5) {
const gsxBoardingTotal = SimVar.GetSimVarValue("L:FSDT_GSX_NUMPASSENGERS_BOARDING_TOTAL", "Number");
this.passengersLeftToFillOrEmpty = gsxBoardingTotal - this.prevBoardedOrDeboarded;

// Passenger boarding, boards each station subsequently
for (const paxStation of Object.values(this.paxStations).reverse()) {
const stationCurrentPax = SimVar.GetSimVarValue(`L:${paxStation.simVar}`, "Number");
const stationCurrentPaxTarget = SimVar.GetSimVarValue(`L:${paxStation.simVar}_DESIRED`, "Number");
if (this.passengersLeftToFillOrEmpty <= 0) {
break;
}

const loadAmount = Math.min(this.passengersLeftToFillOrEmpty, paxStation.seats);
if (stationCurrentPax < stationCurrentPaxTarget) {
this.fillPaxStation(paxStation, stationCurrentPax + loadAmount);
this.passengersLeftToFillOrEmpty -= loadAmount;
}
}
this.prevBoardedOrDeboarded = gsxBoardingTotal;

if (stationCurrentPax !== stationCurrentPaxTarget) {
isAllPaxStationFilled = false;
break;
}
}
const gsxCargoPercentage = SimVar.GetSimVarValue("L:FSDT_GSX_BOARDING_CARGO_PERCENT", "Number");
for (const loadStation of Object.values(this.cargoStations)) {
const stationCurrentLoadTarget = SimVar.GetSimVarValue(`L:${loadStation.simVar}_DESIRED`, "Number");

let isAllCargoStationFilled = true;
for (const _station of Object.values(this.cargoStations)) {
const stationCurrentLoad = SimVar.GetSimVarValue(`L:${_station.simVar}`, "Number");
const stationCurrentLoadTarget = SimVar.GetSimVarValue(`L:${_station.simVar}_DESIRED`, "Number");
const loadAmount = stationCurrentLoadTarget * (gsxCargoPercentage / 100);
this.fillCargoStation(loadStation, loadAmount);
}
}

if (stationCurrentLoad !== stationCurrentLoadTarget) {
isAllCargoStationFilled = false;
break;
if (gsxDeBoardState === 5) {
const gsxDeBoardingTotal = SimVar.GetSimVarValue("L:FSDT_GSX_NUMPASSENGERS_DEBOARDING_TOTAL", "Number");
this.passengersLeftToFillOrEmpty = gsxDeBoardingTotal - this.prevBoardedOrDeboarded;

for (const paxStation of Object.values(this.paxStations).reverse()) {
const stationCurrentPax = SimVar.GetSimVarValue(`L:${paxStation.simVar}`, "Number");
const stationCurrentPaxTarget = SimVar.GetSimVarValue(`L:${paxStation.simVar}_DESIRED`, "Number");
if (this.passengersLeftToFillOrEmpty <= 0) {
break;
}

if (stationCurrentPax > stationCurrentPaxTarget) {
this.fillPaxStation(paxStation, stationCurrentPax - Math.min(this.passengersLeftToFillOrEmpty, paxStation.seats));
this.passengersLeftToFillOrEmpty -= Math.min(this.passengersLeftToFillOrEmpty, paxStation.seats);
}
}
this.prevBoardedOrDeboarded = gsxDeBoardingTotal;
}
}

// Sound Controllers
if ((currentPax < paxTarget) && boardingStartedByUser == true) {
await SimVar.SetSimVarValue("L:A32NX_SOUND_PAX_BOARDING", "Bool", true);
this.isBoarding = true;
this.loadPaxPayload();
this.loadCargoPayload();

} else {
await SimVar.SetSimVarValue("L:A32NX_SOUND_PAX_BOARDING", "Bool", false);
}
if (!boardingStartedByUser) {
return;
}

await SimVar.SetSimVarValue("L:A32NX_SOUND_PAX_DEBOARDING", "Bool", currentPax > paxTarget && boardingStartedByUser == true);
if ((!airplaneCanBoard() && boardingRate == 'REAL') || (!airplaneCanBoard() && boardingRate == 'FAST')) {
return;
}

if ((currentPax == paxTarget) && this.isBoarding == true) {
await SimVar.SetSimVarValue("L:A32NX_SOUND_BOARDING_COMPLETE", "Bool", true);
this.isBoarding = false;
return;
}
await SimVar.SetSimVarValue("L:A32NX_SOUND_BOARDING_COMPLETE", "Bool", false);
const currentPax = Object.values(this.paxStations).map((station) => SimVar.GetSimVarValue(`L:${station.simVar}`, "Number")).reduce((acc, cur) => acc + cur);
const paxTarget = Object.values(this.paxStations).map((station) => SimVar.GetSimVarValue(`L:${station.simVar}_DESIRED`, "Number")).reduce((acc, cur) => acc + cur);
const currentLoad = Object.values(this.cargoStations).map((station) => SimVar.GetSimVarValue(`L:${station.simVar}`, "Number")).reduce((acc, cur) => acc + cur);
const loadTarget = Object.values(this.cargoStations).map((station) => SimVar.GetSimVarValue(`L:${station.simVar}_DESIRED`, "Number")).reduce((acc, cur) => acc + cur);

await SimVar.SetSimVarValue("L:A32NX_SOUND_PAX_AMBIENCE", "Bool", currentPax > 0);
let isAllPaxStationFilled = true;
for (const _station of Object.values(this.paxStations)) {
const stationCurrentPax = SimVar.GetSimVarValue(`L:${_station.simVar}`, "Number");
const stationCurrentPaxTarget = SimVar.GetSimVarValue(`L:${_station.simVar}_DESIRED`, "Number");

if (currentPax === paxTarget && currentLoad === loadTarget && isAllPaxStationFilled && isAllCargoStationFilled) {
// Finish boarding
this.boardingState = "finished";
await SimVar.SetSimVarValue("L:A32NX_BOARDING_STARTED_BY_USR", "Bool", false);
if (stationCurrentPax !== stationCurrentPaxTarget) {
isAllPaxStationFilled = false;
break;
}
}

} else if ((currentPax < paxTarget) || (currentLoad < loadTarget)) {
this.boardingState = "boarding";
} else if ((currentPax === paxTarget) && (currentLoad === loadTarget)) {
this.boardingState = "finished";
}
let isAllCargoStationFilled = true;
for (const _station of Object.values(this.cargoStations)) {
const stationCurrentLoad = SimVar.GetSimVarValue(`L:${_station.simVar}`, "Number");
const stationCurrentLoadTarget = SimVar.GetSimVarValue(`L:${_station.simVar}_DESIRED`, "Number");

if (boardingRate == 'INSTANT') {
// Instant
for (const paxStation of Object.values(this.paxStations)) {
const stationCurrentPaxTarget = SimVar.GetSimVarValue(`L:${paxStation.simVar}_DESIRED`, "Number");
await this.fillPaxStation(paxStation, stationCurrentPaxTarget);
if (stationCurrentLoad !== stationCurrentLoadTarget) {
isAllCargoStationFilled = false;
break;
}
}
for (const loadStation of Object.values(this.cargoStations)) {
const stationCurrentLoadTarget = SimVar.GetSimVarValue(`L:${loadStation.simVar}_DESIRED`, "Number");
await this.fillCargoStation(loadStation, stationCurrentLoadTarget);

// Sound Controllers
if ((currentPax < paxTarget) && boardingStartedByUser == true) {
await SimVar.SetSimVarValue("L:A32NX_SOUND_PAX_BOARDING", "Bool", true);
this.isBoarding = true;
} else {
await SimVar.SetSimVarValue("L:A32NX_SOUND_PAX_BOARDING", "Bool", false);
}
this.loadPaxPayload();
this.loadCargoPayload();
return;
}

let msDelay = 5000;
await SimVar.SetSimVarValue("L:A32NX_SOUND_PAX_DEBOARDING", "Bool", currentPax > paxTarget && boardingStartedByUser == true);

if (boardingRate == 'FAST') {
msDelay = 1000;
}
if ((currentPax == paxTarget) && this.isBoarding == true) {
await SimVar.SetSimVarValue("L:A32NX_SOUND_BOARDING_COMPLETE", "Bool", true);
this.isBoarding = false;
return;
}
await SimVar.SetSimVarValue("L:A32NX_SOUND_BOARDING_COMPLETE", "Bool", false);

if (boardingRate == 'REAL') {
msDelay = 5000;
}
await SimVar.SetSimVarValue("L:A32NX_SOUND_PAX_AMBIENCE", "Bool", currentPax > 0);

if (this.time > msDelay) {
this.time = 0;
if (currentPax === paxTarget && currentLoad === loadTarget && isAllPaxStationFilled && isAllCargoStationFilled) {
// Finish boarding
this.boardingState = "finished";
await SimVar.SetSimVarValue("L:A32NX_BOARDING_STARTED_BY_USR", "Bool", false);

// Stations logic:
for (const paxStation of Object.values(this.paxStations).reverse()) {
const stationCurrentPax = SimVar.GetSimVarValue(`L:${paxStation.simVar}`, "Number");
const stationCurrentPaxTarget = SimVar.GetSimVarValue(`L:${paxStation.simVar}_DESIRED`, "Number");
} else if ((currentPax < paxTarget) || (currentLoad < loadTarget)) {
this.boardingState = "boarding";
} else if ((currentPax === paxTarget) && (currentLoad === loadTarget)) {
this.boardingState = "finished";
}

if (stationCurrentPax < stationCurrentPaxTarget) {
this.fillPaxStation(paxStation, stationCurrentPax + 1);
break;
} else if (stationCurrentPax > stationCurrentPaxTarget) {
this.fillPaxStation(paxStation, stationCurrentPax - 1);
break;
} else {
continue;
// TODO handle having cargo synced but not boarding and vice versa
if (boardingRate == 'INSTANT') {
// Instant
for (const paxStation of Object.values(this.paxStations)) {
const stationCurrentPaxTarget = SimVar.GetSimVarValue(`L:${paxStation.simVar}_DESIRED`, "Number");
await this.fillPaxStation(paxStation, stationCurrentPaxTarget);
}
for (const loadStation of Object.values(this.cargoStations)) {
const stationCurrentLoadTarget = SimVar.GetSimVarValue(`L:${loadStation.simVar}_DESIRED`, "Number");
await this.fillCargoStation(loadStation, stationCurrentLoadTarget);
}
this.loadPaxPayload();
this.loadCargoPayload();
return;
}

for (const loadStation of Object.values(this.cargoStations)) {
const stationCurrentLoad = SimVar.GetSimVarValue(`L:${loadStation.simVar}`, "Number");
const stationCurrentLoadTarget = SimVar.GetSimVarValue(`L:${loadStation.simVar}_DESIRED`, "Number");
let msDelay = 5000;

const loadDelta = Math.abs(stationCurrentLoadTarget - stationCurrentLoad);
if (stationCurrentLoad < stationCurrentLoadTarget) {
this.fillCargoStation(loadStation, stationCurrentLoad + Math.min(60, loadDelta));
break;
} else if (stationCurrentLoad > stationCurrentLoadTarget) {
this.fillCargoStation(loadStation, stationCurrentLoad - Math.min(60, loadDelta));
break;
} else {
continue;
}
if (boardingRate == 'FAST') {
msDelay = 1000;
}

this.loadPaxPayload();
this.loadCargoPayload();
if (boardingRate == 'REAL') {
msDelay = 5000;
}

if (this.time > msDelay) {
this.time = 0;

// TODO handle having cargo synced but not boarding and vice versa
// Stations logic:
for (const paxStation of Object.values(this.paxStations).reverse()) {
const stationCurrentPax = SimVar.GetSimVarValue(`L:${paxStation.simVar}`, "Number");
const stationCurrentPaxTarget = SimVar.GetSimVarValue(`L:${paxStation.simVar}_DESIRED`, "Number");

if (stationCurrentPax < stationCurrentPaxTarget) {
this.fillPaxStation(paxStation, stationCurrentPax + 1);
break;
} else if (stationCurrentPax > stationCurrentPaxTarget) {
this.fillPaxStation(paxStation, stationCurrentPax - 1);
break;
} else {
continue;
}
}

for (const loadStation of Object.values(this.cargoStations)) {
const stationCurrentLoad = SimVar.GetSimVarValue(`L:${loadStation.simVar}`, "Number");
const stationCurrentLoadTarget = SimVar.GetSimVarValue(`L:${loadStation.simVar}_DESIRED`, "Number");

const loadDelta = Math.abs(stationCurrentLoadTarget - stationCurrentLoad);
if (stationCurrentLoad < stationCurrentLoadTarget) {
this.fillCargoStation(loadStation, stationCurrentLoad + Math.min(60, loadDelta));
break;
} else if (stationCurrentLoad > stationCurrentLoadTarget) {
this.fillCargoStation(loadStation, stationCurrentLoad - Math.min(60, loadDelta));
break;
} else {
continue;
}
}

this.loadPaxPayload();
this.loadCargoPayload();
}
}
}
}
19 changes: 18 additions & 1 deletion src/instruments/src/EFB/Ground/Pages/FuelPage.tsx
Expand Up @@ -3,7 +3,7 @@ import React, { useState } from 'react';
import { round } from 'lodash';
import { CloudArrowDown, PlayFill, StopCircleFill } from 'react-bootstrap-icons';
import { useSimVar } from '@instruments/common/simVars';
import { usePersistentProperty } from '@instruments/common/persistence';
import { usePersistentNumberProperty, usePersistentProperty } from '@instruments/common/persistence';
import Slider from 'rc-slider';
import { Units } from '@shared/units';
import { t } from '../../translation';
Expand Down Expand Up @@ -91,6 +91,10 @@ export const FuelPage = () => {
const [RInnCurrent] = useSimVar('FUEL TANK RIGHT MAIN QUANTITY', 'Gallons', 1_000);
const [ROutCurrent] = useSimVar('FUEL TANK RIGHT AUX QUANTITY', 'Gallons', 1_000);

// GSX
const [gsxFuelSyncEnabled] = usePersistentNumberProperty('GSX_FUEL_SYNC', 0);
const [gsxFuelHoseConnected] = useSimVar('L:FSDT_GSX_FUELHOSE_CONNECTED', 'Number');

const { units } = useAppSelector((state) => state.simbrief.data);
const { planRamp } = useAppSelector((state) => state.simbrief.data.fuels);
const simbriefDataLoaded = isSimbriefDataLoaded();
Expand All @@ -108,6 +112,19 @@ export const FuelPage = () => {
setRefuelRate('2');
}
}

if (gsxFuelSyncEnabled === 1) {
if (gsxFuelHoseConnected === 1) {
return true;
}

// In-flight refueling with GSX Sync enabled
if (!isAirplaneCnD() && refuelRate === '2') {
return true;
}

return false;
}
return true;
};

Expand Down