Access LVARs without WASM module

Hey there,

is it possible to access LVARs without the use of a WASM module just via SimConnect?

I fiddled around a bit trying to understand SimConnect until I now reached the point where I wanted to watch LVARs (AS CRJ in this example).
What I’ve tried is



and in a callback function I’m trying to get the events with

        objData = (SIMCONNECT_RECV_SIMOBJECT_DATA *)data;


this is only a part of the code. This worked for “default” variables although I didn’t get any values. I assume as the CRJ heavily relies on LVARs.

So to get back to beginning: LVARs like in the CRJ are not open to SimConnect but only to WASM modules?

Thanks in advance,

There is no way to get local L vars through SimConnect alone.

The setup you show for SimVars is also incorrect, but that’s a different subject…

In the next day or so I’m releasing an open source WASM module and a full C++/C# client implementation to go with it. It will provide remote access to all the “Gauge API” features available via WASM integration. Will post in this forum.


I thought so… I’ll dig into WASM then I guess. Thanks for the input :slight_smile:

Could you elaborate what exactly is wrong? I’ve tried my way through the SDK and some topics in this forum.

I’ll keep an eye out for it :slight_smile: Hopefully I can take get a better understanding with it.


Sorry, not sure what I was thinking of or looking at, but that does look correct after all… :slight_smile: Going between C++/CLI/C# has me confused, apparently.

Just posted in this forum regarding the WASM module and client API project. Hope it helps!


Ah perfect :slight_smile: So at least I don’t have to worry that I got that wrong :smiley:

I sure will crawl through your project and take a look into it :slight_smile:


[copied from the devsupport forums where a similar question popped up]

I’d like to chip in here, especially concerning the suggestion that you need to write a WASM module to be able to exchange data that is not covered by the predefined SimVars.

Yes, L-Vars are the only Simulation Variables that are “uncontrolled” in the sense that you can add your own, but the reason they are also locked tight into the simulator stems from their origin: they were meant to be used in panels and gauges, persisting beyond the single gauge they are created in so they can be read or controlled in another gauge. (or part of the panel) Also, because they persist, they still hold their value the next time the panel (or gauge) needs to be generated, which allows for quite complex components. The first version of Aerosoft’s Airbus Extended (as it was called then) had the MCDU implemented with a large amount of (XML-based) stack-machine code. At the same time brilliant and frighteningly complex.

Given this persistence, it was quickly the go-to method for exchanging custom data between add-ons, provided both lived inside the simulator. So next everyone started making DLLs that implemented some other way of exposing those L-vars to the outside world, which works but is definitely not what they were intended for. I think FSUIPC is a perfect example of this, as it provides a LUA platform where you can access everything in a much more consistent way, including those L-vars, at the cost of now having to integrate with a new environment, increasing your dependencies with one more (versioned) module. I love FSUIPC, but not the reason why it was needed.

The other way, which is what was actually intended to be the “official” SimConnect-compatible way of exchanging data, is to use Client Data. SimConnect allows you to define a block of data, give it a name, and then distribute that data to any subscribers. This data will be sent to any SimConnect client app that knows the name of that block and asks for it. No need for WASM or L-var trickery. The only “disadvantage” is that the Client Data blocks are just unstructured blocks of bytes, which you can easily solve in C, C++, or C# by mapping a struct on top of it with any fields you want.

With Aerosoft being a big fan of L-vars, PMDG is using Client Data. So, if you want to interface with Aerosoft aircraft, you need to solve the L-var conundrum. If you target PMDG aircraft instead, you need to tell their aircraft’s runtime they should send the data to the simulator using an option in an INI file and include the header file they provide to get the struct definition.

Ah yes, there is actually a third way: you can define custom events and send numeric data with them, but this is much riskier because there is no registry for them. So, if you write an add-on that wants to use events to send data around, you need to choose an event number and hope no other add-on is alive that uses that same number.


Hi Bert,

That’s a nice rundown, thank you. Do you have the original post’s URL? Just curious if there was discussion around it there.

The upshot of course is that yes one still needs some kind of “insider” access to read L vars, which at the moment seems most “practical” via WASM module. Mind you I"m not saying this is an ideal solution by any means.

But lots of good stuff right now is controlled or read via L vars (partially because lots of the SimConnect events and SimVars are broken). And users want that data/control (I maintain a plugin for a popular touch-based controller and the L vars were on top of the requested feature list even though they can already request any SimVar and fire any Key Event which SimConnect supports).

The custom “ClientData” struct option is good and maybe “proper” but from an “access tool” author perspective it presents some challenges. Namely that one needs to know, in the code, how to decode the data struct(s) (the tool users can barely handle what’s already available… so setting up custom data structs it out of the question :slight_smile: ).

In contrast, when dealing with individual value types (PODs or known simple structs like XYZ), these are much simpler to define/access “on the fly” using generic code. A somewhat-savvy tool user can set these up pretty easily as needed, which is IMHO essential because there’s no way any tool is going to know about every possible data value on every possible aircraft.

Of course the “ClientData” approach could also use individual fields instead of structs, just like, essentially, SimConnect allows now to individual SimVars (except the few structs of course, but those are essentially just another known type).

Personally this seems like the most flexible solution to me.In fact if aircraft devs could simply “add SimVar” the whole issue would be solved AFAICT. Am I wrong? Not only would they be instantly accessible externally, but it would also delineate that “Local” vars are private and SimVars are public (which I do agree is the point of local vars, as you point out).

Why SimVars have to come from some rigid pre-defined list here in the 21st century escapes me.

I’m not even clear on if using fewer, larger “blocks” of “ClientData” with SimConnect, is actually more efficient than using more smaller ones… my experiments so far show no difference and with my WASimCommander I chose to implement each variable request being returned to the client as separate SimConnect “ClientData” bins (sized appropriately for each data type expected). This makes them much easier to manage too.

Anyway, not sure you wanted to get into a discussion of it or not, but those are my thoughts… with apologies to @Phil7789 for the “hijack!” :slight_smile:


PS. Oh and the custom event “you must choose an ID in this small range and hope no one else happened to have chosen it,” w/out any way to verify, is pretty ridiculous. Anyway it doesn’t do anything for data access at all, just triggering things.

Hey Max,
the link is How to create own SimVar for use by SimConnect (to change its value from outside MSFS) - MSFS DevSupport. In the “Off-topic” space I actually posted a proposal to look at the modernization of the SimConnect API, but I doubt it will get far.