Aerofly FS4 SDK - External DLL

  • Instead of using TCP sockets and JSON parsing, this implementation uses Windows shared memory to create a direct data bridge between Aerofly FS 4 and external applications.

    This is the way to go, if we are to stay on Windows and only need to consider local applications. Actually way more efficient than having a network overhead or even writing a local file over and over again.

    Thank you for your work and research, Jugac64 and a nice trip.

  • Hi, I am back 8)

    Here it is a complete list of the 285 variables we can access using the Aerofly FS4 DLL SDK.

    Please comment if some corrections must be done. The document was generated automatically by Claude Sonnet:

    Aerofly FS4 SDK - Complete Variable Reference (285 Variables)

    It can be downloaded as a PDF, the file size was too big to add it here.

  • Hi Jan /developers, can you check please the document if it is correct, something is missing, etc.

    Next step will be to build a new DLL that will provide us the shared memory access to the variables, so it would we great to know if we are starting from a good place.

    And next-next step, will be to build a Python sort of SDK to simplify the access to the shared memory varíables.

    If all this works, I will try to integrate Sayintentions.

  • Here it is the first update about our work. Luckily, today is holiday in my country :)

    # 🚀 Aerofly FS 4 Bridge DLL - Bidirectional Integration Project

    Hello community! I want to share the progress of an exciting project we’re developing to expand Aerofly FS 4’s integration capabilities.

    ## 📋 What are we building?

    A **complete Bridge DLL** that enables bidirectional communication between Aerofly FS 4 and external applications (Python, C++, web apps, etc.).

    ## 🎯 Current Status: **FUNCTIONAL** ✅

    ### ✅ **WHAT’S ALREADY WORKING**

    **📊 Data Reading (Ultra-fast):**

    - **285 variables** from the SDK completely mapped and accessible
    - **Shared Memory interface**: Sub-millisecond latency for real-time data
    - **TCP JSON streaming**: Network-ready for remote applications
    - **Simultaneous multi-client** support

    **🎮 Command Writing (Bidirectional Control):**

    - **Flight controls**: Flaps, gear, throttle, pitch/roll/yaw inputs ✅ TESTED
    - **COM/NAV frequencies**: Radio management
    - **Autopilot commands**: Altitude, heading, airspeed selection
    - **Real-time response**: Commands execute immediately in simulator

    ### 🏗️ **Architecture Overview**

    ```
    Aerofly FS 4 ↔ AeroflyBridge.dll ↔ Multiple Interfaces ↔ External Apps
    ↓
    [Shared Memory] ← Ultra-fast (local)
    [TCP Server] ← Network/Python
    [JSON API] ← Web/Mobile
    ```

    **Data Flow:**

    - **Reading**: Aerofly → DLL → Shared Memory/TCP → Applications
    - **Writing**: Applications → TCP Commands → DLL → Aerofly

    ## 🧪 **TESTING RESULTS**

    **✅ Shared Memory Test:**

    - Access to flight data: Position, altitude, speeds, attitude
    - Update frequency: ~60Hz
    - Latency: <1ms
    - Data integrity: 100% reliable

    **✅ Command Control Test:**

    - Flap control: **WORKING** - Visual movement confirmed in simulator
    - Throttle control: **WORKING**
    - Real-time response confirmed

    ## 🛠️ **Technical Implementation**

    **Built using:**

    - Official IPACS SDK (`tm_external_message.h`)
    - Visual Studio 2022 compilation
    - Thread-safe operations
    - Multi-interface architecture

    **Performance:**

    - Zero impact on simulator FPS
    - Concurrent client support
    - Robust error handling

    ## 🎯 **POTENTIAL APPLICATIONS**

    This bridge opens up incredible possibilities:

    **🎮 Hardware Integration:**

    - Force Feedback systems using G-force data
    - Custom instrument panels
    - Motion platform control

    **📊 Navigation & Analysis:**

    - XCSoar integration for gliding
    - Flight data logging and analysis
    - Real-time performance monitoring

    **🌐 Remote & Web Applications:**

    - Mobile apps for flight monitoring
    - Web-based dashboards
    - Multi-user training scenarios

    **🤖 AI & Automation:**

    - Machine learning flight data collection
    - Automated flight testing
    - Custom autopilot algorithms

    ## 🔧 **CURRENT WORK & NEXT STEPS**

    **Phase 1 (Current):** ✅ Core functionality working
    **Phase 2 (In Progress):**

    - Fine-tuning variable mapping
    - Python SDK development
    - Thread cleanup optimization

    **Phase 3 (Planned):**

    - Complete Python SDK with examples
    - C++ library for native applications
    - Web API for browser-based apps
    - Comprehensive documentation

    ## 🤝 **COMMUNITY COLLABORATION**

    This project is being developed with community feedback in mind. We’re building:

    - **Open architecture** for easy integration
    - **Standard protocols** (JSON, shared memory)
    - **Multi-language support** from day one

    ## 📋 **FOR DEVELOPERS**

    If you’re interested in integration development, this bridge will provide:

    - Direct access to all 285 simulator variables
    - Real-time control capabilities
    - Multiple interface options for different use cases
    - Production-ready stability

    ## 🎊 **EXCITING PROGRESS**

    We’ve successfully achieved **bidirectional control** - something that’s been a long-time goal for the Aerofly community. The ability to both read data AND control the simulator opens up entirely new possibilities for hardware integration, training applications, and community projects.

    **Stay tuned for more updates!** We’ll be sharing the complete Python SDK and examples soon.

    -----

    *Built with love for the Aerofly FS 4 community* ✈️

  • Hopefully this can also be set up for us Mac users.🙏

    Tschüss, Michael (🍎🚁)

    Configurations:

    - MacBook Pro (16", 2024); Chip: Apple M4 Max; actual macOS
    - Controllers: | WinWing: URSA MINOR-Fighter-Joystick R, EFIS-L & FCU & EFIS-R | Thrustmaster TCA AIRBUS EDITION: 2x Quadrant, 2x Quadrant Add-On | Pro-Flight-Trainer: PUMA X | Steelseries: Nimbus+

    - iPad (12,9", 4th Generation, RAM: 6 GB); actual iOS | Steelseries: Nimbus+

  • Hi, here it is the actual state of the DLL source code, so you can take a look:

    (Please see last post)

    And here it is the source code of the Python test program:

    (same)

    Work in progress, I want to check all the most important variables, but just wanted to share where we are.

    Here you can see some pics of the Python app communicating with the sim using the DLL:

  • Jugac64 This looks very clean and makes understanding the code way more simple.

    Out of curiosity: there are lots of else if statements, are they more performant than a switch operation? Or are switch operations in this environment not possible?

    Given the task of the DLL performance is more important than any other consideration, this could be considered.

  • Jugac64 This looks very clean and makes understanding the code way more simple.

    Out of curiosity: there are lots of else if statements, are they more performant than a switch operation? Or are switch operations in this environment not possible?

    Given the task of the DLL performance is more important than any other consideration, this could be considered.

    TBH if they're using AI to write the code in Python (instead of hand written C++ for example) then performance is probably not top priority.

  • Hello! This is built 100% by AI. I started the project with Claude.ai web tool (similar to ChatGPT interface),. After the DLL code increases it size too much, it was difficult to work on it in the web tool, and I continued it in Cursor IDE, always working with Claude Sonnet 4. Before this project I had never compiled a C++ DLL or working with C++. Just as a reference, I haven’t worked more than 20-30 hours on this.

    Any suggestion to improve it is welcome, it is as easy as to ask the AI to implement it. I generally discuss all the decisions with it, and ask it for advice and suggestions.

    Thanks Frank for the suggestion! I will ask about it.

    And thanks Jan for the feedback, for the moment the main goal is to be able to read all the available variables and to be capable of doing control on all the ones we can write. In the Python app, when the category tabs are selected, I see a 10-15-Hz refresh. When all the variables are read in the last tab (last picture of the tab), it slow down to about 1Hz or less.

    When the first goal is achieved, I will try to improve the efficiency. One thing is pending is to implement this:


    ## Hash-Based Variable Processing Optimization

    ### Performance Issue

    Current variable processing uses sequential if/else chains:

    ```cpp
    void ProcessMessage(const tm_external_message& message) {
    const auto hash = message.GetStringHash().GetHash();
       
    if (hash == MessageAircraftLatitude.GetID()) {
    // process latitude
    } else if (hash == MessageAircraftLongitude.GetID()) {
    // process longitude
    } else if (hash == MessageAircraftAltitude.GetID()) {
    // process altitude
    }
    // ... 100+ more comparisons
    }
    ```

    **Problem**: O(n) complexity - worst case 100+ comparisons per variable

    ### Hash Table Solution

    Replace with O(1) hash table lookup:

    ```cpp
    class OptimizedVariableProcessor {
    private:
    std::unordered_map<uint64_t, std::function<void(const tm_external_message&, AeroflyBridgeData*)>> processors;
       
    public:
    void InitializeProcessors() {
    // Direct hash-to-function mapping
    processors[MessageAircraftLatitude.GetID()] = [](const tm_external_message& msg, AeroflyBridgeData* data) {
    data->latitude = msg.GetDouble();
    data->all_variables[(int)VariableIndex::AIRCRAFT_LATITUDE] = msg.GetDouble();
    };
           
    processors[MessageAircraftLongitude.GetID()] = [](const tm_external_message& msg, AeroflyBridgeData* data) {
    data->longitude = msg.GetDouble();
    data->all_variables[(int)VariableIndex::AIRCRAFT_LONGITUDE] = msg.GetDouble();
    };
           
    // Add all 285+ variables...
    }
       
    void ProcessMessage(const tm_external_message& message, AeroflyBridgeData* data) {
    const uint64_t hash = message.GetStringHash().GetHash();
           
    auto it = processors.find(hash); // O(1) lookup
    if (it != processors.end()) {
    it->second(message, data); // Direct function call
    }
    }
    };
    ```

    ### Performance Benefits

    - **Speed**: 10-50x faster processing (O(1) vs O(n))
    - **Scalability**: Performance doesn’t degrade with more variables
    - **Memory**: Minimal overhead (~8 bytes per variable)

    ### Implementation Benefits

    - **Cleaner Code**: Each variable has its own processor function
    - **Error Handling**: Individual try/catch per variable type
    - **Maintainability**: Easy to add new variables
    - **Debugging**: Built-in statistics and unknown variable detection

    ### Usage

    ```cpp
    // Replace your current ProcessMessage with:
    OptimizedVariableProcessor processor;

    void ProcessMessage(const tm_external_message& message) {
    processor.ProcessMessage(message, pData); // One line!
    }
    ```

    ### Critical Variable Prioritization

    ```cpp
    // Process flight-critical variables first
    std::unordered_set<uint64_t> critical_variables = {
    MessageAircraftLatitude.GetID(),
    MessageAircraftLongitude.GetID(),
    MessageAircraftAltitude.GetID(),
    MessageAircraftPitch.GetID(),
    MessageAircraftBank.GetID()
    // ...
    };
    ```

    **Recommendation**: This optimization is essential for production DLLs processing 100+ variables at high frequency. The performance gain is dramatic with minimal implementation effort.

  • I have been introduced to AI-assisted programming for the last few months. It has been a dramatic improvement. For me it is like constant pair-programming with a incredible quick junior developer who knows everything, even though sometimes not grasping the finer points. ^^

    The discussions with AI sometimes teach me stuff that keeps me awake for the whole night. ^^

    (Some days ago I fed AI some binary data files with some guesses what was supposed to be in there - in this case a world map with a magnetic model. It discovered for me the tabular data, and gave me a small Python script to build my own model in the exact same format, but with current data downloaded from the internet. I was surprised to say the least.)

  • It is very shocking at the beginning with a lot of wow! moments, but as like with everything you get used to it. Maybe now the most impressive to me is the speed it can work. From the time I have been working in this, I doubt that Claude has been writing code for more than 1 hour. Most of the time is spend in discussions, analyzing, testing, fixing errors, going back and forward.

    Please anyone that wants to contribute to this new DLL development, please participate. This is for the benefit of all the AFS4 users.

    The new DLL is the tool we need to do the integrations with the real applications, is not an objective in itself. It is a bridge :)

  • Hello,

    Thank you again for sharing this excellent project!

    I’ve been testing the Python script `aerofly_variable_monitor_v5.py` along with the provided `AeroflyBridge.dll`, but I’m still unable to establish a connection. I’m using the exact setup described, and Aerofly FS4 is running with an aircraft loaded on the runway.

    I’ve already added the correct `external_dll` line to the `main.mcf` file and placed the DLL in the appropriate folder (`Documents\Aerofly FS 4\external_dll\AeroflyBridge\`), but the GUI still shows “Disconnected” and fails to connect.

    Is there anything else I need to check or enable? Do I need to use a specific version of Aerofly FS4 or launch it in a special way?

    The GUI looks amazing, and I’d really love to get it working. I believe this could become the foundation for a full ATC/Voice system I’m building.

    Thanks a lot in advance.

    Bests Regards,

    Pascal

  • Jugac64 This is great, on my part compiling and running the Python sample script is working. I am quite impressed with actually sending commands from the outside into the simulation. (Even though having a joystick connected kills the signals send to variables which are mapped to joystick axes.)

    As of now I did not find anything to improve, as Claude obviously was smart enough to understand the finer points of C++ which I don't. :D