Demo: LVAR write access for any aircraft control

I forgot to hit Reply to Post. See my message above.

This is a very interesting post. But I’m still missing some pieces of the puzzle. I’m trying to understand the relationship between FS2020, SimConnect, WASM, Gauge API, 
 I have googled like crazy, and have read many posts in this forum. But I miss the big picture. I’m still not getting it completely. How are things related to each other?

I’m also confused with some terminology. What does “gauge API” really mean. A “gauge” is an instrument in a plane, right? Or is there a different context when used for FS2020? If I want to control the FCU of the FBW A32NX, do I need that gauge API?

If I want to talk to the FBW A32NX in FS2020, do I create an executable that connects with SimConnect, can put in requests, and gets answers via some kind of callback function? And if I need this WASM module, do I talk to it through SimConnect, or does my executable needs to have some additional initialization and callback routines for this?

Bottom-line is that I would like to connect my proprietary hardware (based on PIC microconroller and via USB) with the FBW A32NX in FS2020. I have an own piece of software written in C# that is capable of detecting my HW modules (multiple), and is able to send commands (LED’s, 7-segment displays) and receive data (keypresses, rotaries, 
). Let’s call it the “right side” of my software. Now I want to develop the “left side” that communicates with FS2020. Next to C#, I also have knowledge of C and C++.

I simply haven’t found a total explanation, tutorial, example or demo that shows me the big picture. I would love to see a schematic (don’t people make these anymore? :slight_smile: ).

I want to contribute as well. Once I have everything up and running, I might start a post to give a full explanation, to bring other newbees like me on the right track.
I hope somebody has the magic key to unlock the knowledge I need!

1 Like

Ok, I’ll go in chronological (historical) order:

The Gauges API

This is the oldest API, which came with FS2002, it’s a set of C/C++ functions calls, which were initially the only documented API in the sim, was used mainly ( but not only ) airplane developers writing C/C++ gauges, and contains many functions to read simVars ( A: variables ) and “XML” vars ( L: variable ), it also contained the “universal” execute_calculator_code, which evaluated an XML expression written using the XML Gauges syntax, which could also be used to read/write variables and/or send events to the sim, like keypresses. This could also be used by developers writing stand-alone .DLL modules that ran in-process to the sim.

The SimConnect API
This is a later API that came with FSX, it’s client-server based so it can be used for both in-process .DLL modules or gauges, but also for external .EXE, not necessarily running on the same PC, because it can also networked. It’s also supported in P3D, and it’s far more powerful there. It supports .NET and managed code, while the Gauges API it’s C/C++ only.

Since it has been around for a very long time, it’s well documented and still developed (not just by Microsoft, since P3D use it too), it’s by far the most used API. However, it lacks access to things only possible ( L: vars and XML expressions ) with the Gauges API.

WASM
This is the new way to create C/C++ code for MSFS. While Simconnect is still supported, it’s only for external .EXE. C/C++ Gauges and Stand-Alone modules (modules that starts with the sim and ends when the sim exits), that is everything that run “in-process”, MUST use WASM. However, WASM Gauges/Modules CAN make Simconnect calls as well. The main difference compared to the old FS8/9/FSX Gauges/Modules, is they are heavily sandboxed, meaning they don’t really have access to the simulator address space and can’t even read any files outside their own package. They can write only on their dedicated area. The main advantage of WASM, is that you can still use C/C++, it’s almost as fast as the true native code, and it’s cross-compatible with Xbox. Also, with WASM ( this is the important bit ), you ALSO have access to the “old” Gauges API, the one I listed first.

By putting together all of this, someone needing to access variables and events not accessible directly through Simconnect, has to do the following:

  • Write a Stand-Alone WASM module ( but also a WASM Gauge would work ) that would use the Gauges API to read variables or receive/send events which wouldn’t otherwise possible to get through Simconnect.

  • Use the Simconnect API in the WASM module to define custom data areas which can be used to “send outside” these results, to a external Simconnect client that would connect to the WASM module. This is bi-directional too, the external client might ask the WASM module to perform commands/events on its behalf, not just read data from it.

Now, why all these complications ? Wouldn’t be easier/better doing everything through WASM ?

No, you can’t, because WASM is heavily sandboxed: in addition to not being able to read any files outside its own package, it doesn’t even have ANY access to ANY of the Windows APIs ( no Win32, no .NET, nothing, just basic Posix and only in your own folders ) so, even if WASM has a somewhat privileged access to the sim compared to just using Simconnect, it can’t do much with it so, you’ll realize soon enough you need a “real” Windows .EXE for almost everything, especially if you need to interface with some hardware.

That’s why the need for bi-directional communication between WASM and another .EXE, using Simconnect “as a transport”.

It’s really outside the scope of this post explaining in detail how the Simconnect client data areas and custom events work but, if your goal is JUST interfacing with some hardware, it’s likely easier if you use the Mobiflight module, which has all the basics done and has some specific functions for the A320-NX

6 Likes

@Umberto67 Thanks for this answer, because it clarifies a lot. I have now read almost this complete post, and copied a lot of interesting links from GitHub, BitBucket, 


I was first confused - I thought that you meant to use MobiFlight (which I can’t, because at the end, I will not use Arduino), but you mean the MobiFlight WASM module, right? I even found the one that FSUIPC is making. So a lot material to dig into and choose from!

I also agree with your remark that Asobo should provide a default WASM module. But didn’t I read somewhere that they are working on some kind of standardization? I don’t find the article back unfortunately.

1 Like

This post is really a great source of information. I have already tried several of the solutions, and it’s a great learning experience. I think that step by step I’m starting to understand better. Thanks a lot!!!

@davux3 I wanted to look at your fs-gauge-bridge, but what I don’t understand is that you seem to put the wasm module in the “Panel” folder, and not in the “Community” folder? Is there a reason? Can I also put it in the Community folder like the other WASM modules mentioned in this post (example MobiFlight, FSUIPC)

@ImpoliteGem5317 I have successfully used your WASM module and client to experiment with the native A320_Neo. So far the only one that worked! Because of that, it will be a good starting point to look into your code and better understand the internals. I downloaded both the WASM and the client source code, and will have a look at it.
One question I have is why I couldn’t use the H-var “H:A320_Neo_MFD_BTN_CSTR_1”. If I use that, nothing happens. Although, if I push the CSTR button with my mouse, the green light goes on, but not if I use the “Set HVAR” menu in your client. I could successfully set other HVars such as all the buttons of the CDU, so “Set HVAR” is definitely working.

@Umberto67 You gave a good explanation of all the variables. But what I miss is the type “B”. On the native A320_Neo I find for example “B:ELECTRICAL_Battery_1_Toggle” (the BAT1 button on the OVHD). But what is a B-type, and how can we access it? If I want to toggle the BAT1 switch, how do I do that?

Am I correct to conclude that the WASM module is only used for L-Vars and H-Vars? The other types have to be managed directly with SimConnect? With other words, WASM has to be seen as an “add-on” on SimConnect, to allow controlling L-Vars and H-Vars? If I use the FSUIPC client application, it has also an “Execute_Calculator_Code”, which I could successfully use with L and H vars, but can I use that for other types as well? I tried with the B-type in it, but my Battery switch is not toggling.

According to the MobiFlight preset list (see https://hubhop.mobiflight.com/) , that hvar is only available in the stable A320. Which version are you using? For the dev version, there are presets A32NX_EFIS_L_CSTR_PUSH and A32NX_EFIS_R_CSTR_PUSH, which use the following calculator code:
(L:A32NX_EFIS_L_OPTION, enum) 1 == if{ 0 } els{ 1 } (>L:A32NX_EFIS_L_OPTION, enum)
(L:A32NX_EFIS_R_OPTION, enum) 1 == if{ 0 } els{ 1 } (>L:A32NX_EFIS_R_OPTION, enum)
i.e. toggle the appropriate lvar.

The WASM module and WAPI interface I provide supports lvars, hvars and calculator code strings (currently up to 255 characters). You should be able to set/activate any type of variable via calculator code, but the WAPI does not provide a mechanism for returning any values from calculator code executed.
If you are using the WAPI to access lvars/hvars, but would also like to read simulator variables (A:vars), then you can either use SimConnect directly in your application, or use the FSUIPC SDK which will provide read/write access to those simvars held in FSUIPC offsets. Alternatively, if using managed code, you could look into using Paul Henty’s dll client for .Net, which is a higher level c# interface wrapper around the FSUIPC SDK and WAPI.

Calculator code is just what it says. FSUIPC just executes the provided calc. code, so you can use any valid calc code you like, including B-types, A types, K types, etc. If the code is not doing what you think it should, I suspect that it is either invalid or not appropriate for the loaded aircraft.

John

1 Like

@ImpoliteGem5317 If I’m not mistaken, I was using the native FS2020 A320_Neo. I think I did something wrong (pretty sure of that :slight_smile: ).

I have also the FBW A32NX dev version. I used the Behavior window and pressed CTRL-G when the CSTR button was highlighted allowing me to find the below code that is indeed doing the same as you described (slightly different syntax - your version is shorter, but I understand that both are doing the same).

image

So I guess that the “BUTTON_CODE” is to toggle the button and the “INDICATOR_CODE” is to control the green indicator in the button? I’m still learning to interpret this RPN notation (still a nightmare because I’m not used to it :frowning: ). The SimConnect SDK documentation is very helpful.

From the above screenshot, I have a few questions:

  • What does “enum” exactly do? Why can’t I just use (L:A320NX_EFIS_L_OPTION)? Or is the syntax required to have a unit (like meter, feet, 
), and because this variable doesn’t have a unit, we have to use “enum”?
  • What is “1 sp0 10 (L:A320NX_EFIS_L_OPTION, enum) ==” exactly doing? I read the documentation about sp0, but don’t understand. Am I right that this code is enabling/disabling the green indicator light, or is this just a fantasy? :slight_smile:

I am no expert in calculator code or gauge programming (first time I have heard of ‘sp0’!), I just provide the mechanisms for these to be used. You should maybe ask over on the FBW discord channels.

1 Like

Hi,
You should take a glance on this SDK Chapter: Reverse Polish Notation.

In Reverse Polish Notation (RPN), sp0, sp1, etc are registers where informations can be stored.
In your case, the value 1 is stored in the first register sp0 and the variable L:A320NX_EFIS_L_OPTION is interpreted like a enum (-1, 0, 1, etc) then compared to the value 10 in order to be identical. If yes, the calculation continue.

@LagaffeVFR5476 Thanks for your feedback, but in the meantime, I found my “glitch”. In the formula, the “10” should be “l0” (character “L”). And now it makes more sense. sp0 stores value 1 and pops it from the stack, and l0 loads the value from register 0 to the top of the stack. With other words, 1 sp0 l0 does the same as just 1. These kind of weird constructions are the result of the RNP compiler that is used by FBW (at least, that is what I understood from some explanation I got on Discord). Now it makes sense, because I don’t compare the EFIS value with 10, but with 1. And this is the CSTR button.

Thank you for sharing this code, it is clear. It certainly works fine in WASM by registering a key event handler, but I went for JavaScript instead. I tried to make this work with a JavaScript listener that I use to intercept key events, but it didn’t work. My code is like this:

this.keyListener = RegisterViewListener('JS_LISTENER_KEYEVENT', () => {
            Coherent.call('INTERCEPT_KEY_EVENT', 'AP_MASTER', 0);
            Coherent.call('INTERCEPT_KEY_EVENT', '0x11000', 0);
            Coherent.call('INTERCEPT_KEY_EVENT', '#0x11000', 0);
            this.keyListener.on('keyIntercepted', this.handleKeyIntercepted);
        });

If you are not familar to JavaScript, this defines a function (hadleKeyIntercepted) that receives all the key events, exactly like the EventHandler you defined in your code. The only difference is that instead of receiving ALL the event, it only receives the ones listed with Coherent.call(‘INTERCEPT_KEY_EVENT’.

It works perfect with AP_MASTER because this is a standard event, but I was unable to get the custom event #0x11000 that is sent through another app.
Any idea?

Thanks.

This is an excellent reply and summary of all the various APIs, thank you very much!

Just to add some “background info”: WASM stands for “Web Assembly” and is essentially a “web standard” (coming from the “browser world”) which defines a compatible “byte format” which can be interpreted by various browser (and obviously also “non-browsers” like Flight Simulator 2020) such as Firefox and Chrome etc.

(As such, it is very much in analogy to “Java Byte Code” which can be interpreted and run by any Java Virtual Machine (JVM)).

WASM is not a “Microsoft invention” and for sure it is not Flight Simulator 2020 specific: it is really a “global standard” which allows to exchange “byte code” to be run on various platforms (again, mostly browsers, but also other applications like Flight Simulator 2020 and others).

There exist many “WASM generators” (compilers), specifically also for C/C++, so you can essentially write “web apps” in C/C++ and have them run in a browser (or as an addon in Flight Simulator 2020). But as already mentioned those WASM modules are in a tight (hopefully ;)) “sandbox” (which might be specific to the context which executes the WASM code), so they have only access to a very limited API (which most likely excludes most operating system APIs, for instance).

2 Likes

I also have similar JS_LISTENER_KEYEVENT code running, but have never tried to make it work with custom events.

I believe that Matt and Dominic at WT, were responsible for the introduction of JS_LISTENER_KEYEVENT into MSFS sometime in mid 2021.

Maybe try asking Matt directly on the WT Discord .
I have always found him most helpful, and willing to share technical information w.r.t. MSFS & JS

1 Like

Yes, I will ask Matt. I already did it in the past and indeed he was very helpful.
For the specific need I had, I found a workaround so there is less urgency but I would like to have the answer.

Thanks :wink:
Eric

Boy! What a great find; And explanation too!;Thanks sir! Sure would be nice if someone developed the Lula’s language the way that that fellow from Germany did for X-Plane. called “FlyWithLua” which includes all of the Lvars exposed by X-Plane, and implemented many of them into built-in functions and procedures. I wrote my first code in 40 years with my X-Plane, “ LilBlueDonuts” LilBlueDonuts - Utilities - X-Plane.Org Forum a 2D/VR multi-function AOA HUD and what a joy to learn “FlyWithLua” FlyWithLua NG (Next Generation) Edition for X-Plane 11 (Win, Lin, Mac) - Utilities - X-Plane.Org Forum written by (AKA? X-Frieze”)
I wish he would port it over to MSFS, though I understand that MS or Asobo or both are loath to expose their variables. ( seemingly backed up by Randazzo’s (Sp.?)complaint resulting in further delay of the PMDG 737. I’d love to see that port happen,since Lua is so close to C and C++. Only problem is I could not find an IDE WITH A debugger.
An IDE Like ZeroBrane Studio makes FlyWithLua a joy to use. It does have a debugger, but there were a sufficient number of changes to Lua 5.3, upon which FWL is based, it couldn’t debug my code. Granted my code could have been so bad, that it gave up
A MSFS port of FlyWithLua could open up a new world to those who want to learn a little code and contribute to the MSFS community
A little help please X-Frieze?!
Sending protective and healing vibes to y’all and your loved ones.
Chas

what is the suggested solution for this? I have a C# app nearly complete (using only SimConnect), except I need to add Lvars 
 I need a minimal WASM I think and communicate from C# main form

Asobo should provide a default WASM module

Hey guys,

I’m trying to create an improved version of the in-game checklist for Milviz 310R and trying to remove and install the control lock LVar is giving me problems.

This control lock can be removed with a left click but can only be reinstalled in the EFB tablet.
I think the aircraft is resetting this LVar so my copilot action in the checklist can’t stick.
I’ve managed to fix the removal of the control lock by directly copying the left-click event defined in the XML.

But the install control lock is having an issue. The copilot action can install the control lock but it’ll only flash one second in the sim and then the control lock is gone and the LVar is reversed back to 0.

Any idea why this is happening and how can I make the value stick?

Regards,
Meo