diff --git a/.gitignore b/.gitignore index 763a5bb8241..25ef38cce02 100644 --- a/.gitignore +++ b/.gitignore @@ -87,13 +87,21 @@ large-files/node_modules !/fbw-ingamepanels-checklist-fix/src/** /fbw-ingamepanels-checklist-fix/out +# === ARINC LVar Bridge === +/fbw-arinc429-lvar-bridge/* +!/fbw-arinc429-lvar-bridge/README.md +!/fbw-arinc429-lvar-bridge/docs/ +!/fbw-arinc429-lvar-bridge/docs/** +!/fbw-arinc429-lvar-bridge/src/ +!/fbw-arinc429-lvar-bridge/src/** +/fbw-arinc429-lvar-bridge/out + # === Tools === !/tools/** /tools/fdr2csv/*.exe /tools/fdr2csv/build/ /tools/fdr2csv/cmake-build* - # Build scripts !/scripts/** !/build-utils.js @@ -106,6 +114,8 @@ localazy.keys.json # build artifacts node_modules/ target/ +out/ +build/ obj/ build/ out/ diff --git a/CMakeLists.txt b/CMakeLists.txt index 789564a13b6..689cc5e5df0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -61,3 +61,6 @@ add_subdirectory(fbw-a32nx/src/wasm) # add the A380X components add_subdirectory(fbw-a380x/src/wasm) + +# add the LVarProvider components +add_subdirectory(fbw-arinc429-lvar-bridge/src/wasm) diff --git a/fbw-a32nx/src/wasm/extra-backend-a32nx/src/Gauge_Extra_Backend.cpp b/fbw-a32nx/src/wasm/extra-backend-a32nx/src/Gauge_Extra_Backend.cpp index 9812cc00522..dbeb28c4669 100644 --- a/fbw-a32nx/src/wasm/extra-backend-a32nx/src/Gauge_Extra_Backend.cpp +++ b/fbw-a32nx/src/wasm/extra-backend-a32nx/src/Gauge_Extra_Backend.cpp @@ -64,3 +64,4 @@ MSFS_CALLBACK bool Gauge_Extra_Backend_gauge_callback([[maybe_unused]] FsContext return false; } } + diff --git a/fbw-arinc429-lvar-bridge/README.md b/fbw-arinc429-lvar-bridge/README.md new file mode 100644 index 00000000000..781d3471f5a --- /dev/null +++ b/fbw-arinc429-lvar-bridge/README.md @@ -0,0 +1,15 @@ +# FlyByWire Arinc429 LVar Bridge + +The Arinc429 LVar Bridge in the FlyByWire project is a bridge designed to interface +between the Aircraft's data bus protocol (ARINC 429) and local simulation variables (LVars). + +As some of these raw values of these LVars might be useful to 3rd parties (e.g. cockpit builder, +3rd party software, etc.) this bridge allows to expose a selected user configurable set of these +arinc429 encoded variables with their raw value as LVars. + +## **NOTE** + +This is still a proof of concept as there are only few arinc429 encoded variables yet. +Also, it is yet unclear how the naming convention of encoded vs. raw values should be handled. + + diff --git a/fbw-arinc429-lvar-bridge/src/base/flybywire-arinc429-lvar-bridge/ContentInfo/fbw-arinc429-lvar-bridge/Thumbnail.jpg b/fbw-arinc429-lvar-bridge/src/base/flybywire-arinc429-lvar-bridge/ContentInfo/fbw-arinc429-lvar-bridge/Thumbnail.jpg new file mode 100644 index 00000000000..24e3301d3de Binary files /dev/null and b/fbw-arinc429-lvar-bridge/src/base/flybywire-arinc429-lvar-bridge/ContentInfo/fbw-arinc429-lvar-bridge/Thumbnail.jpg differ diff --git a/fbw-arinc429-lvar-bridge/src/base/flybywire-arinc429-lvar-bridge/modules/arinc429_vars.txt b/fbw-arinc429-lvar-bridge/src/base/flybywire-arinc429-lvar-bridge/modules/arinc429_vars.txt new file mode 100644 index 00000000000..5033a70145a --- /dev/null +++ b/fbw-arinc429-lvar-bridge/src/base/flybywire-arinc429-lvar-bridge/modules/arinc429_vars.txt @@ -0,0 +1,236 @@ +# ADR 1-3 +A32NX_ADIRS_ADR_1_ALTITUDE +A32NX_ADIRS_ADR_1_ANGLE_OF_ATTACK +A32NX_ADIRS_ADR_1_BAROMETRIC_VERTICAL_SPEED +A32NX_ADIRS_ADR_1_BARO_CORRECTED_ALTITUDE_1 +A32NX_ADIRS_ADR_1_BARO_CORRECTED_ALTITUDE_2 +A32NX_ADIRS_ADR_1_BARO_CORRECTION_1_HPA +A32NX_ADIRS_ADR_1_BARO_CORRECTION_1_INHG +A32NX_ADIRS_ADR_1_BARO_CORRECTION_2_HPA +A32NX_ADIRS_ADR_1_BARO_CORRECTION_2_INHG +A32NX_ADIRS_ADR_1_COMPUTED_AIRSPEED +A32NX_ADIRS_ADR_1_CORRECTED_AVERAGE_STATIC_PRESSURE +A32NX_ADIRS_ADR_1_MACH +A32NX_ADIRS_ADR_1_MAX_AIRSPEED +A32NX_ADIRS_ADR_1_STATIC_AIR_TEMPERATURE +A32NX_ADIRS_ADR_1_TOTAL_AIR_TEMPERATURE +A32NX_ADIRS_ADR_1_TRUE_AIRSPEED +A32NX_ADIRS_ADR_2_ALTITUDE +A32NX_ADIRS_ADR_2_ANGLE_OF_ATTACK +A32NX_ADIRS_ADR_2_BAROMETRIC_VERTICAL_SPEED +A32NX_ADIRS_ADR_2_BARO_CORRECTED_ALTITUDE_1 +A32NX_ADIRS_ADR_2_BARO_CORRECTED_ALTITUDE_2 +A32NX_ADIRS_ADR_2_BARO_CORRECTION_1_HPA +A32NX_ADIRS_ADR_2_BARO_CORRECTION_1_INHG +A32NX_ADIRS_ADR_2_BARO_CORRECTION_2_HPA +A32NX_ADIRS_ADR_2_BARO_CORRECTION_2_INHG +A32NX_ADIRS_ADR_2_COMPUTED_AIRSPEED +A32NX_ADIRS_ADR_2_CORRECTED_AVERAGE_STATIC_PRESSURE +A32NX_ADIRS_ADR_2_MACH +A32NX_ADIRS_ADR_2_MAX_AIRSPEED +A32NX_ADIRS_ADR_2_STATIC_AIR_TEMPERATURE +A32NX_ADIRS_ADR_2_TOTAL_AIR_TEMPERATURE +A32NX_ADIRS_ADR_2_TRUE_AIRSPEED +A32NX_ADIRS_ADR_3_ALTITUDE +A32NX_ADIRS_ADR_3_ANGLE_OF_ATTACK +A32NX_ADIRS_ADR_3_BAROMETRIC_VERTICAL_SPEED +A32NX_ADIRS_ADR_3_BARO_CORRECTED_ALTITUDE_1 +A32NX_ADIRS_ADR_3_BARO_CORRECTED_ALTITUDE_2 +A32NX_ADIRS_ADR_3_BARO_CORRECTION_1_HPA +A32NX_ADIRS_ADR_3_BARO_CORRECTION_1_INHG +A32NX_ADIRS_ADR_3_BARO_CORRECTION_2_HPA +A32NX_ADIRS_ADR_3_BARO_CORRECTION_2_INHG +A32NX_ADIRS_ADR_3_COMPUTED_AIRSPEED +A32NX_ADIRS_ADR_3_CORRECTED_AVERAGE_STATIC_PRESSURE +A32NX_ADIRS_ADR_3_MACH +A32NX_ADIRS_ADR_3_MAX_AIRSPEED +A32NX_ADIRS_ADR_3_STATIC_AIR_TEMPERATURE +A32NX_ADIRS_ADR_3_TOTAL_AIR_TEMPERATURE +A32NX_ADIRS_ADR_3_TRUE_AIRSPEED + +# IR 1-3 +A32NX_ADIRS_IR_1_BODY_LATERAL_ACC +A32NX_ADIRS_IR_1_BODY_LONGITUDINAL_ACC +A32NX_ADIRS_IR_1_BODY_NORMAL_ACC +A32NX_ADIRS_IR_1_BODY_PITCH_RATE +A32NX_ADIRS_IR_1_BODY_ROLL_RATE +A32NX_ADIRS_IR_1_BODY_YAW_RATE +A32NX_ADIRS_IR_1_DRIFT_ANGLE +A32NX_ADIRS_IR_1_FLIGHT_PATH_ANGLE +A32NX_ADIRS_IR_1_GROUND_SPEED +A32NX_ADIRS_IR_1_HEADING +A32NX_ADIRS_IR_1_HEADING_RATE +A32NX_ADIRS_IR_1_LATITUDE +A32NX_ADIRS_IR_1_LONGITUDE +A32NX_ADIRS_IR_1_PITCH +A32NX_ADIRS_IR_1_PITCH_ATT_RATE +A32NX_ADIRS_IR_1_ROLL +A32NX_ADIRS_IR_1_ROLL_ATT_RATE +A32NX_ADIRS_IR_1_TRACK +A32NX_ADIRS_IR_1_TRUE_HEADING +A32NX_ADIRS_IR_1_TRUE_TRACK +A32NX_ADIRS_IR_1_VERTICAL_SPEED +A32NX_ADIRS_IR_1_WIND_DIRECTION +A32NX_ADIRS_IR_1_WIND_DIRECTION_BNR +A32NX_ADIRS_IR_1_WIND_SPEED +A32NX_ADIRS_IR_1_WIND_SPEED_BNR +A32NX_ADIRS_IR_2_BODY_LATERAL_ACC +A32NX_ADIRS_IR_2_BODY_LONGITUDINAL_ACC +A32NX_ADIRS_IR_2_BODY_NORMAL_ACC +A32NX_ADIRS_IR_2_BODY_PITCH_RATE +A32NX_ADIRS_IR_2_BODY_ROLL_RATE +A32NX_ADIRS_IR_2_BODY_YAW_RATE +A32NX_ADIRS_IR_2_DRIFT_ANGLE +A32NX_ADIRS_IR_2_FLIGHT_PATH_ANGLE +A32NX_ADIRS_IR_2_GROUND_SPEED +A32NX_ADIRS_IR_2_HEADING +A32NX_ADIRS_IR_2_HEADING_RATE +A32NX_ADIRS_IR_2_LATITUDE +A32NX_ADIRS_IR_2_LONGITUDE +A32NX_ADIRS_IR_2_PITCH +A32NX_ADIRS_IR_2_PITCH_ATT_RATE +A32NX_ADIRS_IR_2_ROLL +A32NX_ADIRS_IR_2_ROLL_ATT_RATE +A32NX_ADIRS_IR_2_TRACK +A32NX_ADIRS_IR_2_TRUE_HEADING +A32NX_ADIRS_IR_2_TRUE_TRACK +A32NX_ADIRS_IR_2_VERTICAL_SPEED +A32NX_ADIRS_IR_2_WIND_DIRECTION +A32NX_ADIRS_IR_2_WIND_DIRECTION_BNR +A32NX_ADIRS_IR_2_WIND_SPEED +A32NX_ADIRS_IR_2_WIND_SPEED_BNR +A32NX_ADIRS_IR_3_BODY_LATERAL_ACC +A32NX_ADIRS_IR_3_BODY_LONGITUDINAL_ACC +A32NX_ADIRS_IR_3_BODY_NORMAL_ACC +A32NX_ADIRS_IR_3_BODY_PITCH_RATE +A32NX_ADIRS_IR_3_BODY_ROLL_RATE +A32NX_ADIRS_IR_3_BODY_YAW_RATE +A32NX_ADIRS_IR_3_DRIFT_ANGLE +A32NX_ADIRS_IR_3_FLIGHT_PATH_ANGLE +A32NX_ADIRS_IR_3_GROUND_SPEED +A32NX_ADIRS_IR_3_HEADING +A32NX_ADIRS_IR_3_HEADING_RATE +A32NX_ADIRS_IR_3_LATITUDE +A32NX_ADIRS_IR_3_LONGITUDE +A32NX_ADIRS_IR_3_PITCH +A32NX_ADIRS_IR_3_PITCH_ATT_RATE +A32NX_ADIRS_IR_3_ROLL +A32NX_ADIRS_IR_3_ROLL_ATT_RATE +A32NX_ADIRS_IR_3_TRACK +A32NX_ADIRS_IR_3_TRUE_HEADING +A32NX_ADIRS_IR_3_TRUE_TRACK +A32NX_ADIRS_IR_3_VERTICAL_SPEED +A32NX_ADIRS_IR_3_WIND_DIRECTION +A32NX_ADIRS_IR_3_WIND_DIRECTION_BNR +A32NX_ADIRS_IR_3_WIND_SPEED +A32NX_ADIRS_IR_3_WIND_SPEED_BNR + +# APU +A32NX_APU_EGT +A32NX_APU_EGT_CAUTION +A32NX_APU_EGT_WARNING +A32NX_APU_FLAP_FULLY_OPEN +A32NX_APU_LOW_FUEL_PRESSURE_FAULT +A32NX_APU_N + +# FCDC 1-2 +A32NX_FCDC_1_AILERON_LEFT_POS +A32NX_FCDC_1_AILERON_RIGHT_POS +A32NX_FCDC_1_CAPT_PITCH_COMMAND +A32NX_FCDC_1_CAPT_ROLL_COMMAND +A32NX_FCDC_1_ELEVATOR_LEFT_POS +A32NX_FCDC_1_ELEVATOR_RIGHT_POS +A32NX_FCDC_1_ELEVATOR_TRIM_POS +A32NX_FCDC_1_FO_PITCH_COMMAND +A32NX_FCDC_1_FO_ROLL_COMMAND +A32NX_FCDC_1_RUDDER_PEDAL_POS +A32NX_FCDC_1_SPOILER_LEFT_1_POS +A32NX_FCDC_1_SPOILER_LEFT_2_POS +A32NX_FCDC_1_SPOILER_LEFT_3_POS +A32NX_FCDC_1_SPOILER_LEFT_4_POS +A32NX_FCDC_1_SPOILER_LEFT_5_POS +A32NX_FCDC_1_SPOILER_RIGHT_1_POS +A32NX_FCDC_1_SPOILER_RIGHT_2_POS +A32NX_FCDC_1_SPOILER_RIGHT_3_POS +A32NX_FCDC_1_SPOILER_RIGHT_4_POS +A32NX_FCDC_1_SPOILER_RIGHT_5_POS +A32NX_FCDC_2_AILERON_LEFT_POS +A32NX_FCDC_2_AILERON_RIGHT_POS +A32NX_FCDC_2_CAPT_PITCH_COMMAND +A32NX_FCDC_2_CAPT_ROLL_COMMAND +A32NX_FCDC_2_ELEVATOR_LEFT_POS +A32NX_FCDC_2_ELEVATOR_RIGHT_POS +A32NX_FCDC_2_ELEVATOR_TRIM_POS +A32NX_FCDC_2_FO_PITCH_COMMAND +A32NX_FCDC_2_FO_ROLL_COMMAND +A32NX_FCDC_2_RUDDER_PEDAL_POS +A32NX_FCDC_2_SPOILER_LEFT_1_POS +A32NX_FCDC_2_SPOILER_LEFT_2_POS +A32NX_FCDC_2_SPOILER_LEFT_3_POS +A32NX_FCDC_2_SPOILER_LEFT_4_POS +A32NX_FCDC_2_SPOILER_LEFT_5_POS +A32NX_FCDC_2_SPOILER_RIGHT_1_POS +A32NX_FCDC_2_SPOILER_RIGHT_2_POS +A32NX_FCDC_2_SPOILER_RIGHT_3_POS +A32NX_FCDC_2_SPOILER_RIGHT_4_POS +A32NX_FCDC_2_SPOILER_RIGHT_5_POS + +# FM 1-2 +A32NX_FM1_DECISION_HEIGHT +A32NX_FM1_MINIMUM_DESCENT_ALTITUDE +A32NX_FM1_TRANS_ALT +A32NX_FM1_TRANS_LVL +A32NX_FM1_DEST_LAT +A32NX_FM1_DEST_LONG +A32NX_FM1_TO_PITCH_TRIM +A32NX_FM2_DECISION_HEIGHT +A32NX_FM2_MINIMUM_DESCENT_ALTITUDE +A32NX_FM2_TRANS_ALT +A32NX_FM2_TRANS_LVL +A32NX_FM2_DEST_LAT +A32NX_FM2_DEST_LONG +A32NX_FM2_TO_PITCH_TRIM + +# PRESS CPC 1-2 +A32NX_PRESS_CPC_1_CABIN_ALTITUDE +A32NX_PRESS_CPC_1_CABIN_DELTA_PRESSURE +A32NX_PRESS_CPC_1_CABIN_VS +A32NX_PRESS_CPC_1_LANDING_ELEVATION +A32NX_PRESS_CPC_1_OUTFLOW_VALVE_OPEN_PERCENTAGE +A32NX_PRESS_CPC_2_CABIN_ALTITUDE +A32NX_PRESS_CPC_2_CABIN_DELTA_PRESSURE +A32NX_PRESS_CPC_2_CABIN_VS +A32NX_PRESS_CPC_2_LANDING_ELEVATION +A32NX_PRESS_CPC_2_OUTFLOW_VALVE_OPEN_PERCENTAGE + +# RA 1-2 +A32NX_RA_1_RADIO_ALTITUDE +A32NX_RA_2_RADIO_ALTITUDE + +# FAC 1-2 +A32NX_FAC_1_SIDESLIP_TARGET +A32NX_FAC_1_ESTIMATED_SIDESLIP +A32NX_FAC_1_V_ALPHA_LIM +A32NX_FAC_1_V_LS +A32NX_FAC_1_V_STALL_1G +A32NX_FAC_1_V_ALPHA_PROT +A32NX_FAC_1_V_STALL_WARN +A32NX_FAC_1_SPEED_TREND +A32NX_FAC_1_V_3 +A32NX_FAC_1_V_3 +A32NX_FAC_1_V_MAN +A32NX_FAC_1_V_MAX +A32NX_FAC_1_V_FE_NEXT +A32NX_FAC_2_SIDESLIP_TARGET +A32NX_FAC_2_ESTIMATED_SIDESLIP +A32NX_FAC_2_V_ALPHA_LIM +A32NX_FAC_2_V_LS +A32NX_FAC_2_V_STALL_1G +A32NX_FAC_2_V_ALPHA_PROT +A32NX_FAC_2_V_STALL_WARN +A32NX_FAC_2_SPEED_TREND +A32NX_FAC_2_V_3 +A32NX_FAC_2_V_3 +A32NX_FAC_2_V_MAN +A32NX_FAC_2_V_MAX +A32NX_FAC_2_V_FE_NEXT diff --git a/fbw-arinc429-lvar-bridge/src/base/manifest-base.json b/fbw-arinc429-lvar-bridge/src/base/manifest-base.json new file mode 100644 index 00000000000..8fd0726c9bc --- /dev/null +++ b/fbw-arinc429-lvar-bridge/src/base/manifest-base.json @@ -0,0 +1,15 @@ +{ + "creator": "FlyByWire Simulations", + "release_notes": { + "neutral": { + "LastUpdate": "", + "OlderHistory": "" + } + }, + "title": "FlyByWire Arinc429 LVar Bridge", + "dependencies": [], + "content_type": "MISC", + "minimum_game_version": "1.36.2", + "manufacturer": "FlyByWire Simulations", + "package_version": "0.1.0" +} diff --git a/fbw-arinc429-lvar-bridge/src/wasm/CMakeLists.txt b/fbw-arinc429-lvar-bridge/src/wasm/CMakeLists.txt new file mode 100644 index 00000000000..bc09e57877d --- /dev/null +++ b/fbw-arinc429-lvar-bridge/src/wasm/CMakeLists.txt @@ -0,0 +1,8 @@ +# folder structure +set(OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/../../out/flybywire-arinc429-lvar-bridge/modules) + +# add compiler definitions +#add_definitions() + +add_subdirectory(arinc429-lvar-bridge) + diff --git a/fbw-arinc429-lvar-bridge/src/wasm/arinc429-lvar-bridge/CMakeLists.txt b/fbw-arinc429-lvar-bridge/src/wasm/arinc429-lvar-bridge/CMakeLists.txt new file mode 100644 index 00000000000..c843b6e9e39 --- /dev/null +++ b/fbw-arinc429-lvar-bridge/src/wasm/arinc429-lvar-bridge/CMakeLists.txt @@ -0,0 +1,28 @@ +# fbw-arinc429-lvar-bridge CMakeLists.txt + +# add additional compiler definitions for the a32nx extra-backend build +#add_definitions() + +# add the local include directories +include_directories( + ${CMAKE_CURRENT_SOURCE_DIR}/src + ${FBW_COMMON}/cpp-msfs-framework/ +) + +# define the source files +set(SOURCE_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/src/Arinc429LVarBridge.cpp + src/Arinc429LvarConverter.cpp +) + +set(INCLUDE_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/src/Arinc429LVarBridge.h + src/Arinc429LvarConverter.h +) + +# create the targets +add_library(fbw-arinc429-lvar-bridge OBJECT ${SOURCE_FILES} ${INCLUDE_FILES}) +add_wasm_library( + NAME fbw-arinc429-lvar-bridge + DEPENDENCIES fbw-arinc429-lvar-bridge cpp-msfs-framework-lvar-provider +) diff --git a/fbw-arinc429-lvar-bridge/src/wasm/arinc429-lvar-bridge/src/Arinc429LVarBridge.cpp b/fbw-arinc429-lvar-bridge/src/wasm/arinc429-lvar-bridge/src/Arinc429LVarBridge.cpp new file mode 100644 index 00000000000..27b74fabcc7 --- /dev/null +++ b/fbw-arinc429-lvar-bridge/src/wasm/arinc429-lvar-bridge/src/Arinc429LVarBridge.cpp @@ -0,0 +1,70 @@ +// Copyright (c) 2023-2024 FlyByWire Simulations +// SPDX-License-Identifier: GPL-3.0 + +#include +#include +#include + +#include "Arinc429LvarConverter.h" + +HANDLE g_hSimConnect; + +enum eEvents { + EVENT_FRAME // +}; + +Arinc429LvarConverter lvarConverter; + +/** + * @brief This is called whenever SimConnect receives a message. It has been registered in the module_init function. + */ +void CALLBACK ProcessDispatchCallbacks(SIMCONNECT_RECV* pData, DWORD, void*) { + switch (pData->dwID) { + case SIMCONNECT_RECV_ID_EVENT_FRAME: + lvarConverter.update(); + } +} + +/** + * @brief Initializes the module. + */ +extern "C" MSFS_CALLBACK void module_init(void) { + g_hSimConnect = 0; + + HRESULT hr = SimConnect_Open(&g_hSimConnect, "fbw-arinc429-lvar-bridge", nullptr, 0, 0, 0); + if (hr != S_OK) { + fprintf(stderr, "Arinc429LVarBridge: Could not open SimConnect connection.\n"); + return; + } + + hr = SimConnect_SubscribeToSystemEvent(g_hSimConnect, EVENT_FRAME, "Frame"); + if (hr != S_OK) { + fprintf(stderr, "Arinc429LVarBridge: Could not subscribe to \"Frame\" system event.\n"); + return; + } + + hr = SimConnect_CallDispatch(g_hSimConnect, ProcessDispatchCallbacks, nullptr); + if (hr != S_OK) { + fprintf(stderr, "Arinc429LVarBridge: Could not set dispatch callback.\n"); + return; + } + + lvarConverter.init(); +} + +/** + * @brief De-initializes the module. + */ +extern "C" MSFS_CALLBACK void module_deinit(void) { + if (!g_hSimConnect) { + return; + } + + unregister_all_named_vars(); + + HRESULT hr = SimConnect_Close(g_hSimConnect); + if (hr != S_OK) { + fprintf(stderr, "Arinc429LVarBridge: Could not close SimConnect connection.\n"); + return; + } +} diff --git a/fbw-arinc429-lvar-bridge/src/wasm/arinc429-lvar-bridge/src/Arinc429LVarBridge.h b/fbw-arinc429-lvar-bridge/src/wasm/arinc429-lvar-bridge/src/Arinc429LVarBridge.h new file mode 100644 index 00000000000..c26782f5162 --- /dev/null +++ b/fbw-arinc429-lvar-bridge/src/wasm/arinc429-lvar-bridge/src/Arinc429LVarBridge.h @@ -0,0 +1,17 @@ +// Copyright (c) 2023-2024 FlyByWire Simulations +// SPDX-License-Identifier: GPL-3.0 + +#ifndef FLYBYWIRE_AIRCRAFT_ARINC429LVARBRIDGE_H +#define FLYBYWIRE_AIRCRAFT_ARINC429LVARBRIDGE_H + +#ifndef __INTELLISENSE__ +#define MODULE_EXPORT __attribute__((visibility("default"))) +#define MODULE_WASM_MODNAME(mod) __attribute__((import_module(mod))) +#else +#define MODULE_EXPORT +#define MODULE_WASM_MODNAME(mod) +#define __attribute__(x) +#define __restrict__ +#endif + +#endif // FLYBYWIRE_AIRCRAFT_ARINC429LVARBRIDGE_H diff --git a/fbw-arinc429-lvar-bridge/src/wasm/arinc429-lvar-bridge/src/Arinc429LvarConverter.cpp b/fbw-arinc429-lvar-bridge/src/wasm/arinc429-lvar-bridge/src/Arinc429LvarConverter.cpp new file mode 100644 index 00000000000..08213e16242 --- /dev/null +++ b/fbw-arinc429-lvar-bridge/src/wasm/arinc429-lvar-bridge/src/Arinc429LvarConverter.cpp @@ -0,0 +1,161 @@ +// Copyright (c) 2023-2024 FlyByWire Simulations +// SPDX-License-Identifier: GPL-3.0 + +#include +#include +#include + +#include "Arinc429LvarConverter.h" +#include "ScopedTimer.hpp" +#include "arinc429.hpp" +#include "logging.h" + +void Arinc429LvarConverter::init() { + LOG_INFO("FlyByWire Arinc429LVarBridge: Initializing"); + // setup control variables + isArinc429LvarBridgeOnID = register_named_variable("FBW_ARINC429_LVAR_BRIDGE_ON"); + doArinc429LvarBridgeInit = register_named_variable("FBW_ARINC429_LVAR_BRIDGE_INIT"); + isArinc429LvarBridgeVerbose = register_named_variable("FBW_ARINC429_LVAR_BRIDGE_VERBOSE"); + isReadyID = register_named_variable("A32NX_IS_READY"); + + this->initialized = true; +} + +void Arinc429LvarConverter::update() { + // check if the bridge is initialized and the aircraft is ready + if (!this->initialized || !get_named_variable_value(isReadyID)) { + return; + } + + profiler.start(); + + tickCounter++; + + // Update LVars from var files if not done yet or if the init flag is set + if (!varFileRead || get_named_variable_value(doArinc429LvarBridgeInit)) { + set_named_variable_value(doArinc429LvarBridgeInit, 0); + readVarFile(); + } + + int counter = 0; + + // check if the bridge is activated + if (get_named_variable_value(isArinc429LvarBridgeOnID)) { + // process all known arinc vars + for (std::pair& ids : arinc429Vars) { + FLOAT64 value = get_named_variable_value(ids.first); + + Arinc429NumericWord arinc429NumericWord{value}; + arinc429NumericWord.setSsm(Arinc429SignStatus::FunctionalTest); // to get the raw value independent of the actual SSM + float rawValue = arinc429NumericWord.valueOr(0.0f); + + set_named_variable_value(ids.second, rawValue); + counter++; + + if (tickCounter % 100 == 0 && get_named_variable_value(isArinc429LvarBridgeVerbose) >= 2) { + PCSTRINGZ firstName = get_name_of_named_variable(ids.first); + PCSTRINGZ secondName = get_name_of_named_variable(ids.second); + std::cout << "FlyByWire Arinc429LVarBridge: LVar: " << firstName << " = " << value << " Raw Value: " << secondName << " = " + << rawValue << std::endl; + } + } + } + + profiler.stop(); + if (tickCounter % 100 == 0 && get_named_variable_value(isArinc429LvarBridgeVerbose) >= 1) { + std::cout << "Processed " << counter << " arinc vars per tick" << std::endl; + profiler.print(); + } +} + +// ================================================================================================= +// PRIVATE +// ================================================================================================= + +void Arinc429LvarConverter::readVarFile() { + LOG_INFO("FlyByWire Arinc429LVarBridge: Reading vars file"); + ScopedTimer timer("Reading vars files"); + + arinc429Vars.clear(); + + std::ifstream work_vars(WORK_VARS_FILE); + std::map workVars; + std::string line; + + // try to open the work vars file - if it does not exist, create it later when writing to it + if (work_vars.fail()) { + std::cerr << "Vars file does not exist: creating new one" << std::endl; + } else { + // read all vars from the work file into a map with unique keys and true/false values + while (std::getline(work_vars, line)) { + line = helper::StringUtils::removeTrailingComments(line, "#"); + line = helper::StringUtils::trimFast(line); + if (line.size() > 0) { + // if a var is marked with a "-" at the beginning exclude it from the conversion by setting the map value to false + if (line[0] == '-') { + workVars[line.substr(1)] = false; + } else { + workVars[line] = true; + } + } + } + } + + // try to open the default vars file - if it does not exist, print an error message and return + std::ifstream default_vars(DEFAULT_VARS_FILE); + if (default_vars.fail()) { + std::cerr << "Default vars file does not exist" << std::endl; + return; + } + + // read the default vars file and copy all vars which are not in the work to var list from the work file + while (std::getline(default_vars, line)) { + line = helper::StringUtils::removeTrailingComments(line, "#"); + line = helper::StringUtils::trimFast(line); + // add the var to the work map if it is not already in the map + if (line.size() > 0 && workVars.find(line) == workVars.end()) { + workVars[line] = true; + } + } + default_vars.close(); + + // Write the new var list to the work file sorted alphabetically by the var name and close the file + // add a some comments to the first lines of the work file and ignore them when reading the file + std::ofstream workFile(WORK_VARS_FILE, std::ios::trunc); + workFile << "# This file contains the list of LVars that are converted to raw values for the ARINC429 bridge" << std::endl; + workFile << "# Lines starting with a '-' are excluded from the conversion" << std::endl; + workFile << "# This files will be rewritten at every start of the aircraft to include potential new LVars" << std::endl; + workFile << "# The LVars are sorted alphabetically and the exclusion with \"-\" are preserver" << std::endl; + workFile << std::endl; + for (const auto& [key, value] : workVars) { + if (value) { + workFile << key << std::endl; + } else { + workFile << "-" << key << std::endl; + } + } + workFile.close(); + + // now rebuild the arinc429Vars vector with the vars from the work map marked as to be included in the conversion + for (const auto& [key, value] : workVars) { + if (value) { + registerConvertedVars(key); + } + } + + varFileRead = true; +} + +void Arinc429LvarConverter::registerConvertedVars(const std::string& line) { // register converted vars + // check first if the var exists in the sim - if not skip it + if (check_named_variable(line.c_str()) == -1) { + LOG_ERROR("FlyByWire Arinc429LVarBridge: Could not find variable in sim: " + line); + return; + } + + // register the raw value var + const std::string convertedVar = line + ARINC429_LVAR_RAW_SUFFIX; + auto id = register_named_variable(line.c_str()); + auto mappedId = register_named_variable(convertedVar.c_str()); + arinc429Vars.push_back(std::pair(id, mappedId)); +} diff --git a/fbw-arinc429-lvar-bridge/src/wasm/arinc429-lvar-bridge/src/Arinc429LvarConverter.h b/fbw-arinc429-lvar-bridge/src/wasm/arinc429-lvar-bridge/src/Arinc429LvarConverter.h new file mode 100644 index 00000000000..3ab409319cf --- /dev/null +++ b/fbw-arinc429-lvar-bridge/src/wasm/arinc429-lvar-bridge/src/Arinc429LvarConverter.h @@ -0,0 +1,83 @@ +// Copyright (c) 2023-2024 FlyByWire Simulations +// SPDX-License-Identifier: GPL-3.0 + +#ifndef FLYBYWIRE_AIRCRAFT_ARINC429LVARCONVERTER_H +#define FLYBYWIRE_AIRCRAFT_ARINC429LVARCONVERTER_H + +#include +#include + +#include +#include +#include "SimpleProfiler.hpp" + +static const std::string ARINC429_LVAR_RAW_SUFFIX = "_RAW"; // the suffix we add to the raw LVars +static const std::string DEFAULT_VARS_FILE = "\\modules\\arinc429_vars.txt"; +static const std::string WORK_VARS_FILE = "\\work\\aring429_vars.txt"; + +/** + * @brief The Arinc429LvarConverter class is used to convert ARINC429 LVars to raw values and to register the raw value + * LVars in the sim. As the ARINC429 LVars are not directly readable without the proper conversion, this class + * provides the conversion and registration of the raw value LVars for the ARINC429 LVars so that they can be + * used by third parties without having to know the ARINC429 specifics. + * + * This class uses a set of control variables to control the behavior of the converter: + * - FBW_ARINC429_LVAR_BRIDGE_ON: to activate the converter + * - FBW_ARINC429_LVAR_BRIDGE_INIT: to trigger the re-reading of the config files containing the ARINC429 LVars + * - FBW_ARINC429_LVAR_BRIDGE_VERBOSE: to enable verbose output + * + * The converter reads the ARINC429 LVars from a var file that is located in the package's module folder. The file + * should contain the Arinc 429 LVars (one each line) which are to be converted to raw values. + * These LVars are then copied to the work file in the "work" folder. This file can be edited by the user to add or + * mark LVars as "not to be converted". The converter will then use all LVars from the work file and create corresponding + * raw value LVars in the sim. If the FBW_ARINC429_LVAR_BRIDGE_ON control variable is set, the converter will convert the ARINC429 LVars to + * raw values at every frame and update the raw value LVars in the sim. + */ +class Arinc429LvarConverter { + private: + // prevents running update before init + bool initialized = false; + + // flag to signal that the var file has been read + bool varFileRead = false; + + // counter for the ticks (calls to update) + int64_t tickCounter = 0; + + // control variables + ID isReadyID; + ID isArinc429LvarBridgeOnID; + ID doArinc429LvarBridgeInit; + ID isArinc429LvarBridgeVerbose; + + // the list of all LVars that are converted from ARINC429 to raw values + std::vector> arinc429Vars; + + // profiler for the converter + SimpleProfiler profiler{"Arinc429LVarConverter", 100}; + + public: + /** + * @brief Initializes the Arinc429LvarConverter. Must be called before update. + */ + void init(); + + /** + * @brief Updates the Arinc429LvarConverter. Must be called after init and is called every frame. + */ + void update(); + + private: + /** + * @brief Register the raw value variable names in the sim. + * @param line the line from the var file + */ + void registerConvertedVars(const std::string& line); + + /** + * @brief Read the var file and register the raw value variable names in the sim. + */ + void readVarFile(); +}; + +#endif // FLYBYWIRE_AIRCRAFT_ARINC429LVARCONVERTER_H diff --git a/fbw-common/src/wasm/cpp-msfs-framework/CMakeLists.txt b/fbw-common/src/wasm/cpp-msfs-framework/CMakeLists.txt index eb6d017ca94..6780164a0ac 100644 --- a/fbw-common/src/wasm/cpp-msfs-framework/CMakeLists.txt +++ b/fbw-common/src/wasm/cpp-msfs-framework/CMakeLists.txt @@ -50,3 +50,6 @@ target_compile_definitions(cpp-msfs-framework-a32nx PUBLIC A32NX) add_library(cpp-msfs-framework-a380x OBJECT ${SOURCE_FILES} ${INCLUDE_FILES}) target_compile_definitions(cpp-msfs-framework-a380x PUBLIC A380X) + +add_library(cpp-msfs-framework-lvar-provider OBJECT ${SOURCE_FILES} ${INCLUDE_FILES}) +target_compile_definitions(cpp-msfs-framework-lvar-provider PUBLIC LVAR_PROVIDER) diff --git a/fbw-common/src/wasm/cpp-msfs-framework/MsfsHandler/DataManager.h b/fbw-common/src/wasm/cpp-msfs-framework/MsfsHandler/DataManager.h index 3676c373a56..8b4db999287 100644 --- a/fbw-common/src/wasm/cpp-msfs-framework/MsfsHandler/DataManager.h +++ b/fbw-common/src/wasm/cpp-msfs-framework/MsfsHandler/DataManager.h @@ -294,8 +294,8 @@ class DataManager { * @note When reusing a DataDefinitionVariable make sure to know how this DataDefinition is updated and DO NOT CHANGE the update mode * or periodic update settings of the DataDefinitionVariable. This could lead to unexpected behavior in other modules sharing the * same DataDefinitionVariable. Especially as the periodic update settings cannot be retrieved from the sim and the - * DataDefinitionVariable does not store the the periodic update settings as these could get easily out of sync (e.g. by using SimConnect - * directly to change them) which would be worse than not having them at all. + * DataDefinitionVariable does not store the the periodic update settings as these could get easily out of sync (e.g. by using SimConnect + * directly to change them) which would be worse than not having them at all. * * @tparam T The type of the DataDefinitionVariable to retrieve. * @param name The name of the DataDefinitionVariable to retrieve. diff --git a/fbw-common/src/wasm/cpp-msfs-framework/test/CMakeLists.txt b/fbw-common/src/wasm/cpp-msfs-framework/test/CMakeLists.txt index f5d1a5fa511..9c453c073be 100644 --- a/fbw-common/src/wasm/cpp-msfs-framework/test/CMakeLists.txt +++ b/fbw-common/src/wasm/cpp-msfs-framework/test/CMakeLists.txt @@ -10,6 +10,10 @@ set(CMAKE_CXX_STANDARD 20) # compiler refinement set(COMPILER_FLAGS "-g -O0 -Wall -Wextra -Werror -Wshadow -fprofile-arcs -ftest-coverage -pthread") +# Paths +set(FBW_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../) +set(FBW_COMMON ${FBW_ROOT}/fbw-common/src/wasm) + # ==================================================================== # Source files # ==================================================================== @@ -27,6 +31,15 @@ set(SOURCE_FILES # Include directories # ==================================================================== set(INCLUDE_FILES + # these do not work in the test environment + # "${MSFS_SDK}/WASM/include" + # "${MSFS_SDK}/WASM/wasi-sysroot/include" + # "${MSFS_SDK}/WASM/wasi-sysroot/include/c++/v1" + # "${MSFS_SDK}/SimConnect SDK/include" + # "${FBW_COMMON}/cpp-msfs-framework/lib" + # "${FBW_COMMON}/cpp-msfs-framework/MsfsHandler" + # "${FBW_COMMON}/cpp-msfs-framework/MsfsHandler/DataTypes" + ../lib ) @@ -65,5 +78,3 @@ add_executable(${testExeName} ${SOURCE_FILES} ${INCLUDE_FILES}) target_link_libraries(${testExeName} PUBLIC gtest gtest_main) gtest_discover_tests(${testExeName}) - - diff --git a/igniter.config.mjs b/igniter.config.mjs index 56c9701c654..acb037c7fba 100644 --- a/igniter.config.mjs +++ b/igniter.config.mjs @@ -1,6 +1,6 @@ import { ExecTask, TaskOfTasks } from '@flybywiresim/igniter'; -import { getInstrumentsIgniterTasks as getA320InstrumentsIgniterTasks } from './fbw-a32nx/src/systems/instruments/buildSrc/igniter/tasks.mjs'; -import { getInstrumentsIgniterTasks as getA380InstrumentsIgniterTasks } from './fbw-a380x/src/systems/instruments/buildSrc/igniter/tasks.mjs'; +import {getInstrumentsIgniterTasks as getA320InstrumentsIgniterTasks} from './fbw-a32nx/src/systems/instruments/buildSrc/igniter/tasks.mjs'; +import {getInstrumentsIgniterTasks as getA380InstrumentsIgniterTasks} from './fbw-a380x/src/systems/instruments/buildSrc/igniter/tasks.mjs'; export default new TaskOfTasks('all', [ // A32NX Task @@ -250,6 +250,27 @@ export default new TaskOfTasks('all', [ ]), ]), + // Arinc429 LVar Bridge Tasks + new TaskOfTasks("arinc429-lvar-bridge", [ + // Prepare the out folder and any other pre tasks. + // Currently, these can be run in parallel, but in the future, we may need to run them in sequence if there are any dependencies. + new TaskOfTasks("preparation", [ + new ExecTask("copy-base-files", "npm run build-arinc429-lvar-bridge:copy-base-files") + ]), + + new ExecTask('cpp-wasm-cmake', + "npm run build:cpp-wasm-cmake", + [ + 'fbw-common/src/wasm/cpp-msfs-framework', + 'fbw-arinc429-lvar-bridge/src/wasm/arinc429-lvar-bridge', + 'fbw-arinc429-lvar-bridge/out/flybywire-arinc429-lvar-bridge/panel/arinc429-lvar-bridge.wasm' + ]), + + new TaskOfTasks("dist", [ + new ExecTask("manifests", "npm run build-arinc429-lvar-bridge:manifest") + ]) + ]), + // InGamePanels Checklist Fix Tasks new TaskOfTasks('ingamepanels-checklist-fix', [ // Prepare the out folder and any other pre tasks. diff --git a/package.json b/package.json index 1aa5cde4aff..a977ee33479 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "build:cpp-wasm-cmake-debug": "scripts/build-cmake.sh --debug", "build:cpp-wasm-cmake-debug-clean": "scripts/build-cmake.sh --debug --clean", "build:cpp-wasm-cmake-test": "cd fbw-common/src/wasm/cpp-msfs-framework/test && ./test-cpp.sh", + "====== A320 =============================================================": "========================================================", "build-a32nx:copy-base-package": "mkdir -p fbw-a32nx/out/flybywire-aircraft-a320-neo && (rsync -a fbw-a32nx/src/base/flybywire-aircraft-a320-neo fbw-a32nx/out/ || cp -a -u fbw-a32nx/src/base/flybywire-aircraft-a320-neo fbw-a32nx/out/)", "build-a32nx:copy-base-lock-highlight-package": "mkdir -p fbw-a32nx/out/flybywire-aircraft-a320-neo-lock-highlight && (rsync -a fbw-a32nx/src/base/flybywire-aircraft-a320-neo-lock-highlight fbw-a32nx/out/ || cp -a -u fbw-a32nx/src/base/flybywire-aircraft-a320-neo-lock-highlight fbw-a32nx/out/)", @@ -62,6 +63,9 @@ "build-a380x:terronnd": "cd fbw-common/src/wasm/terronnd && ./build.sh --a380x && wasm-opt -O1 --signext-lowering -o /external/fbw-a380x/out/flybywire-aircraft-a380-842/SimObjects/AirPlanes/FlyByWire_A380_842/panel/terronnd.wasm /external/fbw-common/src/wasm/terronnd/out/terronnd_A380X.wasm", "build-a380x:metadata": "node scripts/metadata.js fbw-a380x/out/flybywire-aircraft-a380-842 a380x", "build-a380x:manifest": "node scripts/build_a380x.js flybywire-aircraft-a380-842", + "====== LVar Provider ====================================================": "========================================================", + "build-arinc429-lvar-bridge:copy-base-files": "mkdir -p fbw-arinc429-lvar-bridge/out/flybywire-arinc429-lvar-bridge && (rsync -a fbw-arinc429-lvar-bridge/src/base/flybywire-arinc429-lvar-bridge fbw-arinc429-lvar-bridge/out/ || cp -a -u fbw-arinc429-lvar-bridge/src/base/flybywire-arinc429-lvar-bridge fbw-arinc429-lvar-bridge/out/)", + "build-arinc429-lvar-bridge:manifest": "node scripts/build_arinc429-lvar-bridge.js", "====== INGAMEPANELS CHECKLIST FIX =======================================": "========================================================", "build-ingamepanels-checklist-fix:copy-base-package": "mkdir -p fbw-ingamepanels-checklist-fix/out/flybywire-ingamepanels-checklist-fix && (rsync -a fbw-ingamepanels-checklist-fix/src/base/flybywire-ingamepanels-checklist-fix fbw-ingamepanels-checklist-fix/out/ || cp -a -u fbw-ingamepanels-checklist-fix/src/base/flybywire-ingamepanels-checklist-fix fbw-ingamepanels-checklist-fix/out/)", "build-ingamepanels-checklist-fix:copy-base-files": "npm run build-ingamepanels-checklist-fix:copy-base-package", diff --git a/scripts/build-cmake.sh b/scripts/build-cmake.sh index 159ef257393..48978d9710b 100755 --- a/scripts/build-cmake.sh +++ b/scripts/build-cmake.sh @@ -36,18 +36,26 @@ while [ $# -gt 0 ]; do shift done -A32NX_WASM_OUT_DIR="../fbw-a32nx/out/flybywire-aircraft-a320-neo/SimObjects/AirPlanes/FlyByWire_A320_NEO/panel" -if [ ! -d "$A32NX_WASM_OUT_DIR" ]; then - echo "$A32NX_WASM_OUT_DIR directory does not exist." - mkdir -p $A32NX_WASM_OUT_DIR - echo "$A32NX_WASM_OUT_DIR directory created." -fi -A380X_WASM_OUT_DIR="../fbw-a380x/out/flybywire-aircraft-a380-842/SimObjects/AirPlanes/FlyByWire_A380_842/panel" -if [ ! -d "$A380X_WASM_OUT_DIR" ]; then - echo "$A380X_WASM_OUT_DIR directory does not exist." - mkdir -p $A380X_WASM_OUT_DIR - echo "$A380X_WASM_OUT_DIR directory created." -fi +# Define a list of directory paths to check if they exist, create if not, and print messages +declare -A directories=( + ["A32NX_WASM_OUT_DIR"]="../fbw-a32nx/out/flybywire-aircraft-a320-neo/SimObjects/AirPlanes/FlyByWire_A320_NEO/panel" + ["A380X_WASM_OUT_DIR"]="../fbw-a380x/out/flybywire-aircraft-a380-842/SimObjects/AirPlanes/FlyByWire_A380_842/panel" + ["FBW_ARINC429_LVAR_BRIDGE_WASM_OUT_DIR"]="../fbw-arinc429-lvar-bridge/out/flybywire-arinc429-lvar-bridge/modules" +) + +# Loop over the directory paths to check if they exist, create if not, and print messages +for dir_var in "${!directories[@]}"; do + dir_path="${directories[$dir_var]}" + + if [ ! -d "$dir_path" ]; then + echo "$dir_path directory does not exist." + mkdir -p "$dir_path" + echo "$dir_path directory created." + else + echo "$dir_path directory already exists." + fi +done + echo "Toolchain versions:" cmake --version @@ -55,7 +63,7 @@ clang++ --version wasm-ld --version echo "" -echo "Building extra-backend with CMAKE..." +echo "Building with CMAKE..." cmake -DCMAKE_TOOLCHAIN_FILE=scripts/cmake/DockerToolchain.cmake -B${OUTPUT_DIR} -DCMAKE_BUILD_TYPE=${CONFIG} ../ || (echo "CMake config failed"; exit 1) cmake --build ${OUTPUT_DIR} --config ${CONFIG} ${CLEAN} -j ${PARALLEL} || (echo "CMake build failed"; exit 1) echo "" diff --git a/scripts/build.sh b/scripts/build.sh index 404a6c3e72a..c633dbea49a 100755 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -23,6 +23,7 @@ for arg in "$@"; do rm -rf /external/fbw-a32nx/bundles rm -rf /external/fbw-a380x/out rm -rf /external/fbw-ingamepanels-checklist-fix/out + rm -rf /external/fbw-lvar-provider/out # If the argument is "-4k", build with 4k textures instead of maximum resolution elif [ "$arg" = "-4k" ]; then USE_4K_TEXTURES="true" diff --git a/scripts/build_arinc429-lvar-bridge.js b/scripts/build_arinc429-lvar-bridge.js new file mode 100644 index 00000000000..0af7c1b0821 --- /dev/null +++ b/scripts/build_arinc429-lvar-bridge.js @@ -0,0 +1,81 @@ +// Copyright (c) 2023-2024 FlyByWire Simulations +// SPDX-License-Identifier: GPL-3.0 + +'use strict'; + +const fs = require('fs'); +const path = require('path'); + +function* readdir(d) { + for (const dirent of fs.readdirSync(d, { withFileTypes: true })) { + if (['layout.json', 'manifest.json'].includes(dirent.name)) { + continue; + } + const resolved = path.join(d, dirent.name); + if (dirent.isDirectory()) { + yield* readdir(resolved); + } else { + yield resolved; + } + } +} + +const { execSync } = require('child_process'); + +function executeGitCommand(command) { + return execSync(command) + .toString('utf8') + .replace(/[\n\r]+$/, ''); +} + +const buildInfo = require('./git_build_info').getGitBuildInfo(); +const packageInfo = require('../package.json'); + +let titlePostfix; +if (packageInfo.edition === 'stable') { + titlePostfix = 'Stable'; +} else if (buildInfo?.branch === 'master') { + titlePostfix = 'Development'; +} else if (buildInfo?.branch === 'experimental') { + titlePostfix = 'Experimental'; +} else if (buildInfo?.isPullRequest) { + titlePostfix = `PR #${buildInfo?.ref}`; +} else { + titlePostfix = `branch ${buildInfo?.branch}`; +} +const titleSuffix = ` (${titlePostfix})`; + +const MS_FILETIME_EPOCH = 116444736000000000n; + +const SRC_FOLDER = path.resolve(__dirname, '..', 'fbw-arinc429-lvar-bridge/src'); +const OUT_FOLDER = path.resolve(__dirname, '..', 'fbw-arinc429-lvar-bridge/out'); + +function createPackageFiles(baseDir, manifestBaseFilename) { + const contentEntries = []; + let totalPackageSize = 0; + + for (const filename of readdir(baseDir)) { + const stat = fs.statSync(filename, { bigint: true }); + contentEntries.push({ + path: path.relative(baseDir, filename.replace(path.sep, '/')), + size: Number(stat.size), + date: Number((stat.mtimeNs / 100n) + MS_FILETIME_EPOCH), + }); + totalPackageSize += Number(stat.size); + } + + fs.writeFileSync(path.join(baseDir, 'layout.json'), JSON.stringify({ + content: contentEntries, + }, null, 2)); + + const manifestBase = require(path.join(SRC_FOLDER, 'base', manifestBaseFilename)); + + fs.writeFileSync(path.join(baseDir, 'manifest.json'), JSON.stringify({ + ...manifestBase, + title: manifestBase.title + titleSuffix, + package_version: packageInfo.version + `-${buildInfo?.commitHash}`, + total_package_size: totalPackageSize.toString().padStart(20, '0'), + }, null, 2)); +} + +createPackageFiles(path.resolve(OUT_FOLDER, 'flybywire-arinc429-lvar-bridge'), 'manifest-base.json'); diff --git a/scripts/build_arinc429-lvar-bridge.sh b/scripts/build_arinc429-lvar-bridge.sh new file mode 100755 index 00000000000..4588dbf65e3 --- /dev/null +++ b/scripts/build_arinc429-lvar-bridge.sh @@ -0,0 +1,33 @@ +#!/bin/bash + +set -e + +# store current file ownership +ORIGINAL_USER_ID=$(stat -c '%u' /external) +ORIGINAL_GROUP_ID=$(stat -c '%g' /external) + +# set ownership to root to fix cargo/rust build (when run as github action) +if [ "${GITHUB_ACTIONS}" == "true" ]; then + chown -R root:root /external +fi + +# Loop through the arguments +args=() +for arg in "$@"; do + # If the argument is "-clean", perform some action + if [ "$arg" = "-clean" ]; then + echo "Removing out directories..." + rm -rf /external/fbw-lvar-provider/out + else + # Otherwise, add the arg it to the new array + args+=("$arg") + fi +done + +# run build +time npx igniter -r 'arinc429-lvar-bridge' "${args[@]}" + +# restore ownership (when run as github action) +if [ "${GITHUB_ACTIONS}" == "true" ]; then + chown -R ${ORIGINAL_USER_ID}:${ORIGINAL_GROUP_ID} /external +fi