diff --git a/.github/CHANGELOG.md b/.github/CHANGELOG.md index 93ba1eef46e..573139c2038 100644 --- a/.github/CHANGELOG.md +++ b/.github/CHANGELOG.md @@ -85,6 +85,9 @@ 1. [EFB] Checklist restructure to add more capabilities and use json configs - @frankkopp (Frank Kopp) 1. [FLIGHTMODEL] Landing lights or RAT extended now have drag - @Crocket63 (crocket) 1. [ATHR/FADEC] Improved reverse thrust limit - @aguther (Andreas Guther) +1. [GENERAL] Implemented a new unified VFS JSON5 markup standard for A/C configuration for FlyByWire based projects (building block for per-livery configuration) - @2hwk (2Cas) +1. [GENERAL] Added environ AIRCRAFT_PROJECT_PREFIX to allow for custom aircraft project prefixes - @2hwk (2Cas) +1. [EFB] Read from VFS JSON5 markup for Ground > Payload page - @2hwk (2Cas) ## 0.11.0 diff --git a/.github/workflows/a380x-exp.yml b/.github/workflows/a380x-exp.yml index 0413e34f140..5bcd9303bc9 100644 --- a/.github/workflows/a380x-exp.yml +++ b/.github/workflows/a380x-exp.yml @@ -17,6 +17,8 @@ jobs: FBW_PRODUCTION_BUILD: 1 A32NX_INSTRUMENTS_BUILD_WORKERS: 2 BUILD_DIR_NAME: a380x-experimental-a32nx + AIRCRAFT_PROJECT_PREFIX: a32nx + AIRCRAFT_VARIANT: a320-251n steps: - name: Checkout source uses: actions/checkout@v4 @@ -29,6 +31,8 @@ jobs: echo CLIENT_SECRET=\"${{ secrets.NAVIGRAPH_CLIENT_SECRET }}\" >> fbw-a32nx/.env echo CHARTFOX_SECRET=\"${{ secrets.CHARTFOX_SECRET }}\" >> fbw-a32nx/.env echo SENTRY_DSN=\"${{ secrets.SENTRY_DSN }}\" >> fbw-a32nx/.env + echo AIRCRAFT_PROJECT_PREFIX=${{ env.AIRCRAFT_PROJECT_PREFIX }} >> fbw-a32nx/.env + echo AIRCRAFT_VARIANT=${{ env.AIRCRAFT_VARIANT }} >> fbw-a32nx/.env echo BUILD_DIR_NAME=${{ env.BUILD_DIR_NAME }} >> .env echo LOCALAZY_READ_KEY=${{ secrets.LOCALAZY_READ_KEY }} >> .env echo VITE_BUILD=false >> .env @@ -66,6 +70,8 @@ jobs: env: FBW_PRODUCTION_BUILD: 1 BUILD_DIR_NAME: a380x-experimental-a380x + AIRCRAFT_PROJECT_PREFIX: a380x + AIRCRAFT_VARIANT: a380-842 steps: - name: Checkout source uses: actions/checkout@v4 @@ -78,6 +84,8 @@ jobs: echo CLIENT_SECRET=\"${{ secrets.NAVIGRAPH_CLIENT_SECRET_A380X }}\" >> fbw-a380x/.env echo CHARTFOX_SECRET=\"${{ secrets.CHARTFOX_SECRET }}\" >> fbw-a380x/.env echo SENTRY_DSN=\"${{ secrets.SENTRY_DSN }}\" >> fbw-a380x/.env + echo AIRCRAFT_PROJECT_PREFIX=${{ env.AIRCRAFT_PROJECT_PREFIX }} >> fbw-a380x/.env + echo AIRCRAFT_VARIANT=${{ env.AIRCRAFT_VARIANT }} >> fbw-a380x/.env echo BUILD_DIR_NAME=${{ env.BUILD_DIR_NAME }} >> .env echo LOCALAZY_READ_KEY=${{ secrets.LOCALAZY_READ_KEY }} >> .env echo VITE_BUILD=false >> .env diff --git a/.github/workflows/master.yml b/.github/workflows/master.yml index 6673268dff4..09065d401ae 100644 --- a/.github/workflows/master.yml +++ b/.github/workflows/master.yml @@ -22,6 +22,8 @@ jobs: VMASTER_PRE_RELEASE_ID: 32243965 VMASTER_PRE_RELEASE_TAG: vmaster BUILD_DIR_NAME: master-a32nx + AIRCRAFT_PROJECT_PREFIX: a32nx + AIRCRAFT_VARIANT: a320-251n steps: - name: Checkout source uses: actions/checkout@v4 @@ -34,6 +36,8 @@ jobs: echo CLIENT_SECRET=\"${{ secrets.NAVIGRAPH_CLIENT_SECRET }}\" >> fbw-a32nx/.env echo CHARTFOX_SECRET=\"${{ secrets.CHARTFOX_SECRET }}\" >> fbw-a32nx/.env echo SENTRY_DSN=\"${{ secrets.SENTRY_DSN }}\" >> fbw-a32nx/.env + echo AIRCRAFT_PROJECT_PREFIX=\"${{ env.AIRCRAFT_PROJECT_PREFIX }}\" >> fbw-a32nx/.env + echo AIRCRAFT_VARIANT=${{ env.AIRCRAFT_VARIANT }} >> fbw-a32nx/.env echo BUILD_DIR_NAME=${{ env.BUILD_DIR_NAME }} >> .env echo LOCALAZY_READ_KEY=${{ secrets.LOCALAZY_READ_KEY }} >> .env echo VITE_BUILD=false >> .env @@ -100,6 +104,8 @@ jobs: VMASTER_PRE_RELEASE_ID: 32243965 VMASTER_PRE_RELEASE_TAG: vmaster BUILD_DIR_NAME: master-a380x + AIRCRAFT_PROJECT_PREFIX: a380x + AIRCRAFT_VARIANT: a380-842 steps: - name: Checkout source uses: actions/checkout@v4 @@ -112,6 +118,8 @@ jobs: echo CLIENT_SECRET=\"${{ secrets.NAVIGRAPH_CLIENT_SECRET_A380X }}\" >> fbw-a380x/.env echo CHARTFOX_SECRET=\"${{ secrets.CHARTFOX_SECRET }}\" >> fbw-a380x/.env echo SENTRY_DSN=\"${{ secrets.SENTRY_DSN }}\" >> fbw-a380x/.env + echo AIRCRAFT_PROJECT_PREFIX=\"${{ env.AIRCRAFT_PROJECT_PREFIX }}\" >> fbw-a380x/.env + echo AIRCRAFT_VARIANT=\"${{ env.AIRCRAFT_VARIANT }}\" >> fbw-a380x/.env echo BUILD_DIR_NAME=${{ env.BUILD_DIR_NAME }} >> .env echo LOCALAZY_READ_KEY=${{ secrets.LOCALAZY_READ_KEY }} >> .env echo VITE_BUILD=false >> .env diff --git a/.github/workflows/pr-build.yml b/.github/workflows/pr-build.yml index 211896aa4e4..6dc0ccba2ad 100644 --- a/.github/workflows/pr-build.yml +++ b/.github/workflows/pr-build.yml @@ -49,6 +49,8 @@ jobs: if: github.event.pull_request.draft == false env: FBW_PRODUCTION_BUILD: 1 + AIRCRAFT_PROJECT_PREFIX: a32nx + AIRCRAFT_VARIANT: a320-251n steps: - name: Checkout source uses: actions/checkout@v4 @@ -60,6 +62,8 @@ jobs: echo CLIENT_SECRET=\"${{ secrets.NAVIGRAPH_CLIENT_SECRET_A380X }}\" >> fbw-a32nx/.env echo CHARTFOX_SECRET=\"${{ secrets.CHARTFOX_SECRET }}\" >> fbw-a32nx/.env echo SENTRY_DSN=\"${{ secrets.SENTRY_DSN }}\" >> fbw-a32nx/.env + echo AIRCRAFT_PROJECT_PREFIX=\"${{ env.AIRCRAFT_PROJECT_PREFIX }}\" >> fbw-a32nx/.env + echo AIRCRAFT_VARIANT=\"${{ env.AIRCRAFT_VARIANT }}\" >> fbw-a32nx/.env echo LOCALAZY_READ_KEY=${{ secrets.LOCALAZY_READ_KEY }} >> .env echo VITE_BUILD=false >> .env cat fbw-a32nx/.env @@ -90,6 +94,8 @@ jobs: if: github.event.pull_request.draft == false env: FBW_PRODUCTION_BUILD: 1 + AIRCRAFT_PROJECT_PREFIX: a380x + AIRCRAFT_VARIANT: a380-842 steps: - name: Checkout source uses: actions/checkout@v4 @@ -102,6 +108,8 @@ jobs: echo CHARTFOX_SECRET=\"${{ secrets.CHARTFOX_SECRET }}\" >> fbw-a380x/.env echo SENTRY_DSN=\"${{ secrets.SENTRY_DSN }}\" >> fbw-a380x/.env echo LOCALAZY_READ_KEY=${{ secrets.LOCALAZY_READ_KEY }} >> .env + echo AIRCRAFT_PROJECT_PREFIX=\"${{ env.AIRCRAFT_PROJECT_PREFIX }}\" >> fbw-a380x/.env + echo AIRCRAFT_VARIANT=\"${{ env.AIRCRAFT_VARIANT }}\" >> fbw-a380x/.env echo VITE_BUILD=false >> .env cat fbw-a380x/.env - name: Install dependencies diff --git a/.github/workflows/pre-release.yml b/.github/workflows/pre-release.yml index 97e11779b8b..6ac48d26f7b 100644 --- a/.github/workflows/pre-release.yml +++ b/.github/workflows/pre-release.yml @@ -12,6 +12,8 @@ jobs: FBW_PRODUCTION_BUILD: 1 RELEASE_ZIP_NAME: A32NX-stable.7z BUILD_DIR_NAME: stable + AIRCRAFT_PROJECT_PREFIX: a32nx + AIRCRAFT_VARIANT: a320-251n steps: - name: Checkout source uses: actions/checkout@v2 @@ -23,6 +25,8 @@ jobs: echo CHARTFOX_SECRET=\"${{ secrets.CHARTFOX_SECRET }}\" >> fbw-a32nx/.env echo SENTRY_DSN=\"${{ secrets.SENTRY_DSN }}\" >> fbw-a32nx/.env echo BUILD_DIR_NAME=${{ env.BUILD_DIR_NAME }} >> .env + echo AIRCRAFT_PROJECT_PREFIX=${{ env.AIRCRAFT_PROJECT_PREFIX }} >> fbw-a32nx/.env + echo AIRCRAFT_VARIANT=${{ env.AIRCRAFT_VARIANT }} >> fbw-a32nx/.env echo LOCALAZY_READ_KEY=${{ secrets.LOCALAZY_READ_KEY }} >> .env echo VITE_BUILD=false >> .env - name: Build A32NX diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 4772659929b..0fca6a8d7a0 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -15,6 +15,8 @@ jobs: STABLE_PRE_RELEASE_TAG: assets/stable STABLE_ZIP_NAME: A32NX-stable.7z BUILD_DIR_NAME: stable + AIRCRAFT_PROJECT_PREFIX: a32nx + AIRCRAFT_VARIANT: a320-251n steps: - name: Checkout source uses: actions/checkout@v2 @@ -25,6 +27,8 @@ jobs: echo CLIENT_SECRET=\"${{ secrets.NAVIGRAPH_CLIENT_SECRET }}\" >> fbw-a32nx/.env echo CHARTFOX_SECRET=\"${{ secrets.CHARTFOX_SECRET }}\" >> fbw-a32nx/.env echo SENTRY_DSN=\"${{ secrets.SENTRY_DSN }}\" >> fbw-a32nx/.env + echo AIRCRAFT_PROJECT_PREFIX=${{ env.AIRCRAFT_PROJECT_PREFIX }} >> fbw-a32nx/.env + echo AIRCRAFT_VARIANT=${{ env.AIRCRAFT_VARIANT }} >> fbw-a32nx/.env echo BUILD_DIR_NAME=${{ env.BUILD_DIR_NAME }} >> .env echo LOCALAZY_READ_KEY=${{ secrets.LOCALAZY_READ_KEY }} >> .env echo VITE_BUILD=false >> .env diff --git a/fbw-a32nx/.env b/fbw-a32nx/.env index c7304412e55..667ddf3be9e 100644 --- a/fbw-a32nx/.env +++ b/fbw-a32nx/.env @@ -3,3 +3,5 @@ NODE_ENV=production CLIENT_SECRET="" CLIENT_ID="" SENTRY_DSN="" +AIRCRAFT_PROJECT_PREFIX="a32nx" +AIRCRAFT_VARIANT="a320-251n" diff --git a/fbw-a32nx/src/base/flybywire-aircraft-a320-neo/SimObjects/AirPlanes/FlyByWire_A320_NEO/panel/panel.cfg b/fbw-a32nx/src/base/flybywire-aircraft-a320-neo/SimObjects/AirPlanes/FlyByWire_A320_NEO/panel/panel.cfg index 2b299cde8ea..1dca06005b7 100644 --- a/fbw-a32nx/src/base/flybywire-aircraft-a320-neo/SimObjects/AirPlanes/FlyByWire_A320_NEO/panel/panel.cfg +++ b/fbw-a32nx/src/base/flybywire-aircraft-a320-neo/SimObjects/AirPlanes/FlyByWire_A320_NEO/panel/panel.cfg @@ -122,7 +122,7 @@ size_mm = 1430,1000 pixel_size = 1430,1000 texture = $EFB -htmlgauge00 = A32NX/EFB/efb.html?Airframe=A320_251N, 0,0,1430,1000 +htmlgauge00 = A32NX/EFB/efb.html, 0,0,1430,1000 [VCockpit17] size_mm = 0,0 diff --git a/fbw-a32nx/src/base/flybywire-aircraft-a320-neo/config/a32nx/a320-251n/README.md b/fbw-a32nx/src/base/flybywire-aircraft-a320-neo/config/a32nx/a320-251n/README.md new file mode 100644 index 00000000000..540b0e6f997 --- /dev/null +++ b/fbw-a32nx/src/base/flybywire-aircraft-a320-neo/config/a32nx/a320-251n/README.md @@ -0,0 +1,85 @@ +# FlyByWire Unified Config + +!!!!!!!!!!!! + +Note: This is a work in progress, consider this a developer-only preview, treat this as a private API and integrate with the current format and values at your own risk. Format at this stage can and will change suddenly without notice, warranty or support provided. Thank you for your cooperation, patience and understanding. + + +At this stage, if you have any suggestions, input or inquiries in regards to the structure/function of the config ``.json5`` files, +then please contact the FlyByWire core development team on [discord](https://discord.gg/flybywire). + +!!!!!!!!!!!!! + +The goal of this effort is to unify configuration for all FBW based projects, in a way that can be piped to both JS (completed) and WASM Gauges (pending), +and in doing so, exposing these variables for both easier visibility for contributors as well as aiding external parties in adapting the +flyPad and other components to other aircraft. + +Currently, there is config and hardcoded values spreadout across the project repository, sometimes in various configuration (.json, .h, .toml, etc.) files. + +The solution to this takes on (at the moment) the form of a VFS stored ``.json5`` markup files in ``config///*.json5`` that has a format that currently is being decided and iterated upon. + +This will (eventually) allow for deep, per-livery/tail number configuration i.e. dynamic passenger seating configurations and cargo loading by providing an override file (based on ATC ID/tailnumber), + +i.e. ``///*.json5`` + +This consists of several components and will be expanded upon in stages to facilitate and aid our code review and refactoring processes. + +**Note:** From this point, any configuration that exists in panel.xml and elsewhere that is left hardcoded should be considered to be left *NOT exposed on purpose*. +Please consult with our core development team before adding more configuration and hardcoded values into the ``config.json5`` markup. + +Please do NOT add any new configuration to the panel.xml or other configuration files that are not already present in the unified config. +Please do NOT add any new configuration to the panel.cfg or other configuration files that are not already present in the unified config. +Please do NOT move any more configuration or hardcoded values from FlyByWire header files, or other json or markup in the unified config. + +Please do NOT draft PRs or add configuration to the unified config, or any of its associated boilerplate and middleware, without first consulting with the core development team. + +Please do NOT hesitate to ask questions or seek clarification on the FlyByWire [discord](https://discord.gg/flybywire) server, we are here to help! + +**IMPORTANT** + +The base configuration location is in ``config///*.json5`` + +!!! DO NOT OVERWRITE, ADD, OR MODIFY ANY KEYS OR VALUES IN THE BASE CONFIG FILE. !!! +!!! DO NOT OVERWRITE, ADD, OR MODIFY ANY KEYS OR VALUES IN THE BASE CONFIG FILE. !!! +!!! DO NOT OVERWRITE, ADD, OR MODIFY ANY KEYS OR VALUES IN THE BASE CONFIG FILE. !!! +!!! DO NOT OVERWRITE, ADD, OR MODIFY ANY KEYS OR VALUES IN THE BASE CONFIG FILE. !!! + +Doing so can cause issues with the aircraft and will not be supported by the FlyByWire team. If you need to change a value, please do so in the livery specific config file (when this feature is documented and available). + +Certain unwritable keys are REQUIRED in order for the flyPad and potentially parts of the aircraft to function. These are usually marked with a _ in the base config, but not always. + +Due to how the base configuration files in this folder are read and processed (i.e. ``config///*.json5``), in relation to our GPLv3 license, these VFS based markup configurations are considered an integral part of the aircraft (as the addon cannot function without them) and is therefore part of the GPLv3 license. + +*This means that any changes to the base configuration file must be made available under the same license as per copyleft.* This includes any liveries, plugins, or other modifications that use or override/subsitute specifically the files located in this folder, as they will be linking directly with other boilerplate and middleware which are licensed under GPLv3, *and thus any code which is linked with any modified json5 must also be released under GPLv3*. At this time, this may or may not apply to the livery override files (and has yet to be decided). + +If you are unsure about any of this, please ask on our [discord.](https://discord.gg/flybywire) + +### Current Functionality + +Note: Before v 1.0, also known as the first published version, you can consider this as a "private" and thus mostly undocumented and unreleased feature, mainly here for the +Benefit of code contributors and developers, both working on this feature and in general. + +We will not offer support, warranty or answer help queries based on liveries that have pre-maturely adopted this VFS unified config format structure before this time. + +## v 0.1 + - Basic Configuration for EFB pages (Payload, Ground Services, etc.) + +### Planned Functionality + +## v 0.2 + - Deeper configuration for EFB pages + - Configuration per-livery (initial stage) + +### v 0.3 + - Configuration of EFB graphics (SVGs, etc) + - Further Documentation on the FBW Unified Config format (also into FBW docs format) + +## v 1.x + - Configuration of EFB graphics (SVGs, etc) + - Per-livery config (without overriding default json) + - First published release of the FBW Unified Config + +## Future + - Configuration of physical seating in the cabin model + - Configuration of Persistent Elements (SATCOM) + - Further Documentation on how the FBW Unified Config backend and middleware pipes configuration into both JS/WASM diff --git a/fbw-a32nx/src/base/flybywire-aircraft-a320-neo/config/a32nx/a320-251n/airframe.json5 b/fbw-a32nx/src/base/flybywire-aircraft-a320-neo/config/a32nx/a320-251n/airframe.json5 new file mode 100644 index 00000000000..d51bdf9d677 --- /dev/null +++ b/fbw-a32nx/src/base/flybywire-aircraft-a320-neo/config/a32nx/a320-251n/airframe.json5 @@ -0,0 +1,92 @@ +// Copyright (c) 2024 FlyByWire Simulations +// SPDX-License-Identifier: GPL-3.0 +// ======================================================================================= +// This is the base airframe configuration file for A320-251N +// Any keys prefixed by underscore (_) should be considered read-only and not overwritable. +// +// NOTE: * This is currently a WIP * ! The override functionality has not been completed yet ! +// +// ****** ! WARNING TO LIVERY MAKERS: DO NOT OVERRIDE THIS FILE ! ********** +// ****** ! WARNING TO LIVERY MAKERS: DO NOT OVERRIDE THIS FILE ! ********** +// ****** ! WARNING TO LIVERY MAKERS: DO NOT OVERRIDE THIS FILE ! ********** +// ****** ! WARNING TO LIVERY MAKERS: DO NOT OVERRIDE THIS FILE ! ********** +// +// Please follow the instructions in the documentation to create a new configuration file! +// ======================================================================================= +// Last updated: 2 April 2024 +{ + "configMajorVersion": 0, + "configMinorVersion": 1, + "_variant": "A320-251N", + "_icao": "A20N", + "_name": "Airbus A320neo", + "_engines": "CFM LEAP-1A26", + "_developer": "FBW", + "msnReference": "MSN 9XXX", + "weightVariant": "WV055", + "designLimits": { + "weights": { + "maxGw": 79000, // kg + "maxZfw": 64300, // kg + "minZfw": 42500, // kg + "maxGwCg": 40, // %CG MAC + "maxZfwCg": 40, // %CG MAC + "maxCargo": 9435, // kg + "maxFuel": 23721, // kg + }, + "endurance": { + "range": 3400, // nm + "mmo": "0.82", // mach + }, + "performanceEnvelope": { + "mlw": [ + [ 15, 42500 ], + [ 15, 53000 ], + [ 17, 63000 ], + [ 17, 67400 ], + [ 40, 67400 ], + [ 40, 67400 ], + [ 37, 50000 ], + [ 35, 46000 ], + [ 35, 42500 ] + ], + "mzfw": [ + [ 17, 64300 ], + [ 39.5, 64300 ], + [ 37, 50000 ], + [ 35, 46000 ], + [ 35, 42500 ], + [ 15, 42500 ] + ], + "mtow": [ + [ 15, 42500 ], + [ 15, 53000 ], + [ 17, 63000 ], + [ 17, 72000 ], + [ 27, 79000 ], + [ 36, 79000 ], + [ 40, 73500 ], + [ 40, 67400 ], + [ 37, 50000 ], + [ 33, 42500 ] + ], + "flight": [ + [ 13, 42500 ], + [ 13, 52500 ], + [ 15, 63000 ], + [ 15, 72000 ], + [ 25, 79000 ], + [ 38, 79000 ], + [ 41, 74500 ], + [ 41, 51000 ], + [ 35, 46000 ], + [ 35, 42500 ], + [ 13, 42500 ] + ] + } + }, + "_dimensions": { + "aircraftWheelBase": 12.64, + "aircraftLengthMeter": 37.57 + } +} diff --git a/fbw-common/src/systems/instruments/src/EFB/Ground/Pages/Payload/A320_251N/a20nv55.json b/fbw-a32nx/src/base/flybywire-aircraft-a320-neo/config/a32nx/a320-251n/cabin.json5 similarity index 65% rename from fbw-common/src/systems/instruments/src/EFB/Ground/Pages/Payload/A320_251N/a20nv55.json rename to fbw-a32nx/src/base/flybywire-aircraft-a320-neo/config/a32nx/a320-251n/cabin.json5 index 06241c4633d..7c654630635 100644 --- a/fbw-common/src/systems/instruments/src/EFB/Ground/Pages/Payload/A320_251N/a20nv55.json +++ b/fbw-a32nx/src/base/flybywire-aircraft-a320-neo/config/a32nx/a320-251n/cabin.json5 @@ -1,22 +1,30 @@ +// Copyright (c) 2024 FlyByWire Simulations +// SPDX-License-Identifier: GPL-3.0 +// ======================================================================================= +// This is the base cabin configuration file for A320-251N +// Any keys prefixed by underscore (_) should be considered read-only and not overwritable. +// +// NOTE: * This is currently a WIP * ! The override functionality has not been completed yet ! +// +// ****** ! WARNING TO LIVERY MAKERS: DO NOT OVERRIDE THIS FILE ! ********** +// ****** ! WARNING TO LIVERY MAKERS: DO NOT OVERRIDE THIS FILE ! ********** +// ****** ! WARNING TO LIVERY MAKERS: DO NOT OVERRIDE THIS FILE ! ********** +// ****** ! WARNING TO LIVERY MAKERS: DO NOT OVERRIDE THIS FILE ! ********** +// +// Please follow the instructions in the documentation to create a new configuration file! +// ======================================================================================= +// Last updated: 2 April 2024 { - "specs": { - "prefix": "A32NX", - "weights": { - "maxGw": 79000, - "maxZfw": 64300, - "minZfw": 42500, - "maxGwCg": 40, - "maxZfwCg": 40 - }, - "pax": { - "defaultPaxWeight": 84, - "defaultBagWeight": 20, - "minPaxWeight": 10, - "maxPaxWeight": 250, - "minBagWeight": 1, - "maxBagWeight": 250 - } - }, + "configMajorVersion": 0, + "configMinorVersion": 1, + "defaultPaxWeight": 84, + "defaultBagWeight": 20, + "_paxDecks": 1, + "_decks": 2, + "_minPaxWeight": 10, + "_maxPaxWeight": 250, + "_minBagWeight": 1, + "_maxBagWeight": 250, "seatMap": [ { "name": "ROWS [1-6]", @@ -28,7 +36,7 @@ { "type": 0 }, { "type": 0 }, { "type": 0 }, - { "type": 0, "yOffset": 19}, + { "type": 0, "yOffset": 19}, { "type": 0 }, { "type": 0 } ], @@ -42,7 +50,7 @@ { "type": 0 }, { "type": 0 }, { "type": 0 }, - { "type": 0, "yOffset": 19}, + { "type": 0, "yOffset": 19 }, { "type": 0 }, { "type": 0 } ], @@ -56,7 +64,7 @@ { "type": 0 }, { "type": 0 }, { "type": 0 }, - { "type": 0, "yOffset": 19}, + { "type": 0, "yOffset": 19 }, { "type": 0 }, { "type": 0 } ], @@ -70,7 +78,7 @@ { "type": 0 }, { "type": 0 }, { "type": 0 }, - { "type": 0, "yOffset": 19}, + { "type": 0, "yOffset": 19 }, { "type": 0 }, { "type": 0 } ], @@ -84,7 +92,7 @@ { "type": 0 }, { "type": 0 }, { "type": 0 }, - { "type": 0, "yOffset": 19}, + { "type": 0, "yOffset": 19 }, { "type": 0 }, { "type": 0 } ], @@ -98,7 +106,7 @@ { "type": 0 }, { "type": 0 }, { "type": 0 }, - { "type": 0, "yOffset": 19}, + { "type": 0, "yOffset": 19 }, { "type": 0 }, { "type": 0 } ], @@ -122,7 +130,7 @@ { "type": 0 }, { "type": 0 }, { "type": 0 }, - { "type": 0, "yOffset": 19}, + { "type": 0, "yOffset": 19 }, { "type": 0 }, { "type": 0 } ], @@ -136,7 +144,7 @@ { "type": 0 }, { "type": 0 }, { "type": 0 }, - { "type": 0, "yOffset": 19}, + { "type": 0, "yOffset": 19 }, { "type": 0 }, { "type": 0 } ], @@ -150,7 +158,7 @@ { "type": 0 }, { "type": 0 }, { "type": 0 }, - { "type": 0, "yOffset": 19}, + { "type": 0, "yOffset": 19 }, { "type": 0 }, { "type": 0 } ], @@ -164,7 +172,7 @@ { "type": 0 }, { "type": 0 }, { "type": 0 }, - { "type": 0, "yOffset": 19}, + { "type": 0, "yOffset": 19 }, { "type": 0 }, { "type": 0 } ], @@ -178,7 +186,7 @@ { "type": 0 }, { "type": 0 }, { "type": 0 }, - { "type": 0, "yOffset": 19}, + { "type": 0, "yOffset": 19 }, { "type": 0 }, { "type": 0 } ], @@ -189,12 +197,12 @@ }, { "seats": [ - { "type": 1 }, - { "type": 1 }, - { "type": 1 }, - { "type": 1, "yOffset": 19 }, - { "type": 1 }, - { "type": 1 } + { "type": 1}, + { "type": 1}, + { "type": 1}, + { "type": 1, "yOffset": 19}, + { "type": 1}, + { "type": 1} ], "x": 0, "y": 0, @@ -203,12 +211,12 @@ }, { "seats": [ - { "type": 1 }, - { "type": 1 }, - { "type": 1 }, - { "type": 1, "yOffset": 19 }, - { "type": 1 }, - { "type": 1 } + { "type": 1}, + { "type": 1}, + { "type": 1}, + { "type": 1, "yOffset": 19}, + { "type": 1}, + { "type": 1} ], "x": 0, "y": 0, @@ -230,7 +238,7 @@ { "type": 0 }, { "type": 0 }, { "type": 0 }, - { "type": 0, "yOffset": 19}, + { "type": 0, "yOffset": 19 }, { "type": 0 }, { "type": 0 } ], @@ -244,7 +252,7 @@ { "type": 0 }, { "type": 0 }, { "type": 0 }, - { "type": 0, "yOffset": 19}, + { "type": 0, "yOffset": 19 }, { "type": 0 }, { "type": 0 } ], @@ -258,7 +266,7 @@ { "type": 0 }, { "type": 0 }, { "type": 0 }, - { "type": 0, "yOffset": 19}, + { "type": 0, "yOffset": 19 }, { "type": 0 }, { "type": 0 } ], @@ -272,7 +280,7 @@ { "type": 0 }, { "type": 0 }, { "type": 0 }, - { "type": 0, "yOffset": 19}, + { "type": 0, "yOffset": 19 }, { "type": 0 }, { "type": 0 } ], @@ -286,7 +294,7 @@ { "type": 0 }, { "type": 0 }, { "type": 0 }, - { "type": 0, "yOffset": 19}, + { "type": 0, "yOffset": 19 }, { "type": 0 }, { "type": 0 } ], @@ -300,7 +308,7 @@ { "type": 0 }, { "type": 0 }, { "type": 0 }, - { "type": 0, "yOffset": 19}, + { "type": 0, "yOffset": 19 }, { "type": 0 }, { "type": 0 } ], @@ -314,7 +322,7 @@ { "type": 0 }, { "type": 0 }, { "type": 0 }, - { "type": 0, "yOffset": 19}, + { "type": 0, "yOffset": 19 }, { "type": 0 }, { "type": 0 } ], @@ -328,7 +336,7 @@ { "type": 0 }, { "type": 0 }, { "type": 0 }, - { "type": 0, "yOffset": 19}, + { "type": 0, "yOffset": 19 }, { "type": 0 }, { "type": 0 } ], @@ -352,7 +360,7 @@ { "type": 0 }, { "type": 0 }, { "type": 0 }, - { "type": 0, "yOffset": 19}, + { "type": 0, "yOffset": 19 }, { "type": 0 }, { "type": 0 } ], @@ -366,7 +374,7 @@ { "type": 0 }, { "type": 0 }, { "type": 0 }, - { "type": 0, "yOffset": 19}, + { "type": 0, "yOffset": 19 }, { "type": 0 }, { "type": 0 } ], @@ -380,7 +388,7 @@ { "type": 0 }, { "type": 0 }, { "type": 0 }, - { "type": 0, "yOffset": 19}, + { "type": 0, "yOffset": 19 }, { "type": 0 }, { "type": 0 } ], @@ -394,7 +402,7 @@ { "type": 0 }, { "type": 0 }, { "type": 0 }, - { "type": 0, "yOffset": 19}, + { "type": 0, "yOffset": 19 }, { "type": 0 }, { "type": 0 } ], @@ -408,7 +416,7 @@ { "type": 0 }, { "type": 0 }, { "type": 0 }, - { "type": 0, "yOffset": 19}, + { "type": 0, "yOffset": 19 }, { "type": 0 }, { "type": 0 } ], @@ -422,7 +430,7 @@ { "type": 0 }, { "type": 0 }, { "type": 0 }, - { "type": 0, "yOffset": 19}, + { "type": 0, "yOffset": 19 }, { "type": 0 }, { "type": 0 } ], @@ -436,7 +444,7 @@ { "type": 0 }, { "type": 0 }, { "type": 0 }, - { "type": 0, "yOffset": 19}, + { "type": 0, "yOffset": 19 }, { "type": 0 }, { "type": 0 } ], @@ -450,7 +458,7 @@ { "type": 0 }, { "type": 0 }, { "type": 0 }, - { "type": 0, "yOffset": 19}, + { "type": 0, "yOffset": 19 }, { "type": 0 }, { "type": 0 } ], @@ -498,210 +506,5 @@ "progressBarWidth": 75, "simVar": "A32NX_CARGO_AFT_BULK_LOOSE" } - ], - "chart": { - "performanceEnvelope": { - "mlw": [ - [ - 15, - 42500 - ], - [ - 15, - 53000 - ], - [ - 17, - 63000 - ], - [ - 17, - 67400 - ], - [ - 40, - 67400 - ], - [ - 40, - 67400 - ], - [ - 37, - 50000 - ], - [ - 35, - 46000 - ], - [ - 35, - 42500 - ] - ], - "mzfw": [ - [ - 17, - 64300 - ], - [ - 39.5, - 64300 - ], - [ - 37, - 50000 - ], - [ - 35, - 46000 - ], - [ - 35, - 42500 - ], - [ - 15, - 42500 - ] - ], - "mtow": [ - [ - 15, - 42500 - ], - [ - 15, - 53000 - ], - [ - 17, - 63000 - ], - [ - 17, - 72000 - ], - [ - 27, - 79000 - ], - [ - 36, - 79000 - ], - [ - 40, - 73500 - ], - [ - 40, - 67400 - ], - [ - 37, - 50000 - ], - [ - 33, - 42500 - ] - ], - "flight": [ - [ - 13, - 42500 - ], - [ - 13, - 52500 - ], - [ - 15, - 63000 - ], - [ - 15, - 72000 - ], - [ - 25, - 79000 - ], - [ - 38, - 79000 - ], - [ - 41, - 74500 - ], - [ - 41, - 51000 - ], - [ - 35, - 46000 - ], - [ - 35, - 42500 - ], - [ - 13, - 42500 - ] - ] - }, - "chartLimits": { - "weight": { - "min": 35000, - "max": 80000, - "lines": 9, - "scale": 5000, - "values": [ - 80, - 70, - 60, - 50, - 40 - ] - }, - "cg": { - "angleRad": 0.014025, - "min": 12, - "max": 47, - "overlap": 32, - "highlight": 5, - "lines": 35, - "scale": 1, - "values": [ - 15, - 20, - 25, - 30, - 35, - 40 - ] - }, - "labels": { - "mtow": { - "x1": 0.65, - "x2": 0.22, - "y": 0.02 - }, - "mlw": { - "x1": 0.65, - "x2": 0.22, - "y": 0.22 - }, - "mzfw": { - "x1": 0.65, - "x2": 0.22, - "y": 0.29 - } - } - } - } + ] } diff --git a/fbw-a32nx/src/base/flybywire-aircraft-a320-neo/config/a32nx_checklists.json5 b/fbw-a32nx/src/base/flybywire-aircraft-a320-neo/config/a32nx/a320-251n/checklists.json5 similarity index 100% rename from fbw-a32nx/src/base/flybywire-aircraft-a320-neo/config/a32nx_checklists.json5 rename to fbw-a32nx/src/base/flybywire-aircraft-a320-neo/config/a32nx/a320-251n/checklists.json5 diff --git a/fbw-a32nx/src/base/flybywire-aircraft-a320-neo/config/a32nx/a320-251n/flypad-misc.json5 b/fbw-a32nx/src/base/flybywire-aircraft-a320-neo/config/a32nx/a320-251n/flypad-misc.json5 new file mode 100644 index 00000000000..7710ecb7922 --- /dev/null +++ b/fbw-a32nx/src/base/flybywire-aircraft-a320-neo/config/a32nx/a320-251n/flypad-misc.json5 @@ -0,0 +1,34 @@ +// Copyright (c) 2024 FlyByWire Simulations +// SPDX-License-Identifier: GPL-3.0 +// ======================================================================================= +// This is part of the base flyPad configuration file for A320-251N +// Any keys prefixed by underscore (_) should be considered read-only and not overwritable. +// +// NOTE: * This is currently a WIP * ! The override functionality has not been completed yet ! +// +// ****** ! WARNING TO LIVERY MAKERS: DO NOT OVERRIDE THIS FILE ! ********** +// ****** ! WARNING TO LIVERY MAKERS: DO NOT OVERRIDE THIS FILE ! ********** +// ****** ! WARNING TO LIVERY MAKERS: DO NOT OVERRIDE THIS FILE ! ********** +// ****** ! WARNING TO LIVERY MAKERS: DO NOT OVERRIDE THIS FILE ! ********** +// +// Please follow the instructions in the documentation to create a new configuration file! +// ======================================================================================= +// Last updated: 2 April 2024 +{ + "configMajorVersion": 0, + "configMinorVersion": 1, + "_throttle": { + "numberOfAxis": 2, + "axisOptions": [ + 1, + 2 + ], + "axisMapping": [ + [[1, 2]], // 1 + [[1], [2]], // 2 + ] + }, + "_pushback": { + "turnIndicatorTuningDefault": 1.35, // determined by testing + } +} diff --git a/fbw-a32nx/src/base/flybywire-aircraft-a320-neo/config/a32nx/a320-251n/flypad-payload.json5 b/fbw-a32nx/src/base/flybywire-aircraft-a320-neo/config/a32nx/a320-251n/flypad-payload.json5 new file mode 100644 index 00000000000..6aa4b53b189 --- /dev/null +++ b/fbw-a32nx/src/base/flybywire-aircraft-a320-neo/config/a32nx/a320-251n/flypad-payload.json5 @@ -0,0 +1,133 @@ +// Copyright (c) 2024 FlyByWire Simulations +// SPDX-License-Identifier: GPL-3.0 +// ======================================================================================= +// This is part of the base flyPad configuration file for A320-251N +// Any keys prefixed by underscore (_) should be considered read-only and not overwritable. +// +// NOTE: * This is currently a WIP * ! The override functionality has not been completed yet ! +// +// ****** ! WARNING TO LIVERY MAKERS: DO NOT OVERRIDE THIS FILE ! ********** +// ****** ! WARNING TO LIVERY MAKERS: DO NOT OVERRIDE THIS FILE ! ********** +// ****** ! WARNING TO LIVERY MAKERS: DO NOT OVERRIDE THIS FILE ! ********** +// ****** ! WARNING TO LIVERY MAKERS: DO NOT OVERRIDE THIS FILE ! ********** +// +// Please follow the instructions in the documentation to create a new configuration file! +// ======================================================================================= +// Last updated: 2 April 2024 +{ + "configMajorVersion": 0, + "configMinorVersion": 1, + "_canvas": { + "width": 1000, + "height": 150, + "canvasX": 243, + "canvasY": 78 + }, + "chartLimits": { + "weight": { + "min": 35000, + "max": 80000, + "lines": 9, + "scale": 5000, + "values": [ 80, 70, 60, 50, 40] + }, + "cg": { + "angleRad": 0.014025, + "min": 12, + "max": 47, + "overlap": 32, + "highlight": 5, + "lines": 35, + "scale": 1, + "values": [ 15, 20, 25, 30, 35, 40 ] + }, + "labels": { + "mtow": { "x1": 0.65, "x2": 0.22, "y": 0.02}, + "mlw": { "x1": 0.65, "x2": 0.22, "y": 0.22}, + "mzfw": { "x1": 0.65, "x2": 0.22, "y": 0.29} + } + }, + "seatDisplay": [ + { + // NarrowbodyEconomy + len: 25.4, + wid: 19.2, + padX: 6.8, + padY: 0, + imageX: 25.4, + imageY: 19.2, + }, + { + // NarrowbodyEconomyEmergency + len: 25.4, + wid: 19.2, + padX: 13.8, + padY: 0, + imageX: 25.4, + imageY: 19.2, + }, + { + // WidebodyEconomy + len: 16, + wid: 12.125, + padX: 2, + padY: 0, + imageX: 16, + imageY: 12.125, + }, + { + // WidebodyEconomyEmergency + len: 16, + wid: 12.125, + padX: 2, + padY: 0, + imageX: 16, + imageY: 12.125, + }, + { + // WidebodyBusinessFlatRight + len: 24, + wid: 23.22, + padX: 1, + padY: 0, + imageX: 24, + imageY: 23.22, + }, + { + // WidebodyBusinessFlatLeft + len: 24, + wid: 23.22, + padX: 1, + padY: 0, + imageX: 24, + imageY: 23.22, + }, + { + // WidebodySuiteRight + len: 35, + wid: 20, + padX: 2, + padY: 0, + imageX: 50, + imageY: 50, + }, + { + // WidebodySuiteLeft + len: 35, + wid: 20, + padX: 5, + padY: 0, + imageX: 50, + imageY: 50, + }, + { + // WidebodyPremiumEconomy + len: 18, + wid: 13.64, + padX: 2, + padY: 0, + imageX: 18, + imageY: 13.64, + } + ] +} diff --git a/fbw-a32nx/src/systems/extras-host/index.ts b/fbw-a32nx/src/systems/extras-host/index.ts index 7eb48aa10c3..2acc3bc385e 100644 --- a/fbw-a32nx/src/systems/extras-host/index.ts +++ b/fbw-a32nx/src/systems/extras-host/index.ts @@ -7,6 +7,7 @@ import { ExtrasSimVarPublisher } from 'extras-host/modules/common/ExtrasSimVarPu import { PushbuttonCheck } from 'extras-host/modules/pushbutton_check/PushbuttonCheck'; import { KeyInterceptor } from './modules/key_interceptor/KeyInterceptor'; import { VersionCheck } from './modules/version_check/VersionCheck'; +import { AircraftSync } from './modules/aircraft_sync/AircraftSync'; /** * This is the main class for the extras-host instrument. @@ -40,6 +41,10 @@ class ExtrasHost extends BaseInstrument { private readonly keyInterceptor: KeyInterceptor; + private readonly aircraftSync: AircraftSync; + + public readonly xmlConfig: Document; + /** * "mainmenu" = 0 * "loading" = 1 @@ -58,8 +63,9 @@ class ExtrasHost extends BaseInstrument { this.notificationManager = new NotificationManager(); this.pushbuttonCheck = new PushbuttonCheck(this.bus, this.notificationManager); - this.versionCheck = new VersionCheck(this.bus); this.keyInterceptor = new KeyInterceptor(this.bus, this.notificationManager); + this.versionCheck = new VersionCheck(process.env.AIRCRAFT_PROJECT_PREFIX, this.bus); + this.aircraftSync = new AircraftSync(process.env.AIRCRAFT_PROJECT_PREFIX, this.bus); console.log('A32NX_EXTRASHOST: Created'); } @@ -82,6 +88,12 @@ class ExtrasHost extends BaseInstrument { this.pushbuttonCheck.connectedCallback(); this.versionCheck.connectedCallback(); this.keyInterceptor.connectedCallback(); + this.aircraftSync.connectedCallback(); + } + + public parseXMLConfig(): void { + super.parseXMLConfig(); + this.aircraftSync.parseXMLConfig(this.xmlConfig); } public Update(): void { @@ -94,6 +106,7 @@ class ExtrasHost extends BaseInstrument { this.versionCheck.startPublish(); this.keyInterceptor.startPublish(); this.simVarPublisher.startPublish(); + this.aircraftSync.startPublish(); } this.gameState = gs; } else { @@ -102,6 +115,7 @@ class ExtrasHost extends BaseInstrument { this.versionCheck.update(); this.keyInterceptor.update(); + this.aircraftSync.update(); } } diff --git a/fbw-a32nx/src/systems/extras-host/modules/aircraft_sync/AircraftSync.ts b/fbw-a32nx/src/systems/extras-host/modules/aircraft_sync/AircraftSync.ts new file mode 100644 index 00000000000..1c0234bae0b --- /dev/null +++ b/fbw-a32nx/src/systems/extras-host/modules/aircraft_sync/AircraftSync.ts @@ -0,0 +1,40 @@ +// Copyright (c) 2022 FlyByWire Simulations +// SPDX-License-Identifier: GPL-3.0 + +import { UniversalConfigProvider } from '@flybywiresim/fbw-sdk'; +import { EventBus } from '@microsoft/msfs-sdk'; + +/** + * This class is used to check the airframe of the aircraft and set the LVar + */ +export class AircraftSync { + public xmlConfig: Document + + constructor(private readonly aircraftProjectPrefix: string, private readonly bus: EventBus) { + console.log('AircraftSync: Created'); + } + + public connectedCallback(): void { + // empty + } + + public parseXMLConfig(xmlConfig: Document): void { + this.xmlConfig = xmlConfig; + } + + // TODO: Replace with new function for commbus implementation to sync VFS markup config to WASM + public startPublish(): void { + console.log('AicraftSync: startPublish()'); + + UniversalConfigProvider.initialize( + process.env.AIRCRAFT_PROJECT_PREFIX, + process.env.AIRCRAFT_VARIANT, + ); + + // TODO: Future WASM commbus subscriber goes here + } + + public update(): void { + // empty + } +} diff --git a/fbw-a32nx/src/systems/extras-host/modules/version_check/VersionCheck.ts b/fbw-a32nx/src/systems/extras-host/modules/version_check/VersionCheck.ts index baa68ffe25f..1450c0abed1 100644 --- a/fbw-a32nx/src/systems/extras-host/modules/version_check/VersionCheck.ts +++ b/fbw-a32nx/src/systems/extras-host/modules/version_check/VersionCheck.ts @@ -2,13 +2,13 @@ // SPDX-License-Identifier: GPL-3.0 import { EventBus } from '@microsoft/msfs-sdk'; -import { AircraftVersionChecker } from '@fbw-common/shared/AircraftVersionChecker'; +import { AircraftGithubVersionChecker } from '@fbw-common/shared/AircraftGithubVersionChecker'; /** * This class is used to check the version of the aircraft and display a warning if it is too old. */ export class VersionCheck { - constructor(private readonly bus: EventBus) { + constructor(private readonly aircraftProjectPrefix: string, private readonly bus: EventBus) { console.log('VersionCheck: Created'); } @@ -18,7 +18,7 @@ export class VersionCheck { public startPublish(): void { console.log('VersionCheck: startPublish()'); - AircraftVersionChecker.checkVersion('a32nx'); + AircraftGithubVersionChecker.checkVersion(this.aircraftProjectPrefix); } public update(): void { diff --git a/fbw-a32nx/src/systems/instruments/buildSrc/plugins.mjs b/fbw-a32nx/src/systems/instruments/buildSrc/plugins.mjs index 3d57c9680cb..a3dcaa8bee8 100644 --- a/fbw-a32nx/src/systems/instruments/buildSrc/plugins.mjs +++ b/fbw-a32nx/src/systems/instruments/buildSrc/plugins.mjs @@ -79,6 +79,8 @@ export function baseCompile(instrumentName, instrumentFolder) { 'process.env.CLIENT_SECRET': JSON.stringify(process.env.CLIENT_SECRET), 'process.env.CHARTFOX_SECRET': JSON.stringify(process.env.CHARTFOX_SECRET), 'process.env.SENTRY_DSN': JSON.stringify(process.env.SENTRY_DSN), + 'process.env.AIRCRAFT_PROJECT_PREFIX': JSON.stringify(process.env.AIRCRAFT_PROJECT_PREFIX), + 'process.env.AIRCRAFT_VARIANT': JSON.stringify(process.env.AIRCRAFT_VARIANT), }), postCss(instrumentName, instrumentFolder), ]; diff --git a/fbw-a32nx/src/systems/instruments/src/Common/index.tsx b/fbw-a32nx/src/systems/instruments/src/Common/index.tsx index 234a0ecb464..e0ae9d30229 100644 --- a/fbw-a32nx/src/systems/instruments/src/Common/index.tsx +++ b/fbw-a32nx/src/systems/instruments/src/Common/index.tsx @@ -15,7 +15,7 @@ export const render = (Slot: React.ReactElement, enableSentryTracing = false, se const doRender = () => { new FbwAircraftSentryClient().onInstrumentLoaded({ dsn: process.env.SENTRY_DSN, - buildInfoFilePrefix: 'a32nx', + buildInfoFilePrefix: process.env.AIRCRAFT_PROJECT_PREFIX, enableTracing: enableSentryTracing, root: sentryRootClient, }); diff --git a/fbw-a32nx/src/systems/instruments/src/EFB/index.tsx b/fbw-a32nx/src/systems/instruments/src/EFB/index.tsx index 3ef0ac54b69..3a31182e759 100644 --- a/fbw-a32nx/src/systems/instruments/src/EFB/index.tsx +++ b/fbw-a32nx/src/systems/instruments/src/EFB/index.tsx @@ -2,50 +2,14 @@ // SPDX-License-Identifier: GPL-3.0 import React from 'react'; -import { ChecklistProvider, NXDataStore } from '@flybywiresim/fbw-sdk'; -import { customAlphabet } from 'nanoid'; import { render } from '@instruments/common/index'; -import { readSettingsFromPersistentStorage, migrateSettings, EfbInstrument } from '@flybywiresim/flypad'; +import { EfbWrapper } from '@flybywiresim/flypad'; import { A320FailureDefinitions } from '@failures'; -// TODO move all of this to fbw-common somehow - -const setSessionId = () => { - const ALPHABET = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'; - const SESSION_ID_LENGTH = 14; - const nanoid = customAlphabet(ALPHABET, SESSION_ID_LENGTH); - const generatedSessionID = nanoid(); - - NXDataStore.set('A32NX_SENTRY_SESSION_ID', generatedSessionID); -}; - -const setup = () => { - readSettingsFromPersistentStorage(); - migrateSettings(); - setSessionId(); - - // Needed to fetch METARs from the sim - RegisterViewListener('JS_LISTENER_FACILITY', () => { - console.log('JS_LISTENER_FACILITY registered.'); - }, true); -}; - -if (process.env.VITE_BUILD) { - window.addEventListener('AceInitialized', setup); -} else { - setup(); -} - -ChecklistProvider.getInstance().readChecklist() - .then((aircraftChecklistsFromJson) => { - console.log('Checklists loaded'); - render( - , - true, - true, - ); - }) - .catch((error) => { - console.error('Failed to load checklists', error); - }); +// TODO: Move failure definition into VFS +render( + , + true, + true, +); diff --git a/fbw-a32nx/src/systems/sentry-client/src/index.ts b/fbw-a32nx/src/systems/sentry-client/src/index.ts index b721968a9e9..e3ac35d7ed8 100644 --- a/fbw-a32nx/src/systems/sentry-client/src/index.ts +++ b/fbw-a32nx/src/systems/sentry-client/src/index.ts @@ -8,7 +8,7 @@ declare const process: any; new FbwAircraftSentryClient().onInstrumentLoaded({ dsn: process.env.SENTRY_DSN, - buildInfoFilePrefix: 'a32nx', + buildInfoFilePrefix: process.env.AIRCRAFT_PROJECT_PREFIX, root: false, enableTracing: false, }); diff --git a/fbw-a380x/.env b/fbw-a380x/.env index c7304412e55..18d5c1b5502 100644 --- a/fbw-a380x/.env +++ b/fbw-a380x/.env @@ -3,3 +3,5 @@ NODE_ENV=production CLIENT_SECRET="" CLIENT_ID="" SENTRY_DSN="" +AIRCRAFT_PROJECT_PREFIX="a380x" +AIRCRAFT_VARIANT="a380-842" diff --git a/fbw-a380x/src/base/flybywire-aircraft-a380-842/SimObjects/AirPlanes/FlyByWire_A380_842/panel/panel.cfg b/fbw-a380x/src/base/flybywire-aircraft-a380-842/SimObjects/AirPlanes/FlyByWire_A380_842/panel/panel.cfg index 0a1953fa006..17926360789 100644 --- a/fbw-a380x/src/base/flybywire-aircraft-a380-842/SimObjects/AirPlanes/FlyByWire_A380_842/panel/panel.cfg +++ b/fbw-a380x/src/base/flybywire-aircraft-a380-842/SimObjects/AirPlanes/FlyByWire_A380_842/panel/panel.cfg @@ -120,7 +120,7 @@ size_mm=1430,1000 pixel_size=1430,1000 texture=$SCREEN_EFB -htmlgauge00=A380X/EFB/efb.html?Airframe=A380_842, 0,0,1430,1000 +htmlgauge00=A380X/EFB/efb.html, 0,0,1430,1000 [VCockpit16] size_mm=1664,1024 @@ -168,4 +168,4 @@ pixel_size=0,0 texture=NO_TEXTURE background_color=0,0,0 -htmlgauge04=A380X/ExtrasHost/extras-host.html,0,0,1,1 +htmlgauge04=A380X/ExtrasHost/extras-host.html diff --git a/fbw-a380x/src/base/flybywire-aircraft-a380-842/config/a380x/a380-842/README.md b/fbw-a380x/src/base/flybywire-aircraft-a380-842/config/a380x/a380-842/README.md new file mode 100644 index 00000000000..540b0e6f997 --- /dev/null +++ b/fbw-a380x/src/base/flybywire-aircraft-a380-842/config/a380x/a380-842/README.md @@ -0,0 +1,85 @@ +# FlyByWire Unified Config + +!!!!!!!!!!!! + +Note: This is a work in progress, consider this a developer-only preview, treat this as a private API and integrate with the current format and values at your own risk. Format at this stage can and will change suddenly without notice, warranty or support provided. Thank you for your cooperation, patience and understanding. + + +At this stage, if you have any suggestions, input or inquiries in regards to the structure/function of the config ``.json5`` files, +then please contact the FlyByWire core development team on [discord](https://discord.gg/flybywire). + +!!!!!!!!!!!!! + +The goal of this effort is to unify configuration for all FBW based projects, in a way that can be piped to both JS (completed) and WASM Gauges (pending), +and in doing so, exposing these variables for both easier visibility for contributors as well as aiding external parties in adapting the +flyPad and other components to other aircraft. + +Currently, there is config and hardcoded values spreadout across the project repository, sometimes in various configuration (.json, .h, .toml, etc.) files. + +The solution to this takes on (at the moment) the form of a VFS stored ``.json5`` markup files in ``config///*.json5`` that has a format that currently is being decided and iterated upon. + +This will (eventually) allow for deep, per-livery/tail number configuration i.e. dynamic passenger seating configurations and cargo loading by providing an override file (based on ATC ID/tailnumber), + +i.e. ``///*.json5`` + +This consists of several components and will be expanded upon in stages to facilitate and aid our code review and refactoring processes. + +**Note:** From this point, any configuration that exists in panel.xml and elsewhere that is left hardcoded should be considered to be left *NOT exposed on purpose*. +Please consult with our core development team before adding more configuration and hardcoded values into the ``config.json5`` markup. + +Please do NOT add any new configuration to the panel.xml or other configuration files that are not already present in the unified config. +Please do NOT add any new configuration to the panel.cfg or other configuration files that are not already present in the unified config. +Please do NOT move any more configuration or hardcoded values from FlyByWire header files, or other json or markup in the unified config. + +Please do NOT draft PRs or add configuration to the unified config, or any of its associated boilerplate and middleware, without first consulting with the core development team. + +Please do NOT hesitate to ask questions or seek clarification on the FlyByWire [discord](https://discord.gg/flybywire) server, we are here to help! + +**IMPORTANT** + +The base configuration location is in ``config///*.json5`` + +!!! DO NOT OVERWRITE, ADD, OR MODIFY ANY KEYS OR VALUES IN THE BASE CONFIG FILE. !!! +!!! DO NOT OVERWRITE, ADD, OR MODIFY ANY KEYS OR VALUES IN THE BASE CONFIG FILE. !!! +!!! DO NOT OVERWRITE, ADD, OR MODIFY ANY KEYS OR VALUES IN THE BASE CONFIG FILE. !!! +!!! DO NOT OVERWRITE, ADD, OR MODIFY ANY KEYS OR VALUES IN THE BASE CONFIG FILE. !!! + +Doing so can cause issues with the aircraft and will not be supported by the FlyByWire team. If you need to change a value, please do so in the livery specific config file (when this feature is documented and available). + +Certain unwritable keys are REQUIRED in order for the flyPad and potentially parts of the aircraft to function. These are usually marked with a _ in the base config, but not always. + +Due to how the base configuration files in this folder are read and processed (i.e. ``config///*.json5``), in relation to our GPLv3 license, these VFS based markup configurations are considered an integral part of the aircraft (as the addon cannot function without them) and is therefore part of the GPLv3 license. + +*This means that any changes to the base configuration file must be made available under the same license as per copyleft.* This includes any liveries, plugins, or other modifications that use or override/subsitute specifically the files located in this folder, as they will be linking directly with other boilerplate and middleware which are licensed under GPLv3, *and thus any code which is linked with any modified json5 must also be released under GPLv3*. At this time, this may or may not apply to the livery override files (and has yet to be decided). + +If you are unsure about any of this, please ask on our [discord.](https://discord.gg/flybywire) + +### Current Functionality + +Note: Before v 1.0, also known as the first published version, you can consider this as a "private" and thus mostly undocumented and unreleased feature, mainly here for the +Benefit of code contributors and developers, both working on this feature and in general. + +We will not offer support, warranty or answer help queries based on liveries that have pre-maturely adopted this VFS unified config format structure before this time. + +## v 0.1 + - Basic Configuration for EFB pages (Payload, Ground Services, etc.) + +### Planned Functionality + +## v 0.2 + - Deeper configuration for EFB pages + - Configuration per-livery (initial stage) + +### v 0.3 + - Configuration of EFB graphics (SVGs, etc) + - Further Documentation on the FBW Unified Config format (also into FBW docs format) + +## v 1.x + - Configuration of EFB graphics (SVGs, etc) + - Per-livery config (without overriding default json) + - First published release of the FBW Unified Config + +## Future + - Configuration of physical seating in the cabin model + - Configuration of Persistent Elements (SATCOM) + - Further Documentation on how the FBW Unified Config backend and middleware pipes configuration into both JS/WASM diff --git a/fbw-a380x/src/base/flybywire-aircraft-a380-842/config/a380x/a380-842/airframe.json5 b/fbw-a380x/src/base/flybywire-aircraft-a380-842/config/a380x/a380-842/airframe.json5 new file mode 100644 index 00000000000..5f4fee18a20 --- /dev/null +++ b/fbw-a380x/src/base/flybywire-aircraft-a380-842/config/a380x/a380-842/airframe.json5 @@ -0,0 +1,80 @@ +// Copyright (c) 2024 FlyByWire Simulations +// SPDX-License-Identifier: GPL-3.0 +// ======================================================================================= +// This is the base airframe configuration file for A380-842 +// Any keys prefixed by underscore (_) should be considered read-only and not overwritable. +// +// NOTE: * This is currently a WIP * ! The override functionality has not been completed yet ! +// +// ****** ! WARNING TO LIVERY MAKERS: DO NOT OVERRIDE THIS FILE ! ********** +// ****** ! WARNING TO LIVERY MAKERS: DO NOT OVERRIDE THIS FILE ! ********** +// ****** ! WARNING TO LIVERY MAKERS: DO NOT OVERRIDE THIS FILE ! ********** +// ****** ! WARNING TO LIVERY MAKERS: DO NOT OVERRIDE THIS FILE ! ********** +// +// Please follow the instructions in the documentation to create a new configuration file! +// ======================================================================================= +// Last updated: 2 April 2024 +{ + "configMajorVersion": 0, + "configMinorVersion": 1, + "_variant": "A380-842", + "_icao": "A388", + "_name": "Airbus A380", + "_engines": "RR Trent 972B-84", + "_developer": "FBW", + "msnReference": "MSN 225", + "weightVariant": "WV003", + "designLimits": { + "weights": { + "maxGw": 512000, // kg + "maxZfw": 373000, // kg + "minZfw": 300007, // kg + "maxGwCg": 43, // %CG MAC + "maxZfwCg": 43, // %CG MAC + "maxCargo": 51400, // kg + "maxFuel": 323546, // kg + }, + "endurance": { + "range": 8000, // nm + "mmo": "0.89", // mach + }, + "performanceEnvelope": { + "mlw": [ + [ 29, 270000 ], + [ 29, 375000 ], + [ 29.75, 385000 ], + [ 31.5, 395000 ], + [ 43, 395000 ], + [ 43, 270000 ] + ], + "mzfw": [ + [ 29, 270000 ], + [ 29, 360000 ], + [ 31.5, 365000 ], + [ 43, 365000 ], + [ 43, 270000 ], + [ 29, 270000 ] + ], + "mtow": [ + [ 29, 270000 ], + [ 29, 375000 ], + [ 35.75, 510000 ], + [ 43, 510000 ], + [ 43, 270000 ] + ], + "flight": [ + [ 29, 270000 ], + [ 28, 270000 ], + [ 28, 375000 ], + [ 35, 510000 ], + [ 44, 510000 ], + [ 44, 270000 ], + [ 43, 270000 ] + ] + } + }, + "_dimensions": { + "aircraftWheelBase": 31.9, + "aircraftLengthMeter": 72.72 + } +} diff --git a/fbw-a380x/src/base/flybywire-aircraft-a380-842/config/a380x/a380-842/cabin.json5 b/fbw-a380x/src/base/flybywire-aircraft-a380-842/config/a380x/a380-842/cabin.json5 new file mode 100644 index 00000000000..c9baa84fb03 --- /dev/null +++ b/fbw-a380x/src/base/flybywire-aircraft-a380-842/config/a380x/a380-842/cabin.json5 @@ -0,0 +1,1301 @@ +// Copyright (c) 2024 FlyByWire Simulations +// SPDX-License-Identifier: GPL-3.0 +// ======================================================================================= +// This is the base cabin configuration file for A380-842 +// Any keys prefixed by underscore (_) should be considered read-only and not overwritable. +// +// NOTE: * This is currently a WIP * ! The override functionality has not been completed yet ! +// +// ****** ! WARNING TO LIVERY MAKERS: DO NOT OVERRIDE THIS FILE ! ********** +// ****** ! WARNING TO LIVERY MAKERS: DO NOT OVERRIDE THIS FILE ! ********** +// ****** ! WARNING TO LIVERY MAKERS: DO NOT OVERRIDE THIS FILE ! ********** +// ****** ! WARNING TO LIVERY MAKERS: DO NOT OVERRIDE THIS FILE ! ********** +// +// Please follow the instructions in the documentation to create a new configuration file! +// ======================================================================================= +// Last updated: 2 April 2024 +{ + "configMajorVersion": 0, + "configMinorVersion": 1, + "defaultPaxWeight": 84, + "defaultBagWeight": 20, + "_paxDecks": 2, + "_decks": 3, + "_minPaxWeight": 10, + "_maxPaxWeight": 250, + "_minBagWeight": 1, + "_maxBagWeight": 250, + "seatMap": [ + { + "name": "MAIN FWD A", + "deck": 0, + "capacity": 28, + "rows": [ + { + "seats": [ + { "type": 8, "yOffset": 3.5 }, + { "type": 8 }, + { "type": 8, "yOffset": 77.02 }, + { "type": 8 } + ], + "x": 0, + "y": 0, + "xOffset": 18, + "yOffset": 0 + }, + { + "seats": [ + { "type": 8, "yOffset": 1.5 }, + { "type": 8 }, + { "type": 8, "yOffset": 81.02 }, + { "type": 8 } + ], + "x": 0, + "y": 0, + "xOffset": 0, + "yOffset": 0 + }, + { + "seats": [ + { "type": 8 }, + { "type": 8 }, + { "type": 8, "yOffset": 84.02 }, + { "type": 8 } + ], + "x": 0, + "y": 0, + "xOffset": 0, + "yOffset": 0 + }, + { + "seats": [ + { "type": 8 }, + { "type": 8 }, + { "type": 8, "yOffset": 14.73 }, + { "type": 8 }, + { "type": 8 }, + { "type": 8 }, + { "type": 8, "yOffset": 14.73 }, + { "type": 8 } + ], + "x": 0, + "y": 0, + "xOffset": 0, + "yOffset": 0 + }, + { + "seats": [ + { "type": 8 }, + { "type": 8 }, + { "type": 8, "yOffset": 14.73 }, + { "type": 8 }, + { "type": 8 }, + { "type": 8 }, + { "type": 8, "yOffset": 14.73 }, + { "type": 8 } + ], + "x": 0, + "y": 0, + "xOffset": 0, + "yOffset": 0 + } + ], + "stationIndex": 1, + "position": 70.7, + "simVar": "A32NX_PAX_MAIN_FWD_A" + }, + { + "name": "MAIN FWD B", + "deck": 0, + "capacity": 28, + "rows": [ + { + "seats": [ + { "type": 8 }, + { "type": 8 }, + { "type": 8, "yOffset": 14.73 }, + { "type": 8 }, + { "type": 8 }, + { "type": 8 }, + { "type": 8, "yOffset": 14.73 }, + { "type": 8 } + ], + "x": 0, + "y": 0, + "xOffset": 0, + "yOffset": 0 + }, + { + "seats": [ + { "type": 8 }, + { "type": 8 }, + { "type": 8, "yOffset": 14.73 }, + { "type": 8 }, + { "type": 8 }, + { "type": 8 }, + { "type": 8, "yOffset": 14.73 }, + { "type": 8 } + ], + "x": 0, + "y": 0, + "xOffset": 0, + "yOffset": 0 + }, + { + "seats": [ + { "type": 8 }, + { "type": 8 }, + { "type": 8, "yOffset": 14.73 }, + { "type": 8 }, + { "type": 8 }, + { "type": 8 }, + { "type": 8, "yOffset": 14.73 }, + { "type": 8 } + ], + "x": 0, + "y": 0, + "xOffset": 0, + "yOffset": 0 + }, + { + "seats": [ + { "type": 8, "yOffset": 42.01 }, + { "type": 8 }, + { "type": 8 }, + { "type": 8 } + ], + "x": 0, + "y": 0, + "xOffset": 0, + "yOffset": 0 + } + ], + "stationIndex": 2, + "position": 70.7, + "simVar": "A32NX_PAX_MAIN_FWD_B" + }, + { + "name": "MAIN MID 1A", + "deck": 0, + "capacity": 39, + "rows": [ + { + "seats": [ + { "type": 2 }, + { "type": 2 }, + { "type": 2 + } + ], + "x": 0, + "y": 0, + "xOffset": 25, + "yOffset": 0 + }, + { + "seats": [ + { "type": 2 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2, "yOffset": 66.5 }, + { "type": 2 }, + { "type": 2 + } + ], + "x": 0, + "y": 0, + "xOffset": 0, + "yOffset": 0 + }, + { + "seats": [ + { "type": 2 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2, "yOffset": 9 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2, "yOffset": 9 }, + { "type": 2 }, + { "type": 2 + } + ], + "x": 0, + "y": 0, + "xOffset": 0, + "yOffset": 0 + }, + { + "seats": [ + { "type": 2 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2, "yOffset": 9 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2, "yOffset": 9 }, + { "type": 2 }, + { "type": 2 + } + ], + "x": 0, + "y": 0, + "xOffset": 0, + "yOffset": 0 + }, + { + "seats": [ + { "type": 2 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2, "yOffset": 9 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2, "yOffset": 9 }, + { "type": 2 }, + { "type": 2 + } + ], + "x": 0, + "y": 0, + "xOffset": 0, + "yOffset": 0 + } + ], + "stationIndex": 3, + "position": 25.6, + "simVar": "A32NX_PAX_MAIN_MID_1A" + }, + { + "name": "MAIN MID 1B", + "deck": 0, + "capacity": 50, + "rows": [ + { + "seats": [ + { "type": 2 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2, "yOffset": 9 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2, "yOffset": 9 }, + { "type": 2 }, + { "type": 2 + } + ], + "x": 0, + "y": 0, + "xOffset": 0, + "yOffset": 0 + }, + { + "seats": [ + { "type": 2 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2, "yOffset": 9 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2, "yOffset": 9 }, + { "type": 2 }, + { "type": 2 + } + ], + "x": 0, + "y": 0, + "xOffset": 0, + "yOffset": 0 + }, + { + "seats": [ + { "type": 2 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2, "yOffset": 9 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2, "yOffset": 9 }, + { "type": 2 }, + { "type": 2 + } + ], + "x": 0, + "y": 0, + "xOffset": 0, + "yOffset": 0 + }, + { + "seats": [ + { "type": 2 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2, "yOffset": 9 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2, "yOffset": 9 }, + { "type": 2 }, + { "type": 2 + } + ], + "x": 0, + "y": 0, + "xOffset": 0, + "yOffset": 0 + }, + { + "seats": [ + { "type": 2 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2, "yOffset": 9 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2, "yOffset": 9 }, + { "type": 2 }, + { "type": 2 + } + ], + "x": 0, + "y": 0, + "xOffset": 0, + "yOffset": 0 + } + ], + "stationIndex": 4, + "position": 25.6, + "simVar": "A32NX_PAX_MAIN_MID_1B" + }, + { + "name": "MAIN MID 1C", + "deck": 0, + "capacity": 43, + "rows": [ + { + "seats": [ + { "type": 2 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2, "yOffset": 9 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2, "yOffset": 9 }, + { "type": 2 }, + { "type": 2 + } + ], + "x": 0, + "y": 0, + "xOffset": 0, + "yOffset": 0 + }, + { + "seats": [ + { "type": 2 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2, "yOffset": 9 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2, "yOffset": 9 }, + { "type": 2 }, + { "type": 2 + } + ], + "x": 0, + "y": 0, + "xOffset": 0, + "yOffset": 0 + }, + { + "seats": [ + { "type": 2 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2, "yOffset": 9 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2, "yOffset": 9 }, + { "type": 2 }, + { "type": 2 + } + ], + "x": 0, + "y": 0, + "xOffset": 0, + "yOffset": 0 + }, + { + "seats": [ + { "type": 2 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2, "yOffset": 9 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2, "yOffset": 9 }, + { "type": 2 }, + { "type": 2 + } + ], + "x": 0, + "y": 0, + "xOffset": 0, + "yOffset": 0 + }, + { + "seats": [ + { "type": 2, "yOffset": 102.875 }, + { "type": 2 }, + { "type": 2 + } + ], + "x": 0, + "y": 0, + "xOffset": 0, + "yOffset": 0 + } + ], + "stationIndex": 5, + "position": 25.6, + "simVar": "A32NX_PAX_MAIN_MID_1C" + }, + { + "name": "MAIN MID 2A", + "deck": 0, + "capacity": 48, + "rows": [ + { + "seats": [ + { "type": 2, "yOffset": 11.52 }, + { "type": 2 }, + { "type": 2, "yOffset": 9 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2, "yOffset": 9 }, + { "type": 2 + } + ], + "x": 0, + "y": 0, + "xOffset": 20, + "yOffset": 0 + }, + { + "seats": [ + { "type": 2 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2, "yOffset": 9 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2, "yOffset": 9 }, + { "type": 2 }, + { "type": 2 + } + ], + "x": 0, + "y": 0, + "xOffset": 0, + "yOffset": 0 + }, + { + "seats": [ + { "type": 2 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2, "yOffset": 9 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2, "yOffset": 9 }, + { "type": 2 }, + { "type": 2 + } + ], + "x": 0, + "y": 0, + "xOffset": 0, + "yOffset": 0 + }, + { + "seats": [ + { "type": 2 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2, "yOffset": 9 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2, "yOffset": 9 }, + { "type": 2 }, + { "type": 2 + } + ], + "x": 0, + "y": 0, + "xOffset": 0, + "yOffset": 0 + }, + { + "seats": [ + { "type": 2 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2, "yOffset": 9 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2, "yOffset": 9 }, + { "type": 2 }, + { "type": 2 + } + ], + "x": 0, + "y": 0, + "xOffset": 0, + "yOffset": 0 + } + ], + "stationIndex": 6, + "position": -16.1, + "simVar": "A32NX_PAX_MAIN_MID_2A" + }, + { + "name": "MAIN MID 2B", + "deck": 0, + "capacity": 40, + "rows": [ + { + "seats": [ + { "type": 2 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2, "yOffset": 9 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2, "yOffset": 9 }, + { "type": 2 }, + { "type": 2 + } + ], + "x": 0, + "y": 0, + "xOffset": 0, + "yOffset": 0 + }, + { + "seats": [ + { "type": 2 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2, "yOffset": 9 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2, "yOffset": 9 }, + { "type": 2 }, + { "type": 2 + } + ], + "x": 0, + "y": 0, + "xOffset": 0, + "yOffset": 0 + }, + { + "seats": [ + { "type": 2 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2, "yOffset": 9 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2, "yOffset": 9 }, + { "type": 2 }, + { "type": 2 + } + ], + "x": 0, + "y": 0, + "xOffset": 0, + "yOffset": 0 + }, + { + "seats": [ + { "type": 2 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2, "yOffset": 9 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2, "yOffset": 9 }, + { "type": 2 }, + { "type": 2 + } + ], + "x": 0, + "y": 0, + "xOffset": 0, + "yOffset": 0 + } + ], + "stationIndex": 7, + "position": -16.1, + "simVar": "A32NX_PAX_MAIN_MID_2B" + }, + { + "name": "MAIN MID 2C", + "deck": 0, + "capacity": 36, + "rows": [ + { + "seats": [ + { "type": 2 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2, "yOffset": 9 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2, "yOffset": 9 }, + { "type": 2 }, + { "type": 2 + } + ], + "x": 0, + "y": 0, + "xOffset": 0, + "yOffset": 0 + }, + { + "seats": [ + { "type": 2 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2, "yOffset": 9 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2, "yOffset": 9 }, + { "type": 2 }, + { "type": 2 + } + ], + "x": 0, + "y": 0, + "xOffset": 0, + "yOffset": 0 + }, + { + "seats": [ + { "type": 2 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2, "yOffset": 9 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2, "yOffset": 9 }, + { "type": 2 }, + { "type": 2 + } + ], + "x": 0, + "y": 0, + "xOffset": 0, + "yOffset": 0 + }, + { + "seats": [ + { "type": 2 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2, "yOffset": 66.5 }, + { "type": 2 }, + { "type": 2 + } + ], + "x": 0, + "y": 0, + "xOffset": 0, + "yOffset": 0 + } + ], + "stationIndex": 8, + "position": -16.1, + "simVar": "A32NX_PAX_MAIN_MID_2C" + }, + { + "name": "MAIN AFT A", + "deck": 0, + "capacity": 42, + "rows": [ + { + "seats": [ + { "type": 2 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2, "yOffset": 66.5 }, + { "type": 2 }, + { "type": 2 + } + ], + "x": 0, + "y": 0, + "xOffset": 40, + "yOffset": 0 + }, + { + "seats": [ + { "type": 2 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2, "yOffset": 66.5 }, + { "type": 2 }, + { "type": 2 + } + ], + "x": 0, + "y": 0, + "xOffset": 0, + "yOffset": 0 + }, + { + "seats": [ + { "type": 2 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2, "yOffset": 9 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2, "yOffset": 9 }, + { "type": 2 }, + { "type": 2 + } + ], + "x": 0, + "y": 0, + "xOffset": 0, + "yOffset": 0 + }, + { + "seats": [ + { "type": 2 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2, "yOffset": 9 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2, "yOffset": 9 }, + { "type": 2 }, + { "type": 2 + } + ], + "x": 0, + "y": 0, + "xOffset": 0, + "yOffset": 0 + }, + { + "seats": [ + { "type": 2 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2, "yOffset": 9 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2, "yOffset": 9 }, + { "type": 2 }, + { "type": 2 + } + ], + "x": 0, + "y": 0, + "xOffset": 0, + "yOffset": 0 + } + ], + "stationIndex": 9, + "position": -51.9, + "simVar": "A32NX_PAX_MAIN_AFT_A" + }, + { + "name": "MAIN AFT B", + "deck": 0, + "capacity": 40, + "rows": [ + { + "seats": [ + { "type": 2 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2, "yOffset": 9 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2, "yOffset": 9 }, + { "type": 2 }, + { "type": 2 + } + ], + "x": 0, + "y": 0, + "xOffset": 0, + "yOffset": 0 + }, + { + "seats": [ + { "type": 2 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2, "yOffset": 9 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2, "yOffset": 9 }, + { "type": 2 }, + { "type": 2 + } + ], + "x": 0, + "y": 0, + "xOffset": 0, + "yOffset": 0 + }, + { + "seats": [ + { "type": 2 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2, "yOffset": 9 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2, "yOffset": 9 }, + { "type": 2 }, + { "type": 2 + } + ], + "x": 0, + "y": 0, + "xOffset": 0, + "yOffset": 0 + }, + { + "seats": [ + { "type": 2, "yOffset": 1.5 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2, "yOffset": 7.5 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2 }, + { "type": 2, "yOffset": 7.5 }, + { "type": 2 }, + { "type": 2 + } + ], + "x": 0, + "y": 0, + "xOffset": 0, + "yOffset": 0 + } + ], + "stationIndex": 10, + "position": -51.9, + "simVar": "A32NX_PAX_MAIN_AFT_B" + }, + { + "name": "UPPER FWD", + "deck": 1, + "capacity": 14, + "rows": [ + { + "seats": [ + { "type": 6, "yOffset": 10 }, + { "type": 7, "yOffset": 11 }, + { "type": 6 }, + { "type": 7, "yOffset": 11 + } + ], + "x": 0, + "y": 0, + "xOffset": 45, + "yOffset": 0 + }, + { + "seats": [ + { "type": 6, "yOffset": 10 }, + { "type": 7, "yOffset": 11 }, + { "type": 6 }, + { "type": 7, "yOffset": 11 + } + ], + "x": 0, + "y": 0, + "xOffset": 0, + "yOffset": 0 + }, + { + "seats": [ + { "type": 6, "yOffset": 10 }, + { "type": 7, "yOffset": 11 }, + { "type": 6 }, + { "type": 7, "yOffset": 11 + } + ], + "x": 0, + "y": 0, + "xOffset": 0, + "yOffset": 0 + }, + { + "seats": [ + { "type": 6, "yOffset": 10 }, + { "type": 7, "yOffset": 62 + } + ], + "x": 0, + "y": 0, + "xOffset": 0, + "yOffset": 0 + } + ], + "stationIndex": 11, + "position": 55.8, + "simVar": "A32NX_PAX_UPPER_FWD" + }, + { + "name": "UPPER MID A", + "deck": 1, + "capacity": 30, + "rows": [ + { + "seats": [ + { "type": 4, "yOffset": 45 }, + { "type": 5 + } + ], + "x": 0, + "y": 0, + "xOffset": 45, + "yOffset": 0 + }, + { + "seats": [ + { "type": 4, "yOffset": 10 }, + { "type": 5, "yOffset": 11 }, + { "type": 4 }, + { "type": 5, "yOffset": 11 + } + ], + "x": 0, + "y": 0, + "xOffset": 0, + "yOffset": 0 + }, + { + "seats": [ + { "type": 5, "yOffset": 10 }, + { "type": 4, "yOffset": 11 }, + { "type": 5 }, + { "type": 4, "yOffset": 11 + } + ], + "x": 0, + "y": 0, + "xOffset": 0, + "yOffset": 0 + }, + { + "seats": [ + { "type": 4, "yOffset": 10 }, + { "type": 5, "yOffset": 11 }, + { "type": 4 }, + { "type": 5, "yOffset": 11 + } + ], + "x": 0, + "y": 0, + "xOffset": 0, + "yOffset": 0 + }, + { + "seats": [ + { "type": 5, "yOffset": 10 }, + { "type": 4, "yOffset": 11 }, + { "type": 5 }, + { "type": 4, "yOffset": 11 + } + ], + "x": 0, + "y": 0, + "xOffset": 0, + "yOffset": 0 + }, + { + "seats": [ + { "type": 4, "yOffset": 10 }, + { "type": 5, "yOffset": 11 }, + { "type": 4 }, + { "type": 5, "yOffset": 11 + } + ], + "x": 0, + "y": 0, + "xOffset": 0, + "yOffset": 0 + }, + { + "seats": [ + { "type": 5, "yOffset": 10 }, + { "type": 4, "yOffset": 11 }, + { "type": 5 }, + { "type": 4, "yOffset": 11 + } + ], + "x": 0, + "y": 0, + "xOffset": 0, + "yOffset": 0 + }, + { + "seats": [ + { "type": 4, "yOffset": 10 }, + { "type": 5, "yOffset": 11 }, + { "type": 4 }, + { "type": 5, "yOffset": 11 + } + ], + "x": 0, + "y": 0, + "xOffset": 0, + "yOffset": 0 + } + ], + "stationIndex": 11, + "position": 55.8, + "simVar": "A32NX_PAX_UPPER_MID_A" + }, + { + "name": "UPPER MID B", + "deck": 1, + "capacity": 28, + "rows": [ + { + "seats": [ + { "type": 5, "yOffset": 10 }, + { "type": 4, "yOffset": 11 }, + { "type": 5 }, + { "type": 4, "yOffset": 11 + } + ], + "x": 0, + "y": 0, + "xOffset": 0, + "yOffset": 0 + }, + { + "seats": [ + { "type": 4, "yOffset": 10 }, + { "type": 5, "yOffset": 11 }, + { "type": 4 }, + { "type": 5, "yOffset": 11 + } + ], + "x": 0, + "y": 0, + "xOffset": 0, + "yOffset": 0 + }, + { + "seats": [ + { "type": 5, "yOffset": 10 }, + { "type": 4, "yOffset": 11 }, + { "type": 5 }, + { "type": 4, "yOffset": 11 + } + ], + "x": 0, + "y": 0, + "xOffset": 0, + "yOffset": 0 + }, + { + "seats": [ + { "type": 4, "yOffset": 10 }, + { "type": 5, "yOffset": 11 }, + { "type": 4 }, + { "type": 5, "yOffset": 11 + } + ], + "x": 0, + "y": 0, + "xOffset": 0, + "yOffset": 0 + }, + { + "seats": [ + { "type": 5, "yOffset": 10 }, + { "type": 4, "yOffset": 11 }, + { "type": 5 }, + { "type": 4, "yOffset": 11 + } + ], + "x": 0, + "y": 0, + "xOffset": 0, + "yOffset": 0 + }, + { + "seats": [ + { "type": 4, "yOffset": 10 }, + { "type": 5, "yOffset": 11 }, + { "type": 4 }, + { "type": 5, "yOffset": 11 + } + ], + "x": 0, + "y": 0, + "xOffset": 0, + "yOffset": 0 + }, + { + "seats": [ + { "type": 5, "yOffset": 10 }, + { "type": 4, "yOffset": 11 }, + { "type": 5 }, + { "type": 4, "yOffset": 11 + } + ], + "x": 0, + "y": 0, + "xOffset": 0, + "yOffset": 0 + } + ], + "stationIndex": 11, + "position": 55.8, + "simVar": "A32NX_PAX_UPPER_MID_B" + }, + { + "name": "UPPER AFT", + "deck": 1, + "capacity": 18, + "rows": [ + { + "seats": [ + { "type": 4, "yOffset": 45 }, + { "type": 5 + } + ], + "x": 0, + "y": 0, + "xOffset": 40, + "yOffset": 0 + }, + { + "seats": [ + { "type": 4, "yOffset": 10 }, + { "type": 5, "yOffset": 11 }, + { "type": 4 }, + { "type": 5, "yOffset": 11 + } + ], + "x": 0, + "y": 0, + "xOffset": 0, + "yOffset": 0 + }, + { + "seats": [ + { "type": 5, "yOffset": 10 }, + { "type": 4, "yOffset": 11 }, + { "type": 5 }, + { "type": 4, "yOffset": 11 + } + ], + "x": 0, + "y": 0, + "xOffset": 0, + "yOffset": 0 + }, + { + "seats": [ + { "type": 4, "yOffset": 10 }, + { "type": 5, "yOffset": 11 }, + { "type": 4 }, + { "type": 5, "yOffset": 11 + } + ], + "x": 0, + "y": 0, + "xOffset": 0, + "yOffset": 0 + }, + { + "seats": [ + { "type": 5, "yOffset": 10 }, + { "type": 4, "yOffset": 11 }, + { "type": 5 }, + { "type": 4, "yOffset": 11 + } + ], + "x": 0, + "y": 0, + "xOffset": 0, + "yOffset": 0 + } + ], + "stationIndex": 11, + "position": 55.8, + "simVar": "A32NX_PAX_UPPER_AFT" + } + ], + "cargoMap": [ + { + "name": "FWD BAGGAGE/CONTAINER", + "weight": 28577, + "stationIndex": 15, + "position": 62.4, + "progressBarWidth": 160, + "simVar": "A32NX_CARGO_FWD" + }, + { + "name": "AFT BAGGAGE", + "weight": 20310, + "stationIndex": 16, + "position": -23.5, + "progressBarWidth": 160, + "simVar": "A32NX_CARGO_AFT" + }, + { + "name": "AFT BULK/LOOSE", + "weight": 2513, + "stationIndex": 17, + "position": -57.9, + "progressBarWidth": 100, + "simVar": "A32NX_CARGO_BULK" + } + ] +} diff --git a/fbw-a380x/src/base/flybywire-aircraft-a380-842/config/a380x_checklists.json5 b/fbw-a380x/src/base/flybywire-aircraft-a380-842/config/a380x/a380-842/checklists.json5 similarity index 100% rename from fbw-a380x/src/base/flybywire-aircraft-a380-842/config/a380x_checklists.json5 rename to fbw-a380x/src/base/flybywire-aircraft-a380-842/config/a380x/a380-842/checklists.json5 diff --git a/fbw-a380x/src/base/flybywire-aircraft-a380-842/config/a380x/a380-842/flypad-misc.json5 b/fbw-a380x/src/base/flybywire-aircraft-a380-842/config/a380x/a380-842/flypad-misc.json5 new file mode 100644 index 00000000000..a655fc1c621 --- /dev/null +++ b/fbw-a380x/src/base/flybywire-aircraft-a380-842/config/a380x/a380-842/flypad-misc.json5 @@ -0,0 +1,36 @@ +// Copyright (c) 2024 FlyByWire Simulations +// SPDX-License-Identifier: GPL-3.0 +// ======================================================================================= +// This is part of the base flyPad configuration file for A380-842 +// Any keys prefixed by underscore (_) should be considered read-only and not overwritable. +// +// NOTE: * This is currently a WIP * ! The override functionality has not been completed yet ! +// +// ****** ! WARNING TO LIVERY MAKERS: DO NOT OVERRIDE THIS FILE ! ********** +// ****** ! WARNING TO LIVERY MAKERS: DO NOT OVERRIDE THIS FILE ! ********** +// ****** ! WARNING TO LIVERY MAKERS: DO NOT OVERRIDE THIS FILE ! ********** +// ****** ! WARNING TO LIVERY MAKERS: DO NOT OVERRIDE THIS FILE ! ********** +// +// Please follow the instructions in the documentation to create a new configuration file! +// ======================================================================================= +// Last updated: 2 April 2024 +{ + "configMajorVersion": 0, + "configMinorVersion": 1, + "_throttle": { + "numberOfAxis": 4, + "axisOptions": [ + 1, + 2, + 4 + ], + "axisMapping": [ + [[1, 2, 3, 4]], // 1 + [[1, 2], [3, 4]], // 2 + [[1], [2], [3], [4]] // 4 + ] + }, + "_pushback": { + "turnIndicatorTuningDefault": 1.35, // determined by testing + } +} diff --git a/fbw-a380x/src/base/flybywire-aircraft-a380-842/config/a380x/a380-842/flypad-payload.json5 b/fbw-a380x/src/base/flybywire-aircraft-a380-842/config/a380x/a380-842/flypad-payload.json5 new file mode 100644 index 00000000000..d71355c26c0 --- /dev/null +++ b/fbw-a380x/src/base/flybywire-aircraft-a380-842/config/a380x/a380-842/flypad-payload.json5 @@ -0,0 +1,133 @@ +// Copyright (c) 2024 FlyByWire Simulations +// SPDX-License-Identifier: GPL-3.0 +// ======================================================================================= +// This is part of the base flyPad configuration file for A380-842 +// Any keys prefixed by underscore (_) should be considered read-only and not overwritable. +// +// NOTE: * This is currently a WIP * ! The override functionality has not been completed yet ! +// +// ****** ! WARNING TO LIVERY MAKERS: DO NOT OVERRIDE THIS FILE ! ********** +// ****** ! WARNING TO LIVERY MAKERS: DO NOT OVERRIDE THIS FILE ! ********** +// ****** ! WARNING TO LIVERY MAKERS: DO NOT OVERRIDE THIS FILE ! ********** +// ****** ! WARNING TO LIVERY MAKERS: DO NOT OVERRIDE THIS FILE ! ********** +// +// Please follow the instructions in the documentation to create a new configuration file! +// ======================================================================================= +// Last updated: 2 April 2024 +{ + "configMajorVersion": 0, + "configMinorVersion": 1, + "_canvas": { + "width": 1000, + "height": 150, + "canvasX": 146, + "canvasY": 71 + }, + "chartLimits": { + "weight": { + "min": 235000, + "max": 550000, + "lines": 9, + "scale": 35000, + "values": [ 550, 480, 410, 340, 270 ] + }, + "cg": { + "angleRad": 0.014025, + "min": 24, + "max": 54, + "overlap": 32, + "highlight": 5, + "lines": 30, + "scale": 1, + "values": [ 25, 30, 35, 40, 45, 50 ] + }, + "labels": { + "mtow": { "x1": 0.75, "x2": 0.3, "y": 0.1 }, + "mlw": { "x1": 0.75, "x2": 0.12, "y": 0.47 }, + "mzfw": { "x1": 0.75, "x2": 0.12, "y": 0.57 } + } + }, + "seatDisplay": [ + { + // NarrowbodyEconomy + len: 25.4, + wid: 19.2, + padX: 6.8, + padY: 0, + imageX: 25.4, + imageY: 19.2, + }, + { + // NarrowbodyEconomyEmergency + len: 25.4, + wid: 19.2, + padX: 13.8, + padY: 0, + imageX: 25.4, + imageY: 19.2, + }, + { + // WidebodyEconomy + len: 16, + wid: 12.125, + padX: 2, + padY: 0, + imageX: 16, + imageY: 12.125, + }, + { + // WidebodyEconomyEmergency + len: 16, + wid: 12.125, + padX: 2, + padY: 0, + imageX: 16, + imageY: 12.125, + }, + { + // WidebodyBusinessFlatRight + len: 24, + wid: 23.22, + padX: 1, + padY: 0, + imageX: 24, + imageY: 23.22, + }, + { + // WidebodyBusinessFlatLeft + len: 24, + wid: 23.22, + padX: 1, + padY: 0, + imageX: 24, + imageY: 23.22, + }, + { + // WidebodySuiteRight + len: 35, + wid: 20, + padX: 2, + padY: 0, + imageX: 50, + imageY: 50, + }, + { + // WidebodySuiteLeft + len: 35, + wid: 20, + padX: 5, + padY: 0, + imageX: 50, + imageY: 50, + }, + { + // WidebodyPremiumEconomy + len: 18, + wid: 13.64, + padX: 2, + padY: 0, + imageX: 18, + imageY: 13.64, + } + ] +} diff --git a/fbw-a380x/src/systems/atsu/src/com/webinterfaces/NXApiConnector.ts b/fbw-a380x/src/systems/atsu/src/com/webinterfaces/NXApiConnector.ts index 0baff87768f..5c7768f4b53 100644 --- a/fbw-a380x/src/systems/atsu/src/com/webinterfaces/NXApiConnector.ts +++ b/fbw-a380x/src/systems/atsu/src/com/webinterfaces/NXApiConnector.ts @@ -33,7 +33,7 @@ export class NXApiConnector { const long = SimVar.GetSimVarValue('PLANE LONGITUDE', 'degree longitude'); const alt = SimVar.GetSimVarValue('PLANE ALTITUDE', 'feet'); const heading = SimVar.GetSimVarValue('PLANE HEADING DEGREES TRUE', 'degree'); - const acType = SimVar.GetSimVarValue('TITLE', 'string'); + const acType = SimVar.GetSimVarValue('TITLE', 'string'); // Note: This can be overriden by livery aircraft.cfg const origin = NXDataStore.get('PLAN_ORIGIN', ''); const destination = NXDataStore.get('PLAN_DESTINATION', ''); const freetext = NXDataStore.get('CONFIG_ONLINE_FEATURES_STATUS', 'DISABLED') === 'ENABLED'; diff --git a/fbw-a380x/src/systems/extras-host/index.ts b/fbw-a380x/src/systems/extras-host/index.ts index 1ac80686e76..89032dc5043 100644 --- a/fbw-a380x/src/systems/extras-host/index.ts +++ b/fbw-a380x/src/systems/extras-host/index.ts @@ -7,6 +7,7 @@ import { ExtrasSimVarPublisher } from 'extras-host/modules/common/ExtrasSimVarPu import { PushbuttonCheck } from 'extras-host/modules/pushbutton_check/PushbuttonCheck'; import { KeyInterceptor } from './modules/key_interceptor/KeyInterceptor'; import { VersionCheck } from './modules/version_check/VersionCheck'; +import { AircraftSync } from 'extras-host/modules/aircraft_sync/AircraftSync'; /** * This is the main class for the extras-host instrument. @@ -40,6 +41,8 @@ class ExtrasHost extends BaseInstrument { private readonly keyInterceptor: KeyInterceptor; + private readonly aircraftSync: AircraftSync; + /** * "mainmenu" = 0 * "loading" = 1 @@ -58,8 +61,9 @@ class ExtrasHost extends BaseInstrument { this.notificationManager = new NotificationManager(); this.pushbuttonCheck = new PushbuttonCheck(this.bus, this.notificationManager); - this.versionCheck = new VersionCheck(this.bus); this.keyInterceptor = new KeyInterceptor(this.bus, this.notificationManager); + this.versionCheck = new VersionCheck(process.env.AIRCRAFT_PROJECT_PREFIX, this.bus); + this.aircraftSync = new AircraftSync(process.env.AIRCRAFT_PROJECT_PREFIX, this.bus); console.log('A380X_EXTRASHOST: Created'); } @@ -80,6 +84,12 @@ class ExtrasHost extends BaseInstrument { super.connectedCallback(); this.pushbuttonCheck.connectedCallback(); + this.aircraftSync.connectedCallback(); + } + + public parseXMLConfig(): void { + super.parseXMLConfig(); + this.aircraftSync.parseXMLConfig(this.xmlConfig); } public Update(): void { @@ -93,6 +103,7 @@ class ExtrasHost extends BaseInstrument { this.versionCheck.startPublish(); this.keyInterceptor.startPublish(); this.simVarPublisher.startPublish(); + this.aircraftSync.startPublish(); // Signal that the aircraft is ready via L:A32NX_IS_READY SimVar.SetSimVarValue('L:A32NX_IS_READY', 'number', 1); diff --git a/fbw-a380x/src/systems/extras-host/modules/aircraft_sync/AircraftSync.ts b/fbw-a380x/src/systems/extras-host/modules/aircraft_sync/AircraftSync.ts new file mode 100644 index 00000000000..12cd164db0f --- /dev/null +++ b/fbw-a380x/src/systems/extras-host/modules/aircraft_sync/AircraftSync.ts @@ -0,0 +1,34 @@ +// Copyright (c) 2022 FlyByWire Simulations +// SPDX-License-Identifier: GPL-3.0 + +import { EventBus } from '@microsoft/msfs-sdk'; + +/** + * This class is used to check the airframe of the aircraft and set the LVar + */ +export class AircraftSync { + public xmlConfig: Document + + constructor(private readonly aircraftProjectPrefix: string, private readonly bus: EventBus) { + console.log('AircraftSync: Created'); + } + + public connectedCallback(): void { + // empty + } + + public parseXMLConfig(xmlConfig: Document): void { + this.xmlConfig = xmlConfig; + } + + // TODO: Replace with new function for commbus implementation to sync VFS markup config to WASM + public startPublish(): void { + console.log('AicraftSync: startPublish()'); + + // TODO: Future WASM commbus subscriber goes here + } + + public update(): void { + // empty + } +} diff --git a/fbw-a380x/src/systems/extras-host/modules/version_check/VersionCheck.ts b/fbw-a380x/src/systems/extras-host/modules/version_check/VersionCheck.ts index e4f28374938..54e63fa7f57 100644 --- a/fbw-a380x/src/systems/extras-host/modules/version_check/VersionCheck.ts +++ b/fbw-a380x/src/systems/extras-host/modules/version_check/VersionCheck.ts @@ -7,7 +7,7 @@ import { EventBus } from '@microsoft/msfs-sdk'; * This class is used to check the version of the aircraft and display a warning if it is too old. */ export class VersionCheck { - constructor(private readonly bus: EventBus) { + constructor(private readonly aircraftProjectPrefix: string, private readonly bus: EventBus) { console.log('VersionCheck: Created'); } diff --git a/fbw-a380x/src/systems/instruments/buildSrc/plugins.mjs b/fbw-a380x/src/systems/instruments/buildSrc/plugins.mjs index 3d57c9680cb..a3dcaa8bee8 100644 --- a/fbw-a380x/src/systems/instruments/buildSrc/plugins.mjs +++ b/fbw-a380x/src/systems/instruments/buildSrc/plugins.mjs @@ -79,6 +79,8 @@ export function baseCompile(instrumentName, instrumentFolder) { 'process.env.CLIENT_SECRET': JSON.stringify(process.env.CLIENT_SECRET), 'process.env.CHARTFOX_SECRET': JSON.stringify(process.env.CHARTFOX_SECRET), 'process.env.SENTRY_DSN': JSON.stringify(process.env.SENTRY_DSN), + 'process.env.AIRCRAFT_PROJECT_PREFIX': JSON.stringify(process.env.AIRCRAFT_PROJECT_PREFIX), + 'process.env.AIRCRAFT_VARIANT': JSON.stringify(process.env.AIRCRAFT_VARIANT), }), postCss(instrumentName, instrumentFolder), ]; diff --git a/fbw-a380x/src/systems/instruments/src/EFB/index.tsx b/fbw-a380x/src/systems/instruments/src/EFB/index.tsx index 1f4389301bb..3bef72c2f14 100644 --- a/fbw-a380x/src/systems/instruments/src/EFB/index.tsx +++ b/fbw-a380x/src/systems/instruments/src/EFB/index.tsx @@ -2,46 +2,11 @@ // SPDX-License-Identifier: GPL-3.0 import React from 'react'; -import {ChecklistProvider, NXDataStore} from '@flybywiresim/fbw-sdk'; - -import { customAlphabet } from 'nanoid'; import { render } from '@instruments/common/index'; -import { readSettingsFromPersistentStorage, migrateSettings, EfbInstrument } from '@flybywiresim/flypad'; -import {A380FailureDefinitions} from "../../../failures"; - -// TODO move all of this to fbw-common somehow - -const setSessionId = () => { - const ALPHABET = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'; - const SESSION_ID_LENGTH = 14; - const nanoid = customAlphabet(ALPHABET, SESSION_ID_LENGTH); - const generatedSessionID = nanoid(); - - NXDataStore.set('A32NX_SENTRY_SESSION_ID', generatedSessionID); -}; - -const setup = () => { - readSettingsFromPersistentStorage(); - migrateSettings(); - setSessionId(); - - // Needed to fetch METARs from the sim - RegisterViewListener('JS_LISTENER_FACILITY', () => { - console.log('JS_LISTENER_FACILITY registered.'); - }, true); -}; - -if (process.env.VITE_BUILD) { - window.addEventListener('AceInitialized', setup); -} else { - setup(); -} +import { EfbWrapper} from '@flybywiresim/flypad'; +import { A380FailureDefinitions } from "../../../failures"; -ChecklistProvider.getInstance().readChecklist() - .then((aircraftChecklistsFromJson) => { - console.log('Checklists loaded'); - render(,); - }) - .catch((error) => { - console.error('Failed to load checklists', error); - }); +// TODO: Move failure definition into VFS +render( + +); diff --git a/fbw-common/src/systems/datalink/router/src/webinterfaces/NXApiConnector.ts b/fbw-common/src/systems/datalink/router/src/webinterfaces/NXApiConnector.ts index 5791b005ffd..69ff23031f6 100644 --- a/fbw-common/src/systems/datalink/router/src/webinterfaces/NXApiConnector.ts +++ b/fbw-common/src/systems/datalink/router/src/webinterfaces/NXApiConnector.ts @@ -30,7 +30,7 @@ export class NXApiConnector { const long = SimVar.GetSimVarValue('PLANE LONGITUDE', 'degree longitude'); const alt = SimVar.GetSimVarValue('PLANE ALTITUDE', 'feet'); const heading = SimVar.GetSimVarValue('PLANE HEADING DEGREES TRUE', 'degree'); - const acType = SimVar.GetSimVarValue('TITLE', 'string'); + const acType = SimVar.GetSimVarValue('TITLE', 'string'); // Note: This can be overriden by livery aircraft.cfg const origin = NXDataStore.get('PLAN_ORIGIN', ''); const destination = NXDataStore.get('PLAN_DESTINATION', ''); const freetext = NXDataStore.get('CONFIG_ONLINE_FEATURES_STATUS', 'DISABLED') === 'ENABLED'; diff --git a/fbw-common/src/systems/instruments/src/EFB/Apis/Simbrief/simbriefParser.ts b/fbw-common/src/systems/instruments/src/EFB/Apis/Simbrief/simbriefParser.ts index 4cbe0b460d9..bcc619c17fb 100644 --- a/fbw-common/src/systems/instruments/src/EFB/Apis/Simbrief/simbriefParser.ts +++ b/fbw-common/src/systems/instruments/src/EFB/Apis/Simbrief/simbriefParser.ts @@ -1,7 +1,7 @@ // Copyright (c) 2023-2024 FlyByWire Simulations // SPDX-License-Identifier: GPL-3.0 -import { AircraftVersionChecker, getAircraftType } from '@flybywiresim/fbw-sdk'; +import { AircraftGithubVersionChecker, UniversalConfigProvider } from '@flybywiresim/fbw-sdk'; import { ISimbriefData } from './simbriefInterface'; const SIMBRIEF_BASE_URL = 'https://www.simbrief.com/api/xml.fetcher.php'; @@ -26,14 +26,13 @@ export const getSimbriefData = async (navigraphUsername: string, overrideSimbrie simbriefApiParams.append('json', '1'); // Adding the build version to the url parameters to allow Navigraph/Simbrief to track requests from the A32NX - // The try/catch is there as the a380x build info file cannot be loaded with the current package setup/order and - // will throw an error - if this is fixed (build_info for a380x is readable from the flyPad for the A380X) then - // this try/catch could be removed, but it doesn't hurt to have it here even then as an extra safety measure + // try/catch here is an extra safety measure in case the configuration files are not found try { - const versionInfo = await AircraftVersionChecker.getBuildInfo(getAircraftType()); - simbriefApiParams.append('client', `fbw-${versionInfo.version}`); + const airframeInfo = await UniversalConfigProvider.fetchAirframeInfo(process.env.AIRCRAFT_PROJECT_PREFIX, process.env.AIRCRAFT_VARIANT); + const versionInfo = await AircraftGithubVersionChecker.getBuildInfo(process.env.AIRCRAFT_PROJECT_PREFIX); + simbriefApiParams.append('client', `${airframeInfo.developer.toLowerCase()}-${airframeInfo.variant.toLowerCase()}-${versionInfo.version}`); } catch (e) { - console.error('Error getting build info', e); + console.error('Error getting airframe and build info', e); } simbriefApiUrl.search = simbriefApiParams.toString(); 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 9a99fd1bf56..2263ca4d222 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 @@ -2,14 +2,14 @@ // SPDX-License-Identifier: GPL-3.0 /* eslint-disable max-len */ -import React, { useState, useEffect } from 'react'; +import React, { useEffect } from 'react'; import { useHistory } from 'react-router-dom'; import { IconPlane } from '@tabler/icons'; import { CloudArrowDown } from 'react-bootstrap-icons'; import { usePersistentNumberProperty, usePersistentProperty, useSimVar } from '@flybywiresim/fbw-sdk'; import { toast } from 'react-toastify'; import { - AC_TYPE, ScrollableContainer, getAirframeType, t, useAppSelector, + ScrollableContainer, t, useAppSelector, useAppDispatch, fetchSimbriefDataAction, isSimbriefDataLoaded, setPayloadImported, setFuelImported, setToastPresented, setSimbriefDataPending, } from '@flybywiresim/flypad'; @@ -31,7 +31,7 @@ export const FlightWidget = () => { const [navigraphUsername] = usePersistentProperty('NAVIGRAPH_USERNAME'); const [overrideSimBriefUserID] = usePersistentProperty('CONFIG_OVERRIDE_SIMBRIEF_USERID'); const [autoSimbriefImport] = usePersistentProperty('CONFIG_AUTO_SIMBRIEF_IMPORT'); - const [airframe] = useState(getAirframeType()); + const airframeInfo = useAppSelector((state) => state.config.airframeInfo); const [gsxPayloadSyncEnabled] = usePersistentNumberProperty('GSX_PAYLOAD_SYNC', 248); const [gsxBoardingState] = useSimVar('L:FSDT_GSX_BOARDING_STATE', 'Number', 227); @@ -130,7 +130,7 @@ export const FlightWidget = () => {

{t('Dashboard.YourFlight.Title')}

{simbriefDataLoaded ? `${(airline.length > 0 ? airline : '') + flightNum} | ` : ''} - {(airframe !== null ? AC_TYPE[airframe] : 'A320-251N')} + {airframeInfo.variant}

diff --git a/fbw-common/src/systems/instruments/src/EFB/Dispatch/Pages/Overview/A320_251N/A320Overview.tsx b/fbw-common/src/systems/instruments/src/EFB/Dispatch/Pages/Overview/A320_251N/A320Overview.tsx deleted file mode 100644 index e83a8c51341..00000000000 --- a/fbw-common/src/systems/instruments/src/EFB/Dispatch/Pages/Overview/A320_251N/A320Overview.tsx +++ /dev/null @@ -1,100 +0,0 @@ -// Copyright (c) 2023-2024 FlyByWire Simulations -// SPDX-License-Identifier: GPL-3.0 - -import React, { FC } from 'react'; -import { IconPlane } from '@tabler/icons'; -import { Box, LightningFill, PeopleFill, Rulers, Speedometer2 } from 'react-bootstrap-icons'; -import { useSimVar, Units } from '@flybywiresim/fbw-sdk'; -import { t, A320NoseOutline } from '@flybywiresim/flypad'; - -interface InformationEntryProps { - title: string; - info: string; -} - -const InformationEntry: FC = ({ children, title, info }) => ( -
-
- {children} -

{title}

-
-

{info}

-
-); - -export const A320Overview = () => { - let [airline] = useSimVar('ATC AIRLINE', 'String', 1_000); - - airline ||= 'FlyByWire Simulations'; - const [actualGrossWeight] = useSimVar('TOTAL WEIGHT', 'kilograms', 5_000); - - const getConvertedInfo = (metricValue: number, unitType: 'weight' |'volume' |'distance') => { - const numberWithCommas = (x: number) => x.toFixed(0).replace(/\B(?=(\d{3})+(?!\d))/g, ','); - - switch (unitType) { - case 'weight': - return `${numberWithCommas(Units.kilogramToUser(metricValue))} [${Units.userWeightSuffixEis2}]`; - case 'volume': - return `${numberWithCommas(Units.litreToUser(metricValue))} [${Units.userVolumeSuffixEis2}]`; - case 'distance': - return `${numberWithCommas(metricValue)} [nm]`; - default: throw new Error('Invalid unit type'); - } - }; - - return ( -
-

Airbus A320neo

-

{airline}

- -
- -
- -
-
- - - - - - - - - - - - - - - - - - - -
-
- - - - - - - - - - - - - - - - - - - -
-
-
- ); -}; diff --git a/fbw-common/src/systems/instruments/src/EFB/Dispatch/Pages/Overview/A380_842/A380Overview.tsx b/fbw-common/src/systems/instruments/src/EFB/Dispatch/Pages/Overview/A380_842/A380Overview.tsx deleted file mode 100644 index 1bedc26cea9..00000000000 --- a/fbw-common/src/systems/instruments/src/EFB/Dispatch/Pages/Overview/A380_842/A380Overview.tsx +++ /dev/null @@ -1,100 +0,0 @@ -// Copyright (c) 2023-2024 FlyByWire Simulations -// SPDX-License-Identifier: GPL-3.0 - -import React, { FC } from 'react'; -import { IconPlane } from '@tabler/icons'; -import { Box, LightningFill, PeopleFill, Rulers, Speedometer2 } from 'react-bootstrap-icons'; -import { useSimVar, Units } from '@flybywiresim/fbw-sdk'; -import { t, A380NoseOutline } from '@flybywiresim/flypad'; - -interface InformationEntryProps { - title: string; - info: string; -} - -const InformationEntry: FC = ({ children, title, info }) => ( -
-
- {children} -

{title}

-
-

{info}

-
-); - -export const A380Overview = () => { - let [airline] = useSimVar('ATC AIRLINE', 'String', 1_000); - - airline ||= 'FlyByWire Simulations'; - const [actualGrossWeight] = useSimVar('TOTAL WEIGHT', 'kilograms', 5_000); - - const getConvertedInfo = (metricValue: number, unitType: 'weight' |'volume' |'distance') => { - const numberWithCommas = (x: number) => x.toFixed(0).replace(/\B(?=(\d{3})+(?!\d))/g, ','); - - switch (unitType) { - case 'weight': - return `${numberWithCommas(Units.kilogramToUser(metricValue))} [${Units.userWeightSuffixEis2}]`; - case 'volume': - return `${numberWithCommas(Units.litreToUser(metricValue))} [${Units.userVolumeSuffixEis2}]`; - case 'distance': - return `${numberWithCommas(metricValue)} [nm]`; - default: throw new Error('Invalid unit type'); - } - }; - - return ( -
-

Airbus A380

-

{airline}

- -
- -
- -
-
- - - - - - - - - - - - - - - - - - - -
-
- - - - - - - - - - - - - - - - - - - -
-
-
- ); -}; diff --git a/fbw-common/src/systems/instruments/src/EFB/Dispatch/Pages/OverviewPage.tsx b/fbw-common/src/systems/instruments/src/EFB/Dispatch/Pages/OverviewPage.tsx index 4ef468c76a8..c82f9de7671 100644 --- a/fbw-common/src/systems/instruments/src/EFB/Dispatch/Pages/OverviewPage.tsx +++ b/fbw-common/src/systems/instruments/src/EFB/Dispatch/Pages/OverviewPage.tsx @@ -1,23 +1,106 @@ // Copyright (c) 2023-2024 FlyByWire Simulations // SPDX-License-Identifier: GPL-3.0 -import React from 'react'; -import { getAirframeType } from '@flybywiresim/flypad'; -import { A320Overview } from './Overview/A320_251N/A320Overview'; -import { A380Overview } from './Overview/A380_842/A380Overview'; +import React, { FC } from 'react'; +import { useSimVar, Units, AirframeType } from '@flybywiresim/fbw-sdk'; +import { IconPlane } from '@tabler/icons'; +import { Box, LightningFill, PeopleFill, Rulers, Speedometer2 } from 'react-bootstrap-icons'; +import { t, A320NoseOutline, A380NoseOutline, useAppSelector, getMaxPax } from '@flybywiresim/flypad'; + +interface InformationEntryProps { + title: string; + info: string; +} + +const InformationEntry: FC = ({ children, title, info }) => ( +
+
+ {children} +

{title}

+
+

{info}

+
+); export const OverviewPage = () => { - switch (getAirframeType()) { - case 'A320_251N': - return ( - - ); - case 'A380_842': - return ( - - ); - default: - return ( - - ); - } + let [airline] = useSimVar('ATC AIRLINE', 'String', 1_000); + + airline ||= 'FlyByWire Simulations'; + const [actualGrossWeight] = useSimVar('TOTAL WEIGHT', 'kilograms', 5_000); + + const getConvertedInfo = (metricValue: number, unitType: 'weight' |'volume' |'distance') => { + const numberWithCommas = (x: number) => x.toFixed(0).replace(/\B(?=(\d{3})+(?!\d))/g, ','); + + switch (unitType) { + case 'weight': + return `${numberWithCommas(Units.kilogramToUser(metricValue))} [${Units.userWeightSuffixEis2}]`; + case 'volume': + return `${numberWithCommas(Units.litreToUser(metricValue))} [${Units.userVolumeSuffixEis2}]`; + case 'distance': + return `${numberWithCommas(metricValue)} [nm]`; + default: throw new Error('Invalid unit type'); + } + }; + + const airframeInfo = useAppSelector((state) => state.config.airframeInfo); + + return ( +
+

{airframeInfo.name}

+

{airline}

+ +
+ {/* TODO: Make this SVG configurable */} + {airframeInfo.variant === AirframeType.A380_842 ? ( + + ) : ( + + )} +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + +
+
+
+ ); }; diff --git a/fbw-common/src/systems/instruments/src/EFB/Efb.tsx b/fbw-common/src/systems/instruments/src/EFB/Efb.tsx index 76b9fc936e7..f973e1ae27a 100644 --- a/fbw-common/src/systems/instruments/src/EFB/Efb.tsx +++ b/fbw-common/src/systems/instruments/src/EFB/Efb.tsx @@ -5,6 +5,8 @@ import React, { useEffect, useState } from 'react'; import { ChecklistJsonDefinition, FailureDefinition, + UniversalConfigProvider, + NXDataStore, NavigraphClient, SENTRY_CONSENT_KEY, SentryConsentState, @@ -13,14 +15,18 @@ import { usePersistentNumberProperty, usePersistentProperty, useSimVar, + ChecklistProvider, } from '@flybywiresim/fbw-sdk'; + +import { Provider } from 'react-redux'; +import { customAlphabet } from 'nanoid'; import { Redirect, Route, Switch, useHistory } from 'react-router-dom'; import { Battery } from 'react-bootstrap-icons'; import { ToastContainer } from 'react-toastify'; import { distanceTo } from 'msfs-geo'; import { ErrorBoundary } from 'react-error-boundary'; import { MemoryRouter as Router } from 'react-router'; -import { Provider } from 'react-redux'; +import { migrateSettings, readSettingsFromPersistentStorage, setAirframeInfo, setCabinInfo, setFlypadInfo } from '@flybywiresim/flypad'; import { Error as ErrorIcon } from './Assets/Error'; import { FailuresOrchestratorProvider } from './failures-orchestrator-provider'; import { AlertModal, ModalContainer, ModalProvider, useModals } from './UtilComponents/Modals/Modals'; @@ -51,17 +57,82 @@ import './Assets/Slider.scss'; import 'react-toastify/dist/ReactToastify.css'; import './toast.css'; +export interface EfbWrapperProps { + failures: FailureDefinition[], // TODO: Move failure definition into VFS +} + +export const EfbWrapper: React.FC = ({ failures }) => { + const setSessionId = () => { + const ALPHABET = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'; + const SESSION_ID_LENGTH = 14; + const nanoid = customAlphabet(ALPHABET, SESSION_ID_LENGTH); + const generatedSessionID = nanoid(); + + NXDataStore.set('A32NX_SENTRY_SESSION_ID', generatedSessionID); + }; + const [aircraftChecklists, setAircraftChecklists] = useState([]); + + useEffect(() => { + UniversalConfigProvider.fetchAirframeInfo( + process.env.AIRCRAFT_PROJECT_PREFIX, + process.env.AIRCRAFT_VARIANT, + ).then((info) => store.dispatch(setAirframeInfo(info))); + + UniversalConfigProvider.fetchFlypadInfo( + process.env.AIRCRAFT_PROJECT_PREFIX, + process.env.AIRCRAFT_VARIANT, + ).then((info) => store.dispatch(setFlypadInfo(info))); + + UniversalConfigProvider.fetchCabinInfo( + process.env.AIRCRAFT_PROJECT_PREFIX, + process.env.AIRCRAFT_VARIANT, + ).then((info) => store.dispatch(setCabinInfo(info))); + + ChecklistProvider.getInstance().readChecklist() + .then((aircraftChecklistsFromJson) => { + console.log('Checklists loaded'); + setAircraftChecklists(aircraftChecklistsFromJson); + }) + .catch((error) => { + console.error('Failed to load checklists', error); + }); + }, []); + + const setup = () => { + readSettingsFromPersistentStorage(); + migrateSettings(); + setSessionId(); + + // Needed to fetch METARs from the sim + RegisterViewListener('JS_LISTENER_FACILITY', () => { + console.log('JS_LISTENER_FACILITY registered.'); + }, true); + }; + + if (process.env.VITE_BUILD) { + window.addEventListener('AceInitialized', setup); + } else { + setup(); + } + + return ( + + + + ); +}; + const BATTERY_DURATION_CHARGE_MIN = 180; const BATTERY_DURATION_DISCHARGE_MIN = 540; const LoadingScreen = () => ( -
+
); const EmptyBatteryScreen = () => ( -
+
); @@ -90,13 +161,6 @@ interface BatteryStatus { export const usePower = () => React.useContext(PowerContext); -// this returns either `A380_842` or `A320_251N` depending on the aircraft -// TODO: this will be replaced and improved by PR #8599 -export function getAirframeType() { - return new URL(document.querySelectorAll('vcockpit-panel > *')[0].getAttribute('url')) - .searchParams.get('Airframe'); -} - interface EfbProps { aircraftChecklistsProp: ChecklistJsonDefinition[], } @@ -389,7 +453,7 @@ export const ErrorFallback = ({ resetErrorBoundary }: ErrorFallbackProps) => { const [sentryEnabled] = usePersistentProperty(SENTRY_CONSENT_KEY, SentryConsentState.Refused); return ( -
+
@@ -409,7 +473,7 @@ export const ErrorFallback = ({ resetErrorBoundary }: ErrorFallbackProps) => { )}

Reset Display

@@ -420,7 +484,7 @@ export const ErrorFallback = ({ resetErrorBoundary }: ErrorFallbackProps) => { ); }; -export interface EfbInstrumentProps { +interface EfbInstrumentProps { failures: FailureDefinition[], aircraftChecklists: ChecklistJsonDefinition[], } @@ -439,9 +503,7 @@ export const EfbInstrument: React.FC = ({ failures, aircraft setErr(false)} resetKeys={[err]}> - - - + diff --git a/fbw-common/src/systems/instruments/src/EFB/Ground/Pages/Fuel/Fuel.tsx b/fbw-common/src/systems/instruments/src/EFB/Ground/Pages/Fuel/Fuel.tsx index c0f8b39c109..1ff896230f5 100644 --- a/fbw-common/src/systems/instruments/src/EFB/Ground/Pages/Fuel/Fuel.tsx +++ b/fbw-common/src/systems/instruments/src/EFB/Ground/Pages/Fuel/Fuel.tsx @@ -3,24 +3,24 @@ /* eslint-disable max-len */ import React, { useState } from 'react'; -import { Units, useSimVar } from '@flybywiresim/fbw-sdk'; -import { getAirframeType, isSimbriefDataLoaded } from '@flybywiresim/flypad'; +import { AirframeType, Units, useSimVar } from '@flybywiresim/fbw-sdk'; +import { isSimbriefDataLoaded } from '@flybywiresim/flypad'; import { A320Fuel } from './A320_251N/A320Fuel'; import { A380Fuel } from './A380_842/A380Fuel'; import { useAppSelector } from '../../../Store/store'; export const Fuel = () => { + const airframeInfo = useAppSelector((state) => state.config.airframeInfo); const [isOnGround] = useSimVar('SIM ON GROUND', 'Bool', 8_059); const simbriefUnits = useAppSelector((state) => state.simbrief.data.units); const simbriefPlanRamp = useAppSelector((state) => state.simbrief.data.fuels.planRamp); - const simbriefDataLoaded = isSimbriefDataLoaded(); const [massUnitForDisplay] = useState(Units.usingMetric ? 'KGS' : 'LBS'); const [convertUnit] = useState(Units.usingMetric ? 1 : (1 / 0.4535934)); - switch (getAirframeType()) { - case 'A380_842': + switch (airframeInfo.variant) { + case AirframeType.A380_842: return ( { isOnGround={isOnGround} /> ); - case 'A320_251N': + case AirframeType.A320_251N: default: return ( = ({ {cgAxis} {weightAxis}

{usingMetric ? 'x 1000 kgs' : 'x 1000 lbs'}

-

{flightPhase <= 1 || flightPhase >= 7 ? 'MTOW' : 'FLIGHT'}

+

{flightPhase <= 1 || flightPhase >= 7 ? 'MTOW' : 'FLIGHT'}

MLDW

-

MZFW

+

MZFW

); }; diff --git a/fbw-common/src/systems/instruments/src/EFB/Ground/Pages/Payload/A320_251N/A320Payload.tsx b/fbw-common/src/systems/instruments/src/EFB/Ground/Pages/Payload/NarrowBody/A320Payload.tsx similarity index 88% rename from fbw-common/src/systems/instruments/src/EFB/Ground/Pages/Payload/A320_251N/A320Payload.tsx rename to fbw-common/src/systems/instruments/src/EFB/Ground/Pages/Payload/NarrowBody/A320Payload.tsx index 9024234f216..6bded09b8cc 100644 --- a/fbw-common/src/systems/instruments/src/EFB/Ground/Pages/Payload/A320_251N/A320Payload.tsx +++ b/fbw-common/src/systems/instruments/src/EFB/Ground/Pages/Payload/NarrowBody/A320Payload.tsx @@ -4,34 +4,21 @@ /* eslint-disable max-len */ import React, { useCallback, useEffect, useMemo, useState } from 'react'; import { CloudArrowDown } from 'react-bootstrap-icons'; -import { SeatFlags, Units, usePersistentNumberProperty, usePersistentProperty, useSeatFlags, useSimVar } from '@flybywiresim/fbw-sdk'; +import { CargoStationInfo, PaxStationInfo, SeatFlags, Units, usePersistentNumberProperty, usePersistentProperty, useSeatFlags, useSimVar } from '@flybywiresim/fbw-sdk'; import { setPayloadImported, useAppDispatch, Card, t, TooltipWrapper, SelectGroup, SelectItem, PromptModal, useModals } from '@flybywiresim/flypad'; import { SeatOutlineBg } from '../../../../Assets/SeatOutlineBg'; import { BoardingInput, MiscParamsInput, PayloadInputTable } from '../PayloadElements'; import { CargoWidget } from './CargoWidget'; import { ChartWidget } from '../Chart/ChartWidget'; -import { CargoStationInfo, PaxStationInfo } from '../Seating/Constants'; -import Loadsheet from './a20nv55.json'; import { SeatMapWidget } from '../Seating/SeatMapWidget'; - -interface A320Props { - simbriefUnits: string, - simbriefBagWeight: number, - simbriefPaxWeight: number, - simbriefPax: number, - simbriefBag: number, - simbriefFreight: number, - simbriefDataLoaded: boolean, - payloadImported: boolean, - massUnitForDisplay: string, - isOnGround: boolean, - - boardingStarted: boolean, - boardingRate: string, - setBoardingStarted: (boardingStarted: any) => void, - setBoardingRate: (boardingRate: any) => void, -} -export const A320Payload: React.FC = ({ +import { PayloadProps } from '../PayloadPage'; + +export const A320Payload: React.FC = ({ + airframeInfo, + flypadInfo, + cabinInfo, + maxPax, + maxCargo, simbriefUnits, simbriefBagWeight, simbriefPaxWeight, @@ -49,29 +36,29 @@ export const A320Payload: React.FC = ({ }) => { const { showModal } = useModals(); - const [aFlags] = useSeatFlags(`L:${Loadsheet.seatMap[0].simVar}`, Loadsheet.seatMap[0].capacity, 509); - const [bFlags] = useSeatFlags(`L:${Loadsheet.seatMap[1].simVar}`, Loadsheet.seatMap[1].capacity, 541); - const [cFlags] = useSeatFlags(`L:${Loadsheet.seatMap[2].simVar}`, Loadsheet.seatMap[2].capacity, 569); - const [dFlags] = useSeatFlags(`L:${Loadsheet.seatMap[3].simVar}`, Loadsheet.seatMap[3].capacity, 593); + const [aFlags] = useSeatFlags(`L:${cabinInfo.seatMap[0].simVar}`, cabinInfo.seatMap[0].capacity, 509); + const [bFlags] = useSeatFlags(`L:${cabinInfo.seatMap[1].simVar}`, cabinInfo.seatMap[1].capacity, 541); + const [cFlags] = useSeatFlags(`L:${cabinInfo.seatMap[2].simVar}`, cabinInfo.seatMap[2].capacity, 569); + const [dFlags] = useSeatFlags(`L:${cabinInfo.seatMap[3].simVar}`, cabinInfo.seatMap[3].capacity, 593); - const [aFlagsDesired, setAFlagsDesired] = useSeatFlags(`L:${Loadsheet.seatMap[0].simVar}_DESIRED`, Loadsheet.seatMap[0].capacity, 379); - const [bFlagsDesired, setBFlagsDesired] = useSeatFlags(`L:${Loadsheet.seatMap[1].simVar}_DESIRED`, Loadsheet.seatMap[1].capacity, 421); - const [cFlagsDesired, setCFlagsDesired] = useSeatFlags(`L:${Loadsheet.seatMap[2].simVar}_DESIRED`, Loadsheet.seatMap[2].capacity, 457); - const [dFlagsDesired, setDFlagsDesired] = useSeatFlags(`L:${Loadsheet.seatMap[3].simVar}_DESIRED`, Loadsheet.seatMap[3].capacity, 499); + const [aFlagsDesired, setAFlagsDesired] = useSeatFlags(`L:${cabinInfo.seatMap[0].simVar}_DESIRED`, cabinInfo.seatMap[0].capacity, 379); + const [bFlagsDesired, setBFlagsDesired] = useSeatFlags(`L:${cabinInfo.seatMap[1].simVar}_DESIRED`, cabinInfo.seatMap[1].capacity, 421); + const [cFlagsDesired, setCFlagsDesired] = useSeatFlags(`L:${cabinInfo.seatMap[2].simVar}_DESIRED`, cabinInfo.seatMap[2].capacity, 457); + const [dFlagsDesired, setDFlagsDesired] = useSeatFlags(`L:${cabinInfo.seatMap[3].simVar}_DESIRED`, cabinInfo.seatMap[3].capacity, 499); const activeFlags = useMemo(() => [aFlags, bFlags, cFlags, dFlags], [aFlags, bFlags, cFlags, dFlags]); const desiredFlags = useMemo(() => [aFlagsDesired, bFlagsDesired, cFlagsDesired, dFlagsDesired], [aFlagsDesired, bFlagsDesired, cFlagsDesired, dFlagsDesired]); const setDesiredFlags = useMemo(() => [setAFlagsDesired, setBFlagsDesired, setCFlagsDesired, setDFlagsDesired], []); - const [fwdBag] = useSimVar(`L:${Loadsheet.cargoMap[0].simVar}`, 'Number', 719); - const [aftCont] = useSimVar(`L:${Loadsheet.cargoMap[1].simVar}`, 'Number', 743); - const [aftBag] = useSimVar(`L:${Loadsheet.cargoMap[2].simVar}`, 'Number', 769); - const [aftBulk] = useSimVar(`L:${Loadsheet.cargoMap[3].simVar}`, 'Number', 797); + const [fwdBag] = useSimVar(`L:${cabinInfo.cargoMap[0].simVar}`, 'Number', 719); + const [aftCont] = useSimVar(`L:${cabinInfo.cargoMap[1].simVar}`, 'Number', 743); + const [aftBag] = useSimVar(`L:${cabinInfo.cargoMap[2].simVar}`, 'Number', 769); + const [aftBulk] = useSimVar(`L:${cabinInfo.cargoMap[3].simVar}`, 'Number', 797); - const [fwdBagDesired, setFwdBagDesired] = useSimVar(`L:${Loadsheet.cargoMap[0].simVar}_DESIRED`, 'Number', 619); - const [aftContDesired, setAftContDesired] = useSimVar(`L:${Loadsheet.cargoMap[1].simVar}_DESIRED`, 'Number', 631); - const [aftBagDesired, setAftBagDesired] = useSimVar(`L:${Loadsheet.cargoMap[2].simVar}_DESIRED`, 'Number', 641); - const [aftBulkDesired, setAftBulkDesired] = useSimVar(`L:${Loadsheet.cargoMap[3].simVar}_DESIRED`, 'Number', 677); + const [fwdBagDesired, setFwdBagDesired] = useSimVar(`L:${cabinInfo.cargoMap[0].simVar}_DESIRED`, 'Number', 619); + const [aftContDesired, setAftContDesired] = useSimVar(`L:${cabinInfo.cargoMap[1].simVar}_DESIRED`, 'Number', 631); + const [aftBagDesired, setAftBagDesired] = useSimVar(`L:${cabinInfo.cargoMap[2].simVar}_DESIRED`, 'Number', 641); + const [aftBulkDesired, setAftBulkDesired] = useSimVar(`L:${cabinInfo.cargoMap[3].simVar}_DESIRED`, 'Number', 677); const cargo = useMemo(() => [fwdBag, aftCont, aftBag, aftBulk], [fwdBag, aftCont, aftBag, aftBulk]); const cargoDesired = useMemo(() => [fwdBagDesired, aftContDesired, aftBagDesired, aftBulkDesired], [fwdBagDesired, aftContDesired, aftBagDesired, aftBulkDesired]); @@ -83,11 +70,8 @@ export const A320Payload: React.FC = ({ const [emptyWeight] = useState(SimVar.GetSimVarValue('A:EMPTY WEIGHT', 'Kilograms')); - const [seatMap] = useState(Loadsheet.seatMap); - const [cargoMap] = useState(Loadsheet.cargoMap); - - const maxPax = useMemo(() => seatMap.reduce((a, b) => a + b.capacity, 0), [seatMap]); - const maxCargo = useMemo(() => cargoMap.reduce((a, b) => a + b.weight, 0), [cargoMap]); + const [seatMap] = useState(cabinInfo.seatMap); + const [cargoMap] = useState(cabinInfo.cargoMap); // Calculate Total Pax from Pax Flags const totalPax = useMemo(() => { @@ -203,7 +187,7 @@ export const A320Payload: React.FC = ({ fillStation(i, parseFloat(Number((Math.ceil((seatMap[i].capacity / maxPax) * 1e2) / 1e2).toExponential(2)).toPrecision(3)), numOfPax); } fillStation(0, 1, paxRemaining); - }, [maxPax, ...seatMap, totalPaxDesired]); + }, [maxPax, seatMap, totalPaxDesired]); const setTargetCargo = useCallback((numberOfPax: number, freight: number, perBagWeight: number = paxBagWeight) => { const bagWeight = numberOfPax * perBagWeight; @@ -211,7 +195,7 @@ export const A320Payload: React.FC = ({ let remainingWeight = loadableCargoWeight; - async function fillCargo(station: number, percent: number, loadableCargoWeight: number) { + function fillCargo(station: number, percent: number, loadableCargoWeight: number) { const c = Math.round(percent * loadableCargoWeight); remainingWeight -= c; setCargoDesired[station](c); @@ -221,7 +205,7 @@ export const A320Payload: React.FC = ({ fillCargo(i, cargoMap[i].weight / maxCargo, loadableCargoWeight); } fillCargo(0, 1, remainingWeight); - }, [maxCargo, ...cargoMap, ...cargoDesired, paxBagWeight]); + }, [maxCargo, cargoMap, ...cargoDesired, paxBagWeight]); const processZfw = useCallback((newZfw) => { let paxCargoWeight = newZfw - emptyWeight; @@ -364,10 +348,10 @@ export const A320Payload: React.FC = ({ // Init useEffect(() => { if (paxWeight === 0) { - setPaxWeight(Math.round(Loadsheet.specs.pax.defaultPaxWeight)); + setPaxWeight(Math.round(cabinInfo.defaultPaxWeight)); } if (paxBagWeight === 0) { - setPaxBagWeight(Math.round(Loadsheet.specs.pax.defaultBagWeight)); + setPaxBagWeight(Math.round(cabinInfo.defaultBagWeight)); } }, []); @@ -396,6 +380,8 @@ export const A320Payload: React.FC = ({ setTargetPax(0); setTargetCargo(0, 0); break; + case gsxStates.PERFORMING: + case gsxStates.COMPLETED: default: break; } @@ -476,7 +462,19 @@ export const A320Payload: React.FC = ({
- +
@@ -486,7 +484,7 @@ export const A320Payload: React.FC = ({
= ({
= ({ = ({ cargo, cargoDesired, cargoMap, onClickCargo }) => ( <> -
+
-
+
diff --git a/fbw-common/src/systems/instruments/src/EFB/Ground/Pages/Payload/PayloadElements.tsx b/fbw-common/src/systems/instruments/src/EFB/Ground/Pages/Payload/PayloadElements.tsx index c4af5474db9..bdd865870f7 100644 --- a/fbw-common/src/systems/instruments/src/EFB/Ground/Pages/Payload/PayloadElements.tsx +++ b/fbw-common/src/systems/instruments/src/EFB/Ground/Pages/Payload/PayloadElements.tsx @@ -4,14 +4,8 @@ /* eslint-disable max-len */ import React from 'react'; import { ArrowLeftRight, BoxArrowRight, BriefcaseFill, CaretDownFill, PersonFill, Shuffle, StopCircleFill } from 'react-bootstrap-icons'; -import { Units } from '@flybywiresim/fbw-sdk'; +import { AirframeInfo, Units } from '@flybywiresim/fbw-sdk'; import { ProgressBar, t, TooltipWrapper, SimpleInput } from '@flybywiresim/flypad'; -import { CargoStationInfo, PaxStationInfo } from './Seating/Constants'; - -export type Loadsheet = { - specs: AirframeSpec, - seatMap: PaxStationInfo[] -} export type AirframeSpec = { prefix: string, @@ -61,6 +55,16 @@ export const PayloadValueInput: React.FC = ({ min, max,
); +// TODO: To be removed, relocated from Constants +interface CargoStationInfo { + name: string, + weight: number, + simVar: string, + stationIndex: number, + progressBarWidth: number, + position: number, +} + interface CargoBarProps { cargoId: number, cargo: number[], @@ -244,7 +248,7 @@ export const PayloadPercentUnitDisplay: React.FC<{value: number}> = ({ value }) }; interface PayloadInputTableProps { - loadsheet: Loadsheet, + airframeInfo: AirframeInfo, emptyWeight: number, massUnitForDisplay: string, displayZfw: boolean, @@ -273,7 +277,7 @@ interface PayloadInputTableProps { export const PayloadInputTable: React.FC = ( { - loadsheet, emptyWeight, massUnitForDisplay, + airframeInfo, emptyWeight, massUnitForDisplay, BoardingInProgress, displayZfw, totalPax, totalPaxDesired, maxPax, @@ -364,11 +368,11 @@ export const PayloadInputTable: React.FC = ( {(displayZfw ? ( - +
{ if (!Number.isNaN(parseInt(x)) || parseInt(x) === 0) processZfw(Units.userToKilogram(parseInt(x))); @@ -380,11 +384,11 @@ export const PayloadInputTable: React.FC = ( ) : ( - +
{ if (!Number.isNaN(parseInt(x)) || parseInt(x) === 0) processGw(Units.userToKilogram(parseInt(x))); @@ -415,7 +419,7 @@ export const PayloadInputTable: React.FC = ( @@ -310,7 +315,7 @@ export const PushbackMap = () => { diff --git a/fbw-common/src/systems/instruments/src/EFB/Ground/Pages/Services/A380_842/A380Services.tsx b/fbw-common/src/systems/instruments/src/EFB/Ground/Pages/Services/A380_842/A380Services.tsx index 30e997c3b0a..aaadff6faad 100644 --- a/fbw-common/src/systems/instruments/src/EFB/Ground/Pages/Services/A380_842/A380Services.tsx +++ b/fbw-common/src/systems/instruments/src/EFB/Ground/Pages/Services/A380_842/A380Services.tsx @@ -37,7 +37,7 @@ interface ServiceButtonWrapperProps { // This groups buttons and sets a border and divider line const ServiceButtonWrapper: FC = ({ children, className, xl, xr, y }) => (
{children} @@ -510,13 +510,13 @@ export const A380Services: React.FC = () => { const doorOpenCss = 'text-2xl font-bold text-utility-green w-min'; return ( -
+
= 1.0} main2LeftStatus={main2LeftDoorOpen >= 1.0} main4RightStatus={main4RightDoorOpen >= 1.0} upper1LeftStatus={upper1LeftDoorOpen >= 1.0} - className="inset-x-0 mx-auto h-full w-full text-theme-text" + className="text-theme-text inset-x-0 mx-auto h-full w-full" /> diff --git a/fbw-common/src/systems/instruments/src/EFB/Ground/Pages/Services/ServicesPage.tsx b/fbw-common/src/systems/instruments/src/EFB/Ground/Pages/Services/ServicesPage.tsx index e03d311d8d1..ea0a308fbd3 100644 --- a/fbw-common/src/systems/instruments/src/EFB/Ground/Pages/Services/ServicesPage.tsx +++ b/fbw-common/src/systems/instruments/src/EFB/Ground/Pages/Services/ServicesPage.tsx @@ -2,20 +2,22 @@ // SPDX-License-Identifier: GPL-3.0 /* eslint-disable no-console */ -import React, { useState } from 'react'; -import { getAirframeType } from '@flybywiresim/flypad'; +import React from 'react'; +import { AirframeType } from '@flybywiresim/fbw-sdk'; +import { useAppSelector } from '@flybywiresim/flypad'; import { A380Services } from './A380_842/A380Services'; import { A320Services } from './A320_251N/A320Services'; export const ServicesPage = () => { - const [airframe] = useState(getAirframeType()); + // TODO: Configurable Services Page vs A380/A320 + const airframeInfo = useAppSelector((state) => state.config.airframeInfo); - switch (airframe) { - case 'A380_842': + switch (airframeInfo.variant) { + case AirframeType.A380_842: return ( ); - case 'A320_251N': + case AirframeType.A320_251N: default: return ( diff --git a/fbw-common/src/systems/instruments/src/EFB/Localization/data/en.json b/fbw-common/src/systems/instruments/src/EFB/Localization/data/en.json index f37e80be326..86b7e1a4d4d 100644 --- a/fbw-common/src/systems/instruments/src/EFB/Localization/data/en.json +++ b/fbw-common/src/systems/instruments/src/EFB/Localization/data/en.json @@ -164,6 +164,11 @@ "LoadingTime": "Loading Time", "Passengers": "Passengers", "Planned": "Planned", + "SelectItem": { + "MainDeck": "Main", + "UpperDeck": "Upper", + "CargoDeck": "Cargo" + }, "TT": { "AircraftMustBeColdAndDarkToChangeBoardingTimes": "Aircraft Must Be On the Ground and Have Engines Shutdown to Change Boarding Duration", "FillPayloadFromSimbrief": "Fill Payload Information from Simbrief", diff --git a/fbw-common/src/systems/instruments/src/EFB/Settings/Pages/AboutPage.tsx b/fbw-common/src/systems/instruments/src/EFB/Settings/Pages/AboutPage.tsx index 40e5b1ddd3f..2b441aa780a 100644 --- a/fbw-common/src/systems/instruments/src/EFB/Settings/Pages/AboutPage.tsx +++ b/fbw-common/src/systems/instruments/src/EFB/Settings/Pages/AboutPage.tsx @@ -2,9 +2,8 @@ // SPDX-License-Identifier: GPL-3.0 import React, { useEffect, useState } from 'react'; -import { usePersistentProperty, useSessionStorage, AircraftVersionChecker, BuildInfo, SentryConsentState, SENTRY_CONSENT_KEY } from '@flybywiresim/fbw-sdk'; +import { usePersistentProperty, useSessionStorage, AircraftGithubVersionChecker, BuildInfo, SentryConsentState, SENTRY_CONSENT_KEY, useSimVar } from '@flybywiresim/fbw-sdk'; import { t } from '@flybywiresim/flypad'; -import { getAirframeType } from '../../Efb'; import { SettingsPage } from '../Settings'; // @ts-ignore import FbwTail from '../../Assets/FBW-Tail.svg'; @@ -46,6 +45,7 @@ const BuildInfoEntry = ({ title, value, underline = 0 }: BuildInfoEntryProps) => }; export const AboutPage = () => { + const [title] = useSimVar('TITLE', 'string'); const [buildInfo, setBuildInfo] = useState(undefined); const [sessionId] = usePersistentProperty('A32NX_SENTRY_SESSION_ID'); const [version, setVersion] = useSessionStorage('SIM_VERSION', ''); @@ -60,10 +60,10 @@ export const AboutPage = () => { useViewListenerEvent('JS_LISTENER_COMMUNITY', 'SetGamercardInfo', onSetPlayerData); useEffect(() => { - AircraftVersionChecker.getBuildInfo( - getAirframeType() === 'A320_251N' ? 'a32nx' : 'a380x', + AircraftGithubVersionChecker.getBuildInfo( + process.env.AIRCRAFT_PROJECT_PREFIX, ).then((info) => setBuildInfo(info)); - }, []); + }, [process.env.AIRCRAFT_PROJECT_PREFIX]); return ( @@ -84,7 +84,7 @@ export const AboutPage = () => {
-

© 2020-2022 FlyByWire Simulations and its contributors, all rights reserved.

+

© 2020-2024 FlyByWire Simulations and its contributors, all rights reserved.

Licensed under the GNU General Public License Version 3

@@ -93,6 +93,7 @@ export const AboutPage = () => {
+ diff --git a/fbw-common/src/systems/instruments/src/EFB/Settings/ThrottleConfig/ThrottleConfig.tsx b/fbw-common/src/systems/instruments/src/EFB/Settings/ThrottleConfig/ThrottleConfig.tsx index c622a227d2d..be5ee1a96aa 100644 --- a/fbw-common/src/systems/instruments/src/EFB/Settings/ThrottleConfig/ThrottleConfig.tsx +++ b/fbw-common/src/systems/instruments/src/EFB/Settings/ThrottleConfig/ThrottleConfig.tsx @@ -5,7 +5,7 @@ import React, { useEffect, useState } from 'react'; import { usePersistentNumberProperty, useSimVar } from '@flybywiresim/fbw-sdk'; import { ExclamationCircleFill } from 'react-bootstrap-icons'; -import { getAirframeType } from '../../Efb'; +import { useAppSelector } from '@flybywiresim/flypad'; import { t } from '../../Localization/translation'; import { Toggle } from '../../UtilComponents/Form/Toggle'; import { SelectGroup, SelectItem, VerticalSelectGroup } from '../../UtilComponents/Form/Select'; @@ -36,12 +36,15 @@ interface ThrottleConfigProps { * @constructor */ export const ThrottleConfig = ({ isShown, onClose }: ThrottleConfigProps) => { - const [airframe] = useState(getAirframeType()); + const flypadInfo = useAppSelector((state) => state.config.flypadInfo); - const [axisNum, setAxisNum] = usePersistentNumberProperty('THROTTLE_AXIS', airframe === 'A380_842' ? 4 : 2); + // the number of throttles that are used in the aircraft (2 or 4) + const numberOfThrottles = flypadInfo.throttle.numberOfAxis; + + const [axisNum, setAxisNum] = usePersistentNumberProperty('THROTTLE_AXIS', numberOfThrottles); // this makes sure that the axis number is set to 2 when the A320 is selected when previously the A380 with 4 axis was used - if (airframe !== 'A380_842' && axisNum === 4) { - setAxisNum(2); + if (axisNum > numberOfThrottles) { + setAxisNum(numberOfThrottles); } const [selectedDetent, setSelectedDetent] = useState(2); @@ -63,14 +66,6 @@ export const ThrottleConfig = ({ isShown, onClose }: ThrottleConfigProps) => { const { showModal } = useModals(); - // the number of throttles that are used in the aircraft (2 or 4) - const numberOfThrottles = getAirframeType() === 'A380_842' ? 4 : 2; - - // this makes sure that the axis number is set to 2 when the A320 is selected when previously the A380 with 4 axis was used - if (airframe !== 'A380_842' && axisNum === 4) { - setAxisNum(2); - } - // simvars for each virtual throttle (we define 4 even for the A320 and ignore 3 + 4) const throttleOneSimvars: Array = [ new ThrottleSimvar('Reverse Full', 'L:A32NX_THROTTLE_MAPPING_REVERSE_', 1), @@ -143,7 +138,7 @@ export const ThrottleConfig = ({ isShown, onClose }: ThrottleConfigProps) => { ...getOverlapErrors(2, throttleTwoSimvars), ]; // to avoid false errors on the A320 when only 2 axis are used - if (airframe === 'A380_842') { + if (numberOfThrottles === 4) { errors.push(...getOverlapErrors(3, throttleThreeSimvars)); errors.push(...getOverlapErrors(4, throttleFourSimvars)); } @@ -221,27 +216,16 @@ export const ThrottleConfig = ({ isShown, onClose }: ThrottleConfigProps) => { const axisSelectGroup = ( - setAxisNum(1)} - > - 1 - - setAxisNum(2)} - > - 2 - - {airframe === 'A380_842' && ( + {flypadInfo.throttle.axisOptions.map((option) => ( setAxisNum(4)} + selected={axisNum === option} + onSelect={() => setAxisNum(option)} > - 4 + {option} - )} + ))} + ); const oneAxis = ( @@ -351,13 +335,13 @@ export const ThrottleConfig = ({ isShown, onClose }: ThrottleConfigProps) => { const getAxis = () => { switch (axisNum) { case 4: - if (airframe === 'A380_842') { + if (flypadInfo.throttle.axisOptions.includes(axisNum)) { return fourAxis; } console.warn('A320 does not have 4 axis - defaulting to 2 axis'); return twoAxisA320; case 2: - if (airframe === 'A380_842') { + if (flypadInfo.throttle.axisOptions.includes(4)) { return twoAxisA380; } return twoAxisA320; @@ -370,10 +354,10 @@ export const ThrottleConfig = ({ isShown, onClose }: ThrottleConfigProps) => { if (!isShown) return null; return ( -
+
-
+
{t('Settings.ThrottleConfig.TogaOnAxis')}
setTogaOnAxis(value ? 1 : 0)} /> @@ -392,7 +376,7 @@ export const ThrottleConfig = ({ isShown, onClose }: ThrottleConfigProps) => { {/* To make sure users map throttles 1+2 to axis 1 and 3+4 to axis 2 and not any other grouping */} {validConfig && numberOfThrottles === 4 && axisNum === 2 && ( -
+

{t('Settings.ThrottleConfig.FourThrottleWarning')}

@@ -400,8 +384,8 @@ export const ThrottleConfig = ({ isShown, onClose }: ThrottleConfigProps) => { )} {!validConfig && ( -
-
+
+

@@ -411,12 +395,12 @@ export const ThrottleConfig = ({ isShown, onClose }: ThrottleConfigProps) => { )}

-
+
@@ -435,7 +419,7 @@ export const ThrottleConfig = ({ isShown, onClose }: ThrottleConfigProps) => { />, ); }} - className="rounded-md border-2 border-theme-highlight bg-theme-highlight px-5 py-2.5 text-theme-body transition duration-100 hover:bg-theme-body hover:text-theme-highlight" + className="border-theme-highlight bg-theme-highlight text-theme-body hover:bg-theme-body hover:text-theme-highlight rounded-md border-2 px-5 py-2.5 transition duration-100" > {t('Settings.ThrottleConfig.ResetToDefaults')} @@ -444,7 +428,7 @@ export const ThrottleConfig = ({ isShown, onClose }: ThrottleConfigProps) => { onClick={() => { syncToThrottle(1); }} - className="rounded-md border-2 border-theme-highlight bg-theme-highlight px-5 py-2.5 text-theme-body transition duration-100 hover:bg-theme-body hover:text-theme-highlight" + className="border-theme-highlight bg-theme-highlight text-theme-body hover:bg-theme-body hover:text-theme-highlight rounded-md border-2 px-5 py-2.5 transition duration-100" > {t('Settings.ThrottleConfig.LoadFromFile')} @@ -467,7 +451,7 @@ export const ThrottleConfig = ({ isShown, onClose }: ThrottleConfigProps) => { }} disabled={!validConfig} className={`rounded-md border-2 px-5 py-2.5 transition duration-100 ${validConfig - ? 'border-green-400 bg-green-400 text-theme-body hover:bg-theme-body hover:text-green-400' + ? 'text-theme-body hover:bg-theme-body border-green-400 bg-green-400 hover:text-green-400' : 'border-theme-accent bg-theme-accent opacity-30'}`} > {t('Settings.ThrottleConfig.SaveAndApply')} diff --git a/fbw-common/src/systems/instruments/src/EFB/Store/features/config.ts b/fbw-common/src/systems/instruments/src/EFB/Store/features/config.ts new file mode 100644 index 00000000000..00232982217 --- /dev/null +++ b/fbw-common/src/systems/instruments/src/EFB/Store/features/config.ts @@ -0,0 +1,43 @@ +/* eslint-disable max-len */ +// Copyright (c) 2023-2024 FlyByWire Simulations +// SPDX-License-Identifier: GPL-3.0 + +import { createSlice, PayloadAction } from '@reduxjs/toolkit'; +import { AirframeInfo, CabinInfo, FlypadInfo } from '@flybywiresim/fbw-sdk'; +import { store, RootState } from '../store'; + +interface AircraftState { + airframeInfo: AirframeInfo; + flypadInfo: FlypadInfo; + cabinInfo: CabinInfo; +} + +const initialState: AircraftState = { + airframeInfo: null, + flypadInfo: null, + cabinInfo: null, +}; + +export const configSlice = createSlice({ + name: 'config', + initialState, + reducers: { + setAirframeInfo: (state, action: PayloadAction) => { + state.airframeInfo = action.payload; + }, + setFlypadInfo: (state, action: PayloadAction) => { + state.flypadInfo = action.payload; + }, + setCabinInfo: (state, action: PayloadAction) => { + state.cabinInfo = action.payload; + }, + }, +}); + +export const { setAirframeInfo, setFlypadInfo, setCabinInfo } = configSlice.actions; + +export const getMaxPax = (): number => (store.getState() as RootState).config.cabinInfo.seatMap.reduce((count, station) => count + station.rows.reduce((stationCount, row) => stationCount + row.seats.length, 0), 0); + +export const getMaxCargo = (): number => (store.getState() as RootState).config.cabinInfo.cargoMap.reduce((a, b) => a + b.weight, 0); + +export default configSlice.reducer; diff --git a/fbw-common/src/systems/instruments/src/EFB/Store/features/payload.ts b/fbw-common/src/systems/instruments/src/EFB/Store/features/payload.ts new file mode 100644 index 00000000000..5dfc73de176 --- /dev/null +++ b/fbw-common/src/systems/instruments/src/EFB/Store/features/payload.ts @@ -0,0 +1,20 @@ +// Copyright (c) 2023-2024 FlyByWire Simulations +// SPDX-License-Identifier: GPL-3.0 + +import { createSlice, PayloadAction } from '@reduxjs/toolkit'; + +export const payloadInitialState: {displayPaxMainDeck: boolean} = { displayPaxMainDeck: true }; + +export const payloadSlice = createSlice({ + name: 'payload', + initialState: payloadInitialState, + reducers: { + setDisplayPaxMainDeck: (state, action: PayloadAction) => { + state.displayPaxMainDeck = action.payload; + }, + }, +}); + +export const { setDisplayPaxMainDeck } = payloadSlice.actions; + +export default payloadSlice.reducer; diff --git a/fbw-common/src/systems/instruments/src/EFB/Store/features/simBrief.ts b/fbw-common/src/systems/instruments/src/EFB/Store/features/simBrief.ts index 98785d9cea7..9b0453af20c 100644 --- a/fbw-common/src/systems/instruments/src/EFB/Store/features/simBrief.ts +++ b/fbw-common/src/systems/instruments/src/EFB/Store/features/simBrief.ts @@ -146,8 +146,8 @@ export const simbriefSlice = createSlice({ }, }); -export async function fetchSimbriefDataAction(naivgraphUsername: string, overrideSimbriefID: string): Promise> { - const returnedSimbriefData = await getSimbriefData(naivgraphUsername, overrideSimbriefID); +export async function fetchSimbriefDataAction(navigraphUsername: string, overrideSimbriefID: string): Promise> { + const returnedSimbriefData = await getSimbriefData(navigraphUsername, overrideSimbriefID); return setSimbriefData({ airline: returnedSimbriefData.airline, diff --git a/fbw-common/src/systems/instruments/src/EFB/Store/reducers.ts b/fbw-common/src/systems/instruments/src/EFB/Store/reducers.ts index e15b08eec65..caac20e1614 100644 --- a/fbw-common/src/systems/instruments/src/EFB/Store/reducers.ts +++ b/fbw-common/src/systems/instruments/src/EFB/Store/reducers.ts @@ -17,6 +17,8 @@ import keyboardReducer from './features/keyboard'; import dispatchPageReducer from './features/dispatchPage'; import failuresPageReducer from './features/failuresPage'; import pushbackReducer from './features/pushback'; +import payloadReducer from './features/payload'; +import configReducer from './features/config'; export const createRootReducer = (history: any) => combineReducers({ router: connectRouter(history), @@ -32,4 +34,6 @@ export const createRootReducer = (history: any) => combineReducers({ dispatchPage: dispatchPageReducer, failuresPage: failuresPageReducer, pushback: pushbackReducer, + payload: payloadReducer, + config: configReducer, }); diff --git a/fbw-common/src/systems/instruments/src/EFB/Store/store.ts b/fbw-common/src/systems/instruments/src/EFB/Store/store.ts index e9fd296116f..19a4069b310 100644 --- a/fbw-common/src/systems/instruments/src/EFB/Store/store.ts +++ b/fbw-common/src/systems/instruments/src/EFB/Store/store.ts @@ -19,6 +19,8 @@ import dispatchPageReducer from './features/dispatchPage'; import failuresPageReducer from './features/failuresPage'; import tooltipReducer from './features/tooltip'; import pushbackReducer from './features/pushback'; +import payloadReducer from './features/payload'; +import configReducer from './features/config'; export type RootState = ReturnType; export type AppDispatch = typeof store.dispatch; @@ -39,11 +41,19 @@ const combinedReducer = combineReducers({ failuresPage: failuresPageReducer, tooltip: tooltipReducer, pushback: pushbackReducer, + payload: payloadReducer, + config: configReducer, }); const rootReducer: Reducer = (state: RootState, action: AnyAction) => { if (action.type === EFB_CLEAR_STATE) { - state = {} as RootState; + for (const key in state) { + // TODO: Exclude checklist from state clear, while resetting all items to un-completed. + // Items to exclude from state clear + if (key !== 'config') { + delete state[key]; + } + } } return combinedReducer(state, action); diff --git a/fbw-common/src/systems/instruments/src/EFB/index.ts b/fbw-common/src/systems/instruments/src/EFB/index.ts index 992f604b28b..43caacf92d0 100644 --- a/fbw-common/src/systems/instruments/src/EFB/index.ts +++ b/fbw-common/src/systems/instruments/src/EFB/index.ts @@ -16,6 +16,8 @@ export * from './Settings/sync'; export * from './Store/features/dispatchPage'; export * from './Store/features/groundServicePage'; export * from './Store/features/simBrief'; +export * from './Store/features/payload'; +export * from './Store/features/config'; export * from './Store/store'; export * from './UtilComponents/BingMap'; export * from './UtilComponents/Card/Card'; diff --git a/fbw-common/src/systems/instruments/src/EFB/vite.config.ts b/fbw-common/src/systems/instruments/src/EFB/vite.config.ts index 73b7e4be2ac..3fa8725d53e 100644 --- a/fbw-common/src/systems/instruments/src/EFB/vite.config.ts +++ b/fbw-common/src/systems/instruments/src/EFB/vite.config.ts @@ -11,7 +11,7 @@ import dotenv from 'dotenv'; dotenv.config({ path: '../../../../../../.env' }); -const envVarsToReplace = ['CLIENT_ID', 'CLIENT_SECRET', 'SENTRY_DSN']; +const envVarsToReplace = ['CLIENT_ID', 'CLIENT_SECRET', 'SENTRY_DSN', 'AIRCRAFT_PROJECT_PREFIX', 'AIRCRAFT_VARIANT']; export default defineConfig({ css: { diff --git a/fbw-common/src/systems/instruments/src/react/bitFlags.tsx b/fbw-common/src/systems/instruments/src/react/bitFlags.tsx index 0128cdc0d61..1127785c90d 100644 --- a/fbw-common/src/systems/instruments/src/react/bitFlags.tsx +++ b/fbw-common/src/systems/instruments/src/react/bitFlags.tsx @@ -1,5 +1,5 @@ import { useCallback, useMemo, useRef, useState } from 'react'; -import { SeatFlags } from '../../../shared/src'; +import { PaxStationInfo, SeatFlags } from '../../../shared/src'; import { useSimVarList } from './simVars'; import { useUpdate } from './hooks'; @@ -53,7 +53,7 @@ export const useSeatFlags = ( }; export const useSeatMap = ( - Loadsheet: any, + seatMap: PaxStationInfo[], ) : [ SeatFlags[], SeatFlags[], @@ -74,53 +74,51 @@ export const useSeatMap = ( const desiredUnits: string[] = []; const activeNames: string[] = []; const activeUnits: string[] = []; - Loadsheet.seatMap.forEach((station) => { - desiredNames.push(`L:${station.bitFlags}_DESIRED`); + seatMap.forEach((station) => { + desiredNames.push(`L:${station.simVar}_DESIRED`); desiredUnits.push('number'); - activeNames.push(`L:${station.bitFlags}`); + activeNames.push(`L:${station.simVar}`); activeUnits.push('number'); }); return [desiredNames, desiredUnits, activeNames, activeUnits]; - }, [Loadsheet]); + }, [seatMap]); - const [desiredBitVars] = useSimVarList(desiredVarNames, desiredVarUnits); - const [activeBitVars] = useSimVarList(activeVarNames, activeVarUnits); + const [desiredBitVars] = useSimVarList(desiredVarNames, desiredVarUnits, 379); + const [activeBitVars] = useSimVarList(activeVarNames, activeVarUnits, 379); const setActiveFlags = useCallback((value: SeatFlags, index: number) => { - SimVar.SetSimVarValue(`L:${Loadsheet.seatMap[index].bitFlags}`, 'string', value.toString()).catch(console.error).then(); - }, [Loadsheet]); + SimVar.SetSimVarValue(`L:${seatMap[index].simVar}`, 'string', value.toString()).catch(console.error).then(); + }, [seatMap]); const setDesiredFlags = useCallback((value: SeatFlags, index: number) => { - SimVar.SetSimVarValue(`L:${Loadsheet.seatMap[index].bitFlags}_DESIRED`, 'string', value.toString()).catch(console.error).then(); - }, [Loadsheet]); + SimVar.SetSimVarValue(`L:${seatMap[index].simVar}_DESIRED`, 'string', value.toString()).catch(console.error).then(); + }, [seatMap]); + + const stationSizes = useMemo(() => seatMap.map((station) => { + let stationSize = 0; + station.rows.forEach((row) => { + row.seats.forEach(() => { + stationSize++; + }); + }); + return stationSize; + }), [seatMap]); const desiredFlags = useMemo(() => { const flags: SeatFlags[] = []; - Loadsheet.seatMap.forEach((station, index) => { - let stationSize = 0; - station.rows.forEach((row) => { - row.seats.forEach(() => { - stationSize++; - }); - }); - flags[index] = new SeatFlags(desiredBitVars[index], stationSize); + seatMap.forEach((_station, index) => { + flags[index] = new SeatFlags(desiredBitVars[index], stationSizes[index]); }); return flags; - }, [desiredBitVars, ...desiredBitVars]); + }, [...desiredBitVars, stationSizes]); const activeFlags = useMemo(() => { const flags: SeatFlags[] = []; - Loadsheet.seatMap.forEach((station, index) => { - let stationSize = 0; - station.rows.forEach((row) => { - row.seats.forEach(() => { - stationSize++; - }); - }); - flags[index] = new SeatFlags(activeBitVars[index], stationSize); + seatMap.forEach((_station, index) => { + flags[index] = new SeatFlags(activeBitVars[index], stationSizes[index]); }); return flags; - }, [activeBitVars, ...activeBitVars]); + }, [...activeBitVars, stationSizes]); return [ desiredFlags, diff --git a/fbw-common/src/systems/instruments/src/react/simVars.tsx b/fbw-common/src/systems/instruments/src/react/simVars.tsx index 52b3130c9d8..068cc18eab1 100644 --- a/fbw-common/src/systems/instruments/src/react/simVars.tsx +++ b/fbw-common/src/systems/instruments/src/react/simVars.tsx @@ -129,34 +129,21 @@ export const useSimVarList = ( if (delta >= refreshInterval) { lastUpdate.current = Date.now(); - names.forEach((name, index) => { - stateList[index] = SimVar.GetSimVarValue(name, units[index]); - }); - setStateList(stateList); + setStateList((prevStateList) => prevStateList.map((value, index) => SimVar.GetSimVarValue(names[index], units[index]))); } - }, [ - names, ...names, - units, ...units, - refreshInterval, - ]); + }, [names, units, refreshInterval]); useUpdate(updateCallback); const setter = useCallback((valuesOrSetter: any | SimVarSetter) => { - const executedValues = typeof valuesOrSetter === 'function' ? valuesOrSetter(stateList) : valuesOrSetter; - - executedValues.forEach((executedValue, index) => { - SimVar.SetSimVarValue(names[index], units[index], executedValue); - stateList[index] = executedValue; + setStateList((prevStateList) => { + const executedValues = typeof valuesOrSetter === 'function' ? valuesOrSetter(prevStateList) : valuesOrSetter; + executedValues.forEach((executedValue, index) => { + SimVar.SetSimVarValue(names[index], units[index], executedValue); + }); + return executedValues; }); - setStateList(stateList); - - return stateList; - }, [ - names, ...names, - units, ...units, - ...stateList, stateList, - ]); + }, [names, units]); return [stateList, setter]; }; diff --git a/fbw-common/src/systems/shared/src/AircraftVersionChecker.ts b/fbw-common/src/systems/shared/src/AircraftGithubVersionChecker.ts similarity index 95% rename from fbw-common/src/systems/shared/src/AircraftVersionChecker.ts rename to fbw-common/src/systems/shared/src/AircraftGithubVersionChecker.ts index 07d15bce13d..8ac169ef56b 100644 --- a/fbw-common/src/systems/shared/src/AircraftVersionChecker.ts +++ b/fbw-common/src/systems/shared/src/AircraftGithubVersionChecker.ts @@ -1,6 +1,8 @@ +// Copyright (c) 2023-2024 FlyByWire Simulations // SPDX-License-Identifier: GPL-3.0 /* eslint-disable no-console */ +/* eslint-disable no-underscore-dangle */ import Compare from 'semver/functions/compare'; import { CommitInfo, GitVersions, ReleaseInfo } from '@flybywiresim/api-client'; import { NotificationManager, PopUpDialog } from '@flybywiresim/fbw-sdk'; @@ -40,7 +42,7 @@ export enum KnowBranchNames { * Provides functions to the check the version of the aircraft against the * published GitHub version */ -export class AircraftVersionChecker { +export class AircraftGithubVersionChecker { private static notification: NotificationManager; private static versionChecked = false; @@ -59,7 +61,7 @@ export class AircraftVersionChecker { * @returns true if the aircraft version has been checked, false if no check has been commenced. */ public static async checkVersion(aircraft: string): Promise { - console.log('Checking aircraft version'); + console.log(`Checking aircraft version for A/C project: ${aircraft}`); this.notification = new NotificationManager(); @@ -80,9 +82,9 @@ export class AircraftVersionChecker { const versionInfo = this.getVersionInfo(this.buildInfo.version); if (this.checkOutdated(versionInfo)) { this.setOutdatedVersionFlag(true); - console.log('Aircraft version outdated'); + console.log(`Aircraft ${aircraft} - version outdated`); } else { - console.log('Aircraft version ok'); + console.log(`Aircraft ${aircraft} - version ok`); } this.versionChecked = true; } catch (error) { @@ -152,7 +154,7 @@ export class AircraftVersionChecker { this.releaseInfo = await GitVersions.getReleases('flybywiresim', aircraft, false, 0, 1); this.newestCommit = await GitVersions.getNewestCommit('flybywiresim', aircraft, 'master'); this.newestExpCommit = await GitVersions.getNewestCommit('flybywiresim', aircraft, 'experimental'); - this.buildInfo = await AircraftVersionChecker.getBuildInfo(aircraft); + this.buildInfo = await AircraftGithubVersionChecker.getBuildInfo(aircraft); } /** diff --git a/fbw-common/src/systems/shared/src/UniversalConfigProvider.ts b/fbw-common/src/systems/shared/src/UniversalConfigProvider.ts new file mode 100644 index 00000000000..a18ba42f0dc --- /dev/null +++ b/fbw-common/src/systems/shared/src/UniversalConfigProvider.ts @@ -0,0 +1,137 @@ +// Copyright (c) 2024 FlyByWire Simulations +// SPDX-License-Identifier: GPL-3.0 + +/* eslint-disable no-console */ +/* eslint-disable no-underscore-dangle */ + +import JSON5 from 'json5'; +import { AirframeInfo, CabinInfo, FlypadInfo } from './unifiedConfig'; + +/** + * UniversalConfigProvider is a class that provides for fetching + * airframe, flypad, cabin, etc. related markup from the VFS. + * The data is fetched from the VFS and is cached for subsequent calls. + */ +export class UniversalConfigProvider { + private static airframeInfo: AirframeInfo; + + private static flypadInfo: FlypadInfo; + + private static cabinInfo: CabinInfo; + + /** + * Fetch base VFS JSON5 markup configuration for this A/C variant + */ + private static fetchBaseVFSJson5(aircraft: string, variant: string, fileName: string): Promise { + return fetch(`/VFS/config/${aircraft}/${variant}/${fileName}.json5`) + .then((response) => response.text()) + .then((text) => JSON5.parse(text)) + .catch((error) => { + console.error(`Failed to read ${fileName}: ${error}`); + }); + } + + /** + * Fetch existing livery override JSON5 (TODO) + */ + private static fetchVFSJson5(aircraft: string, variant: string, atcId: string, fileName: string): Promise { + // TODO: Override base VFS Logic goes here + return this.fetchBaseVFSJson5(aircraft, variant, fileName); + } + + /** + * Fetch cached airframe data if it exists, otherwise fetch from VFS + */ + public static async fetchAirframeInfo(aircraft: string, variant: string): Promise { + if (this.airframeInfo) { + return this.airframeInfo; + } + + const json = await this.fetchVFSJson5(aircraft, variant, '', 'airframe'); + this.airframeInfo = ( + { + developer: json._developer, + name: json._name, + variant: json._variant, + icao: json._icao, + engines: json._engines, + designLimits: json.designLimits, + dimensions: json._dimensions, + } + ); + + return this.airframeInfo; + } + + /** + * Fetch cached flypad data if it exists, otherwise fetch from VFS + */ + public static async fetchFlypadInfo(aircraft: string, variant: string): Promise { + if (this.flypadInfo) { + return this.flypadInfo; + } + + const jsonPayload = await this.fetchVFSJson5(aircraft, variant, '', 'flypad-payload'); + const jsonMisc = await this.fetchVFSJson5(aircraft, variant, '', 'flypad-misc'); + this.flypadInfo = ( + { + payload: { + chartLimits: jsonPayload.chartLimits, + planeCanvas: jsonPayload._canvas, + seatDisplay: jsonPayload.seatDisplay, + }, + throttle: jsonMisc._throttle, + pushback: jsonMisc._pushback, + } + ); + + return this.flypadInfo; + } + + /** + * Fetch cached cabin data if it exists, otherwise fetch from VFS + */ + public static async fetchCabinInfo(aircraft: string, variant: string): Promise { + if (this.cabinInfo) { + return this.cabinInfo; + } + + const json = await this.fetchVFSJson5(aircraft, variant, '', 'cabin'); + this.cabinInfo = ( + { + defaultPaxWeight: json.defaultPaxWeight, + defaultBagWeight: json.defaultBagWeight, + paxDecks: json._paxDecks, + decks: json._decks, + minPaxWeight: json._minPaxWeight, + maxPaxWeight: json._maxPaxWeight, + minBagWeight: json._minBagWeight, + maxBagWeight: json._maxBagWeight, + seatMap: json.seatMap, + cargoMap: json.cargoMap, + } + ); + + return this.cabinInfo; + } + + /** + * Initialize the A/C config for all airframe, flypad, cabin, etc. related information + * + * @private + */ + public static async initialize(aircraft: string, variant: string) { + this.airframeInfo = await UniversalConfigProvider.fetchAirframeInfo( + aircraft, + variant, + ); + this.flypadInfo = await UniversalConfigProvider.fetchFlypadInfo( + aircraft, + variant, + ); + this.cabinInfo = await UniversalConfigProvider.fetchCabinInfo( + aircraft, + variant, + ); + } +} diff --git a/fbw-common/src/systems/shared/src/aircraftTypeCheck.ts b/fbw-common/src/systems/shared/src/aircraftTypeCheck.ts deleted file mode 100644 index a0daa449d51..00000000000 --- a/fbw-common/src/systems/shared/src/aircraftTypeCheck.ts +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) 2023-2024 FlyByWire Simulations -// SPDX-License-Identifier: GPL-3.0 - -/** - * Determine the aircraft type using the Aircraft Title SimVar. - * @returns {string} - the aircraft type (a32nx, a380x, other) - */ -export function getAircraftType(): string { - const aircraftName :string = SimVar.GetSimVarValue('TITLE', 'string'); - let aircraft: string; - if (aircraftName.includes('A320')) { - aircraft = 'a32nx'; - } else if (aircraftName.includes('A380')) { - aircraft = 'a380x'; - } else { - // FIXME: temporary fix as this will be change via PF #8599 anyway - aircraft = 'a32nx'; - } - return aircraft; -} diff --git a/fbw-common/src/systems/shared/src/checklists/ChecklistProvider.ts b/fbw-common/src/systems/shared/src/checklists/ChecklistProvider.ts index 9607346fa8c..ffb216a5ba6 100644 --- a/fbw-common/src/systems/shared/src/checklists/ChecklistProvider.ts +++ b/fbw-common/src/systems/shared/src/checklists/ChecklistProvider.ts @@ -1,7 +1,7 @@ // Copyright (c) 2023-2024 FlyByWire Simulations // SPDX-License-Identifier: GPL-3.0 -import { ConditionType, getAircraftType } from '@flybywiresim/fbw-sdk'; +import { ConditionType } from '@flybywiresim/fbw-sdk'; import JSON5 from 'json5'; import { ChecklistItem, ChecklistJsonDefinition } from './ChecklistInterfaces'; @@ -56,9 +56,7 @@ export class ChecklistProvider { // ============================================================================================= private constructor() { - // TODO: adapt to the new unified configuration (PR #8599) - const aircraft = getAircraftType(); - this.configFilename = `/VFS/config/${aircraft}_checklists.json5`; + this.configFilename = `/VFS/config/${process.env.AIRCRAFT_PROJECT_PREFIX}/${process.env.AIRCRAFT_VARIANT}/checklists.json5`; } /** diff --git a/fbw-common/src/systems/shared/src/index.ts b/fbw-common/src/systems/shared/src/index.ts index 5a2066fa3b3..136b7c565cd 100644 --- a/fbw-common/src/systems/shared/src/index.ts +++ b/fbw-common/src/systems/shared/src/index.ts @@ -1,4 +1,4 @@ -export * from './AircraftVersionChecker'; +export * from './AircraftGithubVersionChecker'; export * from './ApproachUtils'; export * from './Arinc429ConsumerSubject'; export * from './Arinc429RegisterSubject'; @@ -15,7 +15,8 @@ export * from './MathUtils'; export * from './PathVector'; export * from './RunwayUtils'; export * from './UpdateThrottler'; -export * from './aircraftTypeCheck'; +export * from './UniversalConfigProvider'; +export * from './unifiedConfig'; export * from './arinc429'; export * from './array'; export * from './ata'; diff --git a/fbw-common/src/systems/shared/src/unifiedConfig.ts b/fbw-common/src/systems/shared/src/unifiedConfig.ts new file mode 100644 index 00000000000..d49564fa83f --- /dev/null +++ b/fbw-common/src/systems/shared/src/unifiedConfig.ts @@ -0,0 +1,193 @@ +/** + * Contains the airframe.json file's information in a structured way. + */ +export enum AirframeType { + A320_251N = 'A320-251N', + A380_842 = 'A380-842' +} +export interface AirframeInfo { + developer: string; + name: string; + variant: string; + icao: string; + engines: string; + designLimits: AirframeDesignLimits; + dimensions: AirframeDimensions; +} + +export interface AirframeDesignLimits { + weights: AirframeDesignLimitsWeights; + endurance: AirframeDesignLimitsEndurance; + performanceEnvelope: AirframePerformanceEnvelope; +} + +export interface AirframeDesignLimitsWeights { + maxGw: number; + maxZfw: number; + minZfw: number; + maxGwCg: number; + maxZfwCg: number; + maxCargo: number; + maxFuel: number; +} + +export interface AirframeDesignLimitsEndurance { + range: number; + mmo: string; +} + +export interface AirframePerformanceEnvelope { + mlw: number[][]; + mzfw: number[][]; + mtow: number[][]; + flight: number[][]; +} + +export interface AirframeDimensions { + aircraftWheelBase: number; + aircraftLengthMeter: number; +} + +/** + * Contains the flypad-*.json files' information in a structured way. + */ +export interface FlypadInfo { + payload: PayloadFlypadInfo; + throttle: ThrottleFlypadInfo; + pushback: PushbackFlypadInfo; +} + +export interface ThrottleFlypadInfo { + numberOfAxis: number; + axisOptions: number[]; + axisMapping: ThrottleFlypadAxisMapping; +} + +export interface ThrottleFlypadAxisMapping { + 1?: number[][]; + 2?: number[][]; + 3?: number[][]; + 4?: number[][]; +} + +export interface PushbackFlypadInfo { + turnIndicatorTuningDefault: number; +} + +export interface PayloadFlypadInfo { + planeCanvas: PayloadPlaneCanvas; + chartLimits: PayloadChartLimits; + seatDisplay: PayloadSeatDisplay[]; + +} +export interface PayloadPlaneCanvas { + width: number; + height: number; + canvasX: number; + canvasY: number; +} + +export interface PayloadSeatDisplay { + len: number; + wid: number; + padX: number; + padY: number; + imageX: number; + imageY: number; +} +export interface PayloadChartLimits { + weight: ChartLimitsWeights; + cg: ChartLimitsCG; + labels: ChartLimitsLabels; +} + +export interface ChartLimitsWeights { + min: number; + max: number; + lines: number; + scale: number; + values: number[]; + +} + +export interface ChartLimitsCG { + angleRad: number; + min: number; + max: number; + overlap: number; + highlight: number; + lines: number; + scale: number; + values: number[]; +} + +export interface ChartLimitsLabels { + mtow: ChartLimitsLabelsValue; + mlw: ChartLimitsLabelsValue; + mzfw: ChartLimitsLabelsValue; +} + +export interface ChartLimitsLabelsValue { + x1: number; + x2: number; + y: number; +} + +export enum SeatType { + NarrowbodyEconomy = 0, + NarrowbodyEconomyEmergency = 1, + WidebodyEconomy = 2, + WidebodyEconomyEmergency = 3, + WidebodyBusinessFlatRight = 4, + WidebodyBusinessFlatLeft = 5, + WidebodySuiteRight = 6, + WidebodySuiteLeft = 7, + WidebodyPremiumEconomy = 8 +} + +export interface CabinInfo { + defaultPaxWeight: number; + defaultBagWeight: number; + paxDecks: number; + decks: number; + minPaxWeight: number; + maxPaxWeight: number; + minBagWeight: number; + maxBagWeight: number; + seatMap: PaxStationInfo[]; + cargoMap: CargoStationInfo[]; +} + +export interface PaxStationInfo { + name: string, + capacity: number, + rows: RowInfo[], + simVar: string, + stationIndex: number, + position: number, + deck: number +} + +export interface CargoStationInfo { + name: string, + weight: number, + simVar: string, + stationIndex: number, + progressBarWidth: number, + position: number, +} + +export interface RowInfo { + x?: number, + y?: number, + xOffset?: number, + yOffset?: number, + seats: SeatInfo[], +} + +export interface SeatInfo { + type: SeatType, + x?: number, + y?: number, + yOffset?: number +} diff --git a/package.json b/package.json index b919e090820..60454f8600e 100644 --- a/package.json +++ b/package.json @@ -205,4 +205,4 @@ "uuid": "^9.0.0", "ws": "^7.4.5" } -} +} \ No newline at end of file diff --git a/scripts/build_a32nx.sh b/scripts/build_a32nx.sh index f757fc4c688..29108188c07 100755 --- a/scripts/build_a32nx.sh +++ b/scripts/build_a32nx.sh @@ -6,6 +6,8 @@ set -e ORIGINAL_USER_ID=$(stat -c '%u' /external) ORIGINAL_GROUP_ID=$(stat -c '%g' /external) +AIRCRAFT_PROJECT_PREFIX="a32nx" + # set ownership to root to fix cargo/rust build (when run as github action) if [ "${GITHUB_ACTIONS}" == "true" ]; then chown -R root:root /external @@ -17,8 +19,8 @@ for arg in "$@"; do # If the argument is "-clean", perform some action if [ "$arg" = "-clean" ]; then echo "Removing out directories..." - rm -rf /external/fbw-a32nx/out - rm -rf /external/fbw-a32nx/bundles + rm -rf /external/fbw-"${AIRCRAFT_PROJECT_PREFIX}"/out + rm -rf /external/fbw-"${AIRCRAFT_PROJECT_PREFIX}"/bundles else # Otherwise, add the arg it to the new array args+=("$arg") @@ -26,7 +28,7 @@ for arg in "$@"; do done # run build -time npx igniter -r a32nx "${args[@]}" +time npx igniter -r "${AIRCRAFT_PROJECT_PREFIX}" "${args[@]}" # restore ownership (when run as github action) if [ "${GITHUB_ACTIONS}" == "true" ]; then diff --git a/scripts/build_a380x.sh b/scripts/build_a380x.sh index fec458af915..9fdcc4630b9 100755 --- a/scripts/build_a380x.sh +++ b/scripts/build_a380x.sh @@ -6,6 +6,8 @@ set -e ORIGINAL_USER_ID=$(stat -c '%u' /external) ORIGINAL_GROUP_ID=$(stat -c '%g' /external) +AIRCRAFT_PROJECT_PREFIX="a380x" + # set ownership to root to fix cargo/rust build (when run as github action) if [ "${GITHUB_ACTIONS}" == "true" ]; then chown -R root:root /external @@ -17,8 +19,8 @@ for arg in "$@"; do # If the argument is "-clean", perform some action if [ "$arg" = "-clean" ]; then echo "Removing out directories..." - rm -rf /external/fbw-a380x/out - rm -rf /external/fbw-a380x/bundles + rm -rf /external/fbw-"${AIRCRAFT_PROJECT_PREFIX}"/out + rm -rf /external/fbw-"${AIRCRAFT_PROJECT_PREFIX}"/bundles else # Otherwise, add the arg it to the new array args+=("$arg") @@ -26,7 +28,7 @@ for arg in "$@"; do done # run build -time npx igniter -r a380x "${args[@]}" +time npx igniter -r "${AIRCRAFT_PROJECT_PREFIX}" "${args[@]}" # restore ownership (when run as github action) if [ "${GITHUB_ACTIONS}" == "true" ]; then