Demo: LVAR write access for any aircraft control

Hi Maurice,
sorry for the delay in this. been busy, as I’m sure we all are…
I now have a WASM module that can list and update lvars, as well as activating hvars, with the results being sent to the client via Client Data areas to my test client. The last piece of the jigsaw puzzle I’m interested in now is how to know what lvars and hvars are actually available? I’m currently using pre-defined config files for the lvar/hvar names. Is there a way to determine what lvars and hvars are available for the current loaded a/c via code in a WASM module?
Thought I’d post here, but maybe this needs separate topic…

John

Hi John-

I haven’t worked out a way to list available h-events, but you can get the available Lvars by using:

PCSTRINGZ get_name_of_named_variable( ID  id );

The function returns the name of the lvar for a given ID, or NULL if the lvar ID doesn’t exist.

To see all of the lvars for a loaded aircraft, I start at zero and increment the id until get_name_of_named_variable() returns NULL.

The following will print each lvar to the console for the currently loaded aircraft :

  	bool isValidLVAR = true;
  	int x = 0;

  	do
  	{
  		PCSTRINGZ lvarname = get_name_of_named_variable(x);
  		if (lvarname)
  		{
  			fprintf(stderr, "LVAR ID: %d     LVAR Name: %s\n", x, lvarname);
  		}
  		else
  		{
  			fprintf(stderr, "LVAR ID: %d     no Lvar", x);
  			isValidLVAR = false;
  		}
  		x++;
  	} while (isValidLVAR);

Hope this helps.

Matt

1 Like

Just searching through the code for the aircraft is probably the most thorough way to do so. I know the ModelBehaviors dev menu lists L:vars, but not H:vars. Do you have your code uploaded to GitHub?

@The727Pilot Thanks. Yes, thats a useful method to generate a list of available lvars.
@Iceman2152798 No code in GitHub, sorry. I use AzireDevops and its not public (as commercial).

Gotcha. So then would it be possible for the code to be uploaded to GitHub separately? I’m sure everyone reading this thread would greatly benefit from it - I know for a fact that us at FlyByWire (and the Working Title folks as well) are looking into the best way to get/set Lvars from SimConnect, and if someone already has a robust solution, I see no reason to reinvent the wheel here.

Ok. I’m still working on it. I’ll consider putting the WASM module into GitHub when done. But this is still several weeks away - unfortunately I’m not getting enoght time as I’d like to work on this at the moment…
Note also that there are various different approaches you can take. In my implementation, the client holds a table of all lvars and values, and so reads of lvars are just client side. Values in the table are updated (from the Client Data Areas) at a configurable rate on request from the client (simconnect) and update of lvars on a gauge event.
Change of aircraft and Client Data Area (CDA) size limit (8k) is also a bit of a pain. Changing aircraft means dropping existing lvars/CDAs and re-creating. And the 8k limit on CDA size mean that there is a limit to the number of lvars that each CDA can hold (currently 128 in my implementation, limited by the size of the lvar name, for which I’m currently allowing 56 Bytes), so I’m allowing multiple CDAs per a/c. Not sure if this is necessary though…if 128 is enough (or if I can reduce the 56 byres allowed for the lvar name), then I could simplify the implementation quite a bit.

Just an update concerning my efforts to get the code of @VFRMau working:

Running out of ideas what might be wrong, I decided to create my own WASM module. Doing sowas much easier than I thought and I got it running in 15 minutes. Then, I copied/pasted VFRMau’s code into my own WASM and debugged it.

Surprisingly, the WASM seems to work, even setting a breakpoint at the start of EventHandler() worked. But I never got a breakpoint to be hit in the cases of the switch statement, so I think for some reason transmitting the event does not work.

One general question: Although setting brewakpoints seems to work, I couldn’t watch any variable value. E.g. when breaking at the start of EventHandler(), I tried to look at the value of the function’s parameters. This did not work, neither with “watch” nor with showing “locals”. Is this a limitation when debugging WASM or is this a hint that there is something wrong with the project properties (e.g. calling convention)?

Thanks a lot,
Jens

Guys, I think we should really need to talk about this situation:

Everybody here seems to be in the process of reinventing his own version of the wheel: getting some access to LVariables via Simconnect communication with WASM, because Simconnect doesn’t allow to do that directly.

The result of this, is that in a very short time, we’ll have multiple modules running all at the same time, doing the same thing, increasing traffic over the named pipes used by the several Simconnect clients to talk to each other, to the detriment of everybody’s performances.

Yes, of course, we already have our own WASM module that does the same thing, and it’s hard enough being careful to optimize it as best as we can to reduce unnecessarily traffic without being worried by dozen of other identical modules doing the same service.

So, I think we REALLY need some kind of coordination here, unless you think it’s possible to lobby Asobo to add direct LVar/Hvar acces to Simconnect proper.

Is anybody willing to start a joined project on Github, which can be contributed by all interested developers, that can be distributed as a SINGLE, separate package, with every product that requires it ?

Note that, we already have our own WASM module fully working right now, with only the things we need, but of course the whole concept of using Simconnect itself as a communication channel between WASM and external EXE can be easily expanded to provide further services. There are some things that need to be handled with care, one for example is the synchronization between requests, which you might not notice if you “just” want to read or write an LVar, but will become obvious if you try to do things very fast from the client side. Yes, we handled this too in our module.

Also, to really make it work, we should try to stick with it and use it, and enhance it, instead of “just” taking the source code and make a fork of it to create a separate version, because that would defeat the purpose of having a single module installed in the sim at any time.

And, we would require some clarification and possibly some support from Asobo about how Dependencies will eventually work, in case multiple products using the module would work on the MS Marketplace, and possibly the Xbox version too. Who’s going to send the the MS Marketplace team the latest version of the module ? How fast can be kept updated ?

So yes, I understand there are tricky issues to be solved first and, if you think about it, the situation in FSX/P3D wasn’t that different, since even there you couldn’t access LVar directly without using a .DLL but, maybe, we have a chance to makes things better now.

Because, the LAST thing we want, is that in a year, there will be dozen of apps on the MS Marketplace, each one installing its own version of a WASM “bridge” ( that’s how we call our version ), clobbering the sim and the Simconnect communication channel for everybody, and this assuming all modules are done equally well and won’t crash the sim or conflict with each other.

8 Likes

Well said Umberto, documentation is key I think as well as the implementation of LVar and HVar in Simconnect that link with WASM Module.

1 Like

I believe the best way forward here is to put pressure on MS/ASOBO to implement a generic WASm bridge to allow direct SimConnect read/write to standard SimConnect Event and Variables as well as
(>H: Events and LVars. Without MS/ASOBO involvement here, it is going to be a mess.

I have now 4 “WASM bridges” active for SimConnect Client App, but would very much like to have just one.

This should work - its a problem in your code, or in the client transmitting the event. When transmitting, use the ‘#’ notation, and receiving just the numerical value.
What doesn’t work at the moment is setting a breakpoint in the module_init() function, as you cannot connect the debugger to MSFS until in the main menu, otherwise you just get too many exceptions. This proved a bit of a pain for me, and I had to temporarily re-organise my code to track down a memory issue in the module_init function.

There are currently issues with the watch window. Debugger limitations are listed in the SDK documentation:

  • The Watch windows do not display the value of the watched variables. Please refer to the Locals and Autos windows for now.
  • The Locals and Autos windows might have problems displaying the value of complex classes/structures.
  • Stepping into a function may display the Disassembly window instead of the original C/C++ source code.

John

1 Like

Hi John @ImpoliteGem5317,

thanks for your post

When look at this post you will find out that VFRMau cross-checked the values for the function calls I make.

My program is stripped down to just initialize SimConnect and then call MapClientToSimEvent and TransmitClientEvent.

With this piece of software I control the A320 FCU so far and it works fine.

The only difference I still have compared to VFRMau whose code is working is that he uses C++ while I am using C#.

Kind regards,
Jens

Ok, understood. I’m using C++ as well and no issues. Not too familiar with C# but should be similar and the code looks ok. Did you check/debug to see if anything is being received in your WASM module thats handling the event? If its the same module handling the event from the C++ code thats working and the C# code that isn’t, then if you code is ok then sounds like an issue with the libraries you are using… Aren’t there any C# WASM samples any where to check?

Yes,I checked as written above:

So, the WASM module worked but never received the events my C# code transmitted.

That’s my (only) idea, too. I just removed references to the SimConnect libraries and re-installed them, but unfortunately even this act of pure desperation was unsuccessful.

But even the “must be a library problem”-idea is a mystery to me:
The thing that really drives me crazy is the fact that I can send lots of events to SimConnect without any problem. My understanding is that there is no difference between sending any pre-defined event as e.g. “SPEED_SLOT_INDEX_SET” or “AP_SPD_VAR_SET” on the one hand and the “#0x11001”-event on the other hand.
In both cases, these events are mapped to a number the client uses from then on.
In both cases, the mapped number is sent to SimConnect.
So, why on earth should the former work and the latter fail?

They are handled differently on the receiving end, as the pre-defined events are handled by a DispatchProc callback, and the number-mapped ones in an EventHandler, so even though the client interface is the same, they are handled differently by SimConnect.

I’m not sure where you issue lies though I’m afraid.

Thanks for the clarification of event processing. I am not sure how to proceed, but if I will ever find out what’s going wrong here, I am sure it will be due ro the information I get here.

That makes two of us. At least, I am not alone.

Thanks a lot for all your input!

I have put my minimal code out there weeks ago.

https://bitbucket.org/mobiflight/mobiflightwasm/src/master/

Please feel free to contribute.

Well, I finally made it work.

The errors in this post are

  • object-ID: it must be 0, not 1
  • the flag in transmit client event should not be DEFAULT but GROUP_ID_IS_PRORITY

With that changes, everything works as expecterd. Fortunately, the error had nothing to do with SimConnect interface components or differences between programming languages amd/or project setup.

Regards,
Jens

This is a good idea and I fully support it, but the main thing to keep in mind here would be that many aircraft, both freeware and payware, will have their own set of custom LVar’s and H events which are subject to change every time an aircraft is updated. If a single, global Lvar/H event bridge module were to be made, there should be a specification (e.g. a standardized CFG format in every third party plane’s folder) which dictates what LVar’s and H events it wants exposed.

I took a look at the code from @MobiFlight for H events (great stuff), but the main limitation of their current approach is that events are stored in a static flat file in their package, which will often be out of date (at least for us folks at FBW) since our development moves quickly. I think a standardized CFG file that each addon includes in their base-level package directory could solve that.

I’ve made good progress on a WASM gauge for H events and Lvars, originally meant for just the A32NX, but it still needs some work, and if anyone’s willing to join in, we can make this a standalone module. We can even solve the distribution problem by pitching it to Asobo for inclusion in the sim by default. (Or if that’s not viable, we could ship this open-source module package side-by-side with the A32NX package, since I’m sure almost everyone out there has our aircraft).

For anyone interested: feel free to reach out to me via Discord if interested (my handle is Iceman#5540 for DM’s, or ping me on the #sdk channel in the FlyByWire discord).

2 Likes

Yes, I had a look at it, and in fact is not very flexible, especially considering other modules won’t be able to access that text file, since it will be outside their own package.

We already have our module for LVars fully working, and the way we did it, was with a communication protocol using the “Client Data” functions creating two shared memory areas, one for IN and another for OUT, and a set of named custom events, named like “WASM.RegisterVariable”, or “WASM.GetVariable”, “WASM.SetVariable” and other events for the matching responses, the WASM bridge will wait for them, pass through the relevant function, fill up the Client data area with data and reply.

The client will wait using the same two Client data ( just the OUT for the client is the IN of the server and vice-versa ) so, when it gets a response from the server to a previous query, it will read the Client data with the content that has been filled by the server.

I think the goal for the wasm “bridge” is to just execute commands on behalf of the clients AS IF they had access to a native Simconnect function allowing to call register variables, set/get variables, execute calculator code, etc. The Wasm module shouldn’t have any knowledge of default or custom events or any specific logic of the sim or the airplane, that’s should be entirely done by the various clients.

4 Likes