michielsweb Posted February 3 Report Posted February 3 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?
John Dowson Posted February 4 Report Posted February 4 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.
John Dowson Posted February 4 Report Posted February 4 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.
Paul Henty Posted February 4 Report Posted February 4 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
michielsweb Posted February 5 Author Report Posted February 5 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 🙂
michielsweb Posted February 7 Author Report Posted February 7 @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 🙂
Paul Henty Posted February 7 Report Posted February 7 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
michielsweb Posted February 7 Author Report Posted February 7 okay, found the issue, @Paul Henty program did not have time to start the service 🙂 wil clean up my code and fix the code to read it here 1
michielsweb Posted February 7 Author Report Posted February 7 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. 🙂
michielsweb Posted February 7 Author Report Posted February 7 feel free to add it too the paul henty examples. as it gives a nice structures to program own programs on 🙂
michielsweb Posted February 10 Author Report Posted February 10 odd question is it possible to lvar read out msfs atc ? 🙂
Paul Henty Posted February 10 Report Posted February 10 I don't think so. The LVars come from the loaded aircraft. Paul
John Dowson Posted February 11 Report Posted February 11 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😞 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
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now