Jump to content
The simFlight Network Forums

Recommended Posts

Posted
       private static async Task StartSimInputOutputLoop()
       {
           Console.WriteLine("Starting Input/Output loop...");

           await Task.Run(async () =>
           {
               try
               {
                   FSUIPCConnection.Open(); // Open connection ONCE

                   while (!stopSimLoop)
                   {
                       try
                       {
                           Console.WriteLine("Checking FSUIPC data...");

                           // Process pending inputs (Write to LVARs)
                           if (simdata_input_pending != null)
                           {
                               foreach (string input in simdata_input_pending)
                               {
                                   string[] i = input.Split(',');
                                   if (i.Length >= 2)
                                   {
                                       string lvar = i[0].Trim();
                                       if (float.TryParse(i[1].Trim(), out float newValue))
                                       {
                                           // Send command to update LVAR
                                           Offset<string> setLvar = new Offset<string>(0x0D70, 256);
                                           setLvar.Value = $"L:{lvar}={newValue}";
                                           FSUIPCConnection.Process();

                                           Console.WriteLine($" Updated LVAR: {lvar} = {newValue}");
                                       }
                                   }
                               }
                               simdata_input_pending = null;
                           }

                           // Read LVAR values properly
                           if (simdata_lvars != null)
                           {
                               simdata_output = new string[simdata_lvars.Length];

                               for (int j = 0; j < simdata_lvars.Length; j++)
                               {
                                   string lvarName = simdata_lvars[j];

                                   // Send request to get LVAR value
                                   Offset<string> getLvarRequest = new Offset<string>(0x0D70, 256);
                                   getLvarRequest.Value = $"L:{lvarName}";
                                   FSUIPCConnection.Process();

                                   // Wait a bit for FSUIPC to process the request
                                   await Task.Delay(100);

                                   // Retrieve the actual LVAR value from offset 0x66C0 (example offset)
                                   Offset<float> getLvarResponse = new Offset<float>(0x66C0);
                                   FSUIPCConnection.Process(); // Fetch updated value
                                   // Store and print result
                                   float lvarValue = getLvarResponse.Value;
                                   simdata_output[j] = $"{lvarName}: {lvarValue}";

                                   Console.WriteLine($" [TEST] Read LVAR: {lvarName} = {lvarValue}"); // Debugging output
                               }
                           }
                       }
                       catch (Exception ex)
                       {
                           Console.WriteLine($" FSUIPC Read/Write Error: {ex.Message}");
                       }

                       await Task.Delay(5000); // Wait 5 seconds before next update
                   }
               }
               catch (Exception ex)
               {
                   Console.WriteLine($" FSUIPC Connection Error: {ex.Message}");
               }
               finally
               {
                   FSUIPCConnection.Close(); // Close connection when stopping
               }
           });
       }



i run this task,  to read out about 80ish. lvars. 
" ? FSUIPC Read/Write Error: FSUIPC Error #15: FSUIPC_ERR_SIZE. The amount of data requested exceeded the maximum allowed in one Process()." 

this is the result. is their a limit to the ammount of lvar data in a procces??  

also @Pete Dowson is their anyway we can turn process into a Task? so we can use a await?

Posted

Which SDK are you using? If using Paul Henty's client dll then you should post in that forum (I can move this post id you like).
Other than that, the error should be obvious (as indicated by the message), but as your process calls are in the loop and process one read/write at a time,  I don't know why the data limit is exceeded. But I am not familiar with the SDK you are using.

22 hours ago, michielsweb said:

also @Pete Dowson is their anyway we can turn process into a Task? so we can use a await?

Pete retired more than 5 years ago now. There are various wrappers around the basic FSUIPC SDK, some of which provide an event-driven interface. with Pai; Henty's dll being the most advanced.
 

Posted

I am not familiar with the SDK you are using, but this:

On 2/3/2025 at 11:24 AM, michielsweb said:
                                   Offset<string> getLvarRequest = new Offset<string>(0x0D70, 256);

Offset 0x0D70 is only 128 bytes, not 256. This also doesn't seem correct:

On 2/3/2025 at 11:24 AM, michielsweb said:
setLvar.Value = $"L:{lvar}={newValue}";

To update an lvar, the value must first be written to offset 0x0D6C. But I am not familiar with the SDK you are using, or which FS you are using (there is probably an easier API to access lvars if using MSFS). Maybe @Paul Henty could comment as I presume this is using his dll.

Posted

Yes, it's my DLL.

To michielsweb:

If you're only targeting MSFS2020 or MSFS2024 then you should look at the MSFSVariableServices class. This is way more efficient at dealing with LVARs than the FSUIPC interface. There is a demo project on the website. http://fsuipc.paulhenty.com/#downloads

You're exceeding the FSUIPC data limit because you keep declaring a new copy of the offset every time the loop goes round...

	foreach (string input in simdata_input_pending)
                               {
                                   string[] i = input.Split(',');
                                   if (i.Length >= 2)
                                   {
                                       string lvar = i[0].Trim();
                                       if (float.TryParse(i[1].Trim(), out float newValue))
                                       {
                                           // Send command to update LVAR
                                           Offset<string> setLvar = new Offset<string>(0x0D70, 256);

You'll end up with hundred of these, all being processed at the same time which will easily exceed the data limit for FSUIPC.

Offsets should only be declared once, usually at the class level, and then reused.

Quote

 is their anyway we can turn process into a Task? so we can use a await?

I have no immediate plans to make the library async. If you want async behaviour on the Process() call you can create and await a new Task...

await Task.Run(() => FSUIPCConnection.Process());

Paul

Posted

Hey Gentlemen,

 

first off all sorry for my late reply, work kept me occupied.  i just read the replies. i did do wasm interpertation in the mean time. 

But halfway through the lvar list i entered a 15 again.  so i wil attempt to read paul's script tommorow. hopefully i find out where i am going wrong. keep u all updated 🙂

Posted

@Paul Henty, looking into youre c# file.

Been trying to adjust your form version, to  a backend version.
for now using console for debugging. 

yet i get 0 off the  lvars found! even tough in fsuipc them self they are found.
is it the way i declare the lvars? 
tried the following methods.
L:FSDT_Deice_Available
FSDT_Deice_Available
(->L:FSDT_Deice_Available)

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
using FSUIPC;
using System.Deployment.Application;

namespace MSFSVariableServices_CSharp
{
    class Program
    {
        private static string[] simdata_lvars;
        private static double[] simdata_values;
        private static bool stopSimLoop = false;

        static async Task Main()
        {
            OpenConsoleWindow();
            Console.WriteLine("🔍 Starting FSUIPC connection test..."); //works

            if (!TestFSUIPCConnection())
            {
                Console.WriteLine(" FSUIPC connection failed. Make sure MSFS and FSUIPC are running."); // works if sim is off. 
                return;
            }

            Console.WriteLine(" FSUIPC connected. Proceeding...");  // works
            LoadLVarList();
            InitMSFSServices();
            await StartSimInputOutputLoop();
        }

        private static void OpenConsoleWindow()
        {
            bool attached = AttachConsole(-1);
            if (!attached)
            {
                AllocConsole();
                Console.WriteLine("🖥 New console created!"); //works
            }
            else
            {
                Console.WriteLine("🖥 Attached to existing console!"); //works
            }
        }


        [DllImport("kernel32.dll")]
        private static extern bool AllocConsole();

        [DllImport("kernel32.dll")]
        private static extern bool AttachConsole(int dwProcessId);

        private static bool TestFSUIPCConnection()
        {
            try
            {
                FSUIPCConnection.Open();
                Console.WriteLine(" FSUIPC connection successful."); // works
                FSUIPCConnection.Close();
                return true;
            }
            catch (Exception ex)
            {
                Console.WriteLine($" FSUIPC Connection Error: {ex.Message}"); 
                return false;
            }
        }

        private static void InitMSFSServices()
        {
            MSFSVariableServices.OnLogEntryReceived += VS_OnLogEntryReceived;
            MSFSVariableServices.OnVariableListChanged += VS_VariableListChanged;
            MSFSVariableServices.OnValuesChanged += VS_OnValuesChanged;
            MSFSVariableServices.Init();
            MSFSVariableServices.LogLevel = LOGLEVEL.LOG_LEVEL_INFO;
        }

        private static void VS_OnLogEntryReceived(object sender, LogEventArgs e)
        {
            Console.WriteLine($"[LOG] {e.LogEntry}");
        }

        private static void VS_VariableListChanged(object sender, EventArgs e)
        {
            Console.WriteLine("[INFO] Variable list updated.");
        }

        private static void VS_OnValuesChanged(object sender, EventArgs e)
        {
            Console.WriteLine("[INFO] LVAR values changed.");
        }

        private static void LoadLVarList()
        {
            string filePath = Path.Combine(Directory.GetCurrentDirectory(), "lvars.txt");
            if (File.Exists(filePath))
            {
                simdata_lvars = File.ReadAllLines(filePath);
                simdata_values = new double[simdata_lvars.Length];
                Console.WriteLine($" Loaded {simdata_lvars.Length} LVARs from file."); // works
            }
            else
            {
                Console.WriteLine($" Error: LVAR file not found: {filePath}");
                simdata_lvars = new string[0];
                simdata_values = new double[0];
            }
        }

        private static async Task StartSimInputOutputLoop()
        {
            while (!stopSimLoop)
            {
                await ReadSimDataMSFSVariableServices();
                await Task.Delay(500);
            }
        }

        private static async Task ReadSimDataMSFSVariableServices()
        {
            if (simdata_lvars == null || simdata_lvars.Length == 0)
            {
                Console.WriteLine("⚠️ No LVARs found in lvars.txt.");
                return;
            }

            for (int i = 0; i < simdata_lvars.Length; i++)
            {
                try
                {
                    string lvar = simdata_lvars[i].Trim();
                    if (!lvar.StartsWith("L:"))
                        lvar = "L:" + lvar;
                    FsLVar lvarObj = MSFSVariableServices.LVars[lvar];
                    if (lvarObj != null)
                    {
                        double newValue = lvarObj.Value;
                        if (simdata_values[i] != newValue)
                        {
                            simdata_values[i] = newValue;
                            Console.WriteLine($"📢 [UPDATED] {lvar}: {newValue}");
                        }
                    }
                    else
                    {
                        Console.WriteLine($" ERROR: LVAR {lvar} not found."); // i always end here even if the lvar is in fsuipc self active
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine($" ERROR reading LVAR {simdata_lvars[i]}: {ex.Message}");
                }
            }
            await Task.CompletedTask;
        }
    }
}


also @Paul Henty i would not mind if we get it too work, if this part is getting added to the sample. 
as i think is a more common way.  to extract the data from the sim, then read a value from the form 🙂

 

console.jpg

Posted

Looking at your output, you are getting nothing back from the WASM module at all.

When you call Init() the WASM client sends a log message telling you version info and if the WASM SimConnect connection is open or not.

You should also expect to see the events OnVariableListChanged and OnValuesChanged being fired, which is also not happening.

I suspect it can't find the FSUIPC_WAPID.dll file. Check that this is included in your project and that its property "Copy to output folder" is set to "Copy if newer" or "Copy always".

Quote

L:FSDT_Deice_Available
FSDT_Deice_Available

I can't remember if the names come through with the L: on or not. When you're getting variables through you can look at the collection:

MSFSVariableServices.LVars.Names 

to see what LVars it found and their exact names.

Paul

 

Posted
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
using FSUIPC;

namespace MSFSVariableServices_CSharp
{
    class Program
    {
        private static string[] simdata_lvars;
        private static double[] simdata_values;
        private static bool stopSimLoop = false;

        static async Task Main()
        {
            if (!TestFSUIPCConnection())
            {
                return;
            }
            InitMSFSServices();
            await WaitForMSFSVariableServices();
            MSFSVariableServices.Start();
            LoadLVarList();
            await StartSimInputOutputLoop();
        }
        private static bool TestFSUIPCConnection()
        {
            try
            {
                FSUIPCConnection.Open();
                Console.WriteLine("FSUIPC connection successful.");
                FSUIPCConnection.Close();
                return true;
            }
            catch (Exception ex)
            {
                Console.WriteLine($"FSUIPC Connection Error: {ex.Message}");
                return false;
            }
        }
        private static async Task WaitForMSFSVariableServices()
        {
            Console.WriteLine("Waiting for MSFSVariableServices to start...");

            int retries = 10;
            for (int i = 0; i < retries; i++)
            {
                if (MSFSVariableServices.IsRunning)
                {
                    Console.WriteLine("MSFSVariableServices is now running!");
                    return;
                }

                Console.WriteLine($"Attempt {i + 1}/{retries}: Waiting for MSFSVariableServices...");
                await Task.Delay(100);
            }

            Console.WriteLine("ERROR: MSFSVariableServices did not start. Check MSFS and FSUIPC.");
        }
        private static void InitMSFSServices()
        {
            Console.WriteLine("Initializing MSFS Variable Services...");
            try
            {
                MSFSVariableServices.OnLogEntryReceived += VS_OnLogEntryReceived;
                MSFSVariableServices.OnVariableListChanged += VS_VariableListChanged;
                MSFSVariableServices.OnValuesChanged += VS_OnValuesChanged;

                MSFSVariableServices.Init();
                MSFSVariableServices.LogLevel = LOGLEVEL.LOG_LEVEL_INFO;

                Console.WriteLine("MSFSVariableServices initialized successfully!");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"MSFSVariableServices Init Failed: {ex.Message}");
            }
        }

        private static void VS_OnLogEntryReceived(object sender, LogEventArgs e)
        {
        }

        private static void VS_VariableListChanged(object sender, EventArgs e)
        {
        }

        private static void VS_OnValuesChanged(object sender, EventArgs e)
        {
            foreach (FsLVar lvar in MSFSVariableServices.LVarsChanged)
            {
            }
        }

        private static void LoadLVarList()
        {
            string filePath = Path.Combine(Directory.GetCurrentDirectory(), "lvars.txt");
            if (File.Exists(filePath))
            {
                simdata_lvars = File.ReadAllLines(filePath);
                simdata_values = new double[simdata_lvars.Length];
            }
            else
            {
                simdata_lvars = new string[0];
                simdata_values = new double[0];
            }
        }

        private static async Task StartSimInputOutputLoop()
        {
            while (!stopSimLoop)
            {
                await ReadSimDataMSFSVariableServices();
                await Task.Delay(300);
            }
        }
        private static async Task WriteLVarValue(string lvarName, double value)
        {
            FsLVar lvar = MSFSVariableServices.LVars[lvarName];
            if (lvar != null)
            {
                lvar.SetValue(value);
            }
            else
            {
            }
            await Task.CompletedTask;
        }
        private static async Task ReadSimDataMSFSVariableServices()
        {
            if (simdata_lvars == null || simdata_lvars.Length == 0)
            {
                Console.WriteLine("No LVARs found in lvars.txt.");
                return;
            }

            for (int i = 0; i < simdata_lvars.Length; i++)
            {
                try
                {
                    string lvar = simdata_lvars[i].Trim();
                    FsLVar lvarObj = MSFSVariableServices.LVars[lvar];

                    if (lvarObj != null)
                    {
                        double newValue = lvarObj.Value;
                        Console.WriteLine($"{lvar} = {newValue}");

                        if (simdata_values[i] != newValue)
                        {
                            simdata_values[i] = newValue;
                        }
                    }
                    else
                    {
                    }
                }
                catch (Exception ex)
                {
                }
            }
            await Task.CompletedTask;
        }
    }
}

@Paul Henty this allows, to monitor a own set of lvars, and store it in a  array.  🙂

 

Posted
On 2/10/2025 at 1:40 AM, michielsweb said:

odd question is it possible to lvar read out msfs atc ?  🙂

There are the following ATC simvars (see https://docs.flightsimulator.com/flighting/html/Programming_Tools/SimVars/Aircraft_SimVars/Aircraft_RadioNavigation_Variables.htm😞

image.thumb.png.710bcbb57b14482c5a329626e93499e7.png

Any simvar can be added to spare/free FSUIPC offsets using the facility described in the section Adding Simulator variables (simvars) to FSUIPC offsets on page 35 of the Advanced User guide. As you can see, most of those are read-only, although 4 are updateable. 

John

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use. Guidelines Privacy Policy We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.