Jump to content
The simFlight Network Forums

Added Support for LVars/HVars Access in MSFS via John Dowson's WASM Module.


Recommended Posts

Thanks, that's great explanation.

When you probably were responding to my comments, I changed them on you by making a subtle discovery about the hdg toggle in the CRJ. I am going to just repeat it here for correctness:

In order for the hdg toggle to work consecutively, the lvar must always be reset to 0 before setting it back to 1 again. Therefore, I have to explicitly set the offset to 0 (ie. clear it) for the whole thing to work, and I need to put a time delay "Thread.Sleep(10)" between each Process() as indicated in my updated code above. Can you comment on the required time delay? Is this MSFS thing or the CRJ thing or offset thing, or?

Link to comment
Share on other sites

Ah so the CRJ isn't resetting the LVar itself. That's a pain, so yes you'll need to do this yourself.

The delay requirement is likely to be down to a timer somewhere. Maybe the CRJ code checking the LVAR value, maybe FSUIPC checking the offset value. If you change it to 0 and then back to 1 too quickly (between another component's timer tick) then it won't notice the change. That would be my guess.

There is also a whole chain of communication from my DLL to FSUIPC to the WASM module to SimConnect to the CRJ code so there are a number of places it could get missed if you change values too quickly.

Paul 

Link to comment
Share on other sites

Quote

Ah so the CRJ isn't resetting the LVar itself. That's a pain, so yes you'll need to do this yourself.

Yeap, ... I did confirm that the hdg mode Lvar in the CRJ (when you push the hdg button on the MCP) only goes high (value=1) when the button is pressed and immediately is reset back to 0. I have to do this all manually with the offset so that the CRJ notices the trigger.

Thanks for the rest of explanation and support. After playing with this long enough and your support and John's I have a starting point to make my MCP work with the CRJ lvars.

  • Like 1
Link to comment
Share on other sites

Paul,

I am going to reach to you one more time with the following problem. John sent me over here because I am using your api.

I am trying to read now this Lvar: ASCRJ_VAR_AP_SELHDG (verified, exists, it is read only)

Here's the setup:

[LvarOffsets]
1=L:ASCRJ_VAR_AP_SELHDG=SD0xA000

Here's the code:

var offset = new Offset<int>(0xA000);
  FSUIPCConnection.Process();
  var result2 = offset.Value;

It always returns 0 although the heading is other than zero. Your code on the other hand works:

var result = FSUIPCConnection.ReadLVar("ASCRJ_VAR_AP_SELHDG");

Same console app, I open/close connection as usual.

I am lost why some lvars work, others don't. 

Link to comment
Share on other sites

Everything looks okay to me. 

I suggest using FSUIPC to log the A000 offset. This will take my DLL and your C# application out of the equation.

In FSUIPC7 select Log->Offsets and log A000 as S32 (signed 32bit) a the MSFS Title bar:

image.png.c2e38f4bf0be8c258e1aa58cefa6c7c8.png

With your Lvar to offset set up in the ini file. you should see the value of A000 appear on the title bar. If it's 0 there then the problem is with your FSUIPC setup. You can go back to John with this logging result and without any C# code.

If you can see a good value there then it's something in the C# side of things and we can continue here.

Sorry this is frustrating for you, getting passed back and forth from me to John, but hopefully this strategy will make it clear where any problems are and you can go to the right person. Once you can see valid values in the offset with the FSUIPC7 logging then you can bring the C# part back into play.

Paul

 

Link to comment
Share on other sites

Quote

 If it's 0 there then the problem is with your FSUIPC setup. 

Sorry, I had to fix the offset (Initially typed it wrong in the log and had to edit my comments here) ... now it is 0. Back to John? 

Curious, why the other offsets I worked with work and this one doesn't? This is really confusing now.

These work:

[LvarOffsets]
1=L:ASCRJ_FCP_HDG=SD0xA000
2=L:ASCRJ_FCP_HDG_LED=SD0xA004
3=L:ASCRJ_FCP_HDG_CHANGE=SD0xA008

I tried another that displays similar info "ASCRJ_VAR_AP_SELIAS", same issue. In summary, the flag offsets and toggle offsets work, the ones that display specific values don't.

2) As a side note:

I tried today the new MSFSVariableServices class. I composed the following app (see code below), it initializes fine but then no events are ever triggered (beside the log event) neither any Lvars are discovered. Did this ever work for anyone??

Log messages suggest start up worked but nothing happens after.

Lvars log:   [INFO]: **** Starting FSUIPC7 WASM Interface (WAPI) version 0.5.1
Lvars log:   [INFO]: Connected to MSFS
LogLvars() produces: Lvars log:   [INFO]: We have 000 lvars:

But ... if I do this from FSUIPC, it logs all the CRJ lvars to log file just fine.

UPDATE: Changed call from _LvarsSvc.Init() to _LvarsSvc.Init(this.Handle), Works now but we have some Band news, read-on: 

1) How did I get it to work: Remember that window handle param for the Init() method? Well, if you don't pass window handle to the Init() or just pass 0 nothing happens (as described above). Looks like the window handle is required. Once it is passed, I can see the Lvars and can iterate over these (sometimes) but what's the bad news? See next point.

2) The values changed event fires and causes intermittent crashes (but mostly it crashes):

Here's the console trace when it crashes:

The program '[18140] MSFSLvarsWinformsApp.exe' has exited with code -1073741819 (0xc0000005) 'Access violation'.

By debugging it, it appears its happening here: Lvars_OnValuesChanged event

The crash happens on 3rd iteration (sometimes later) and it appears that the memory violation happens every time on the same memory address.

protected override void OnLoad(EventArgs e)
		{
			base.OnLoad(e);
			_Setup();
		}

		protected override void OnClosing(CancelEventArgs e)
		{
			base.OnClosing(e);
			_Teardown();
		}

		private static void Lvars_VariablesReadyChanged(object sender, EventArgs e)
		{
			// Show the variable status in a checkbox
			var ready = _LvarsSvc.VariablesReady;
		}

		private static void Lvars_OnValuesChanged(object sender, EventArgs e)
		{
			Console.WriteLine($"Values changed....");

			foreach (FsLVar lvar in _LvarsSvc.LVars)
			{
				Console.WriteLine($"Lvar {lvar.Name} (ID {lvar.ID}) = {lvar.ValueChanged}");
			}
		}

		private static void Lvars_OnLogEntryReceived(object sender, LogEventArgs e)
		{
			Console.WriteLine($"Lvars log: {e.LogEntry}");
		}

		private void _Setup()
		{
			// Lvar service events
			_LvarsSvc.LogLevel = LOGLEVEL.ENABLE_LOG;
			_LvarsSvc.OnLogEntryReceived += Lvars_OnLogEntryReceived;
			_LvarsSvc.OnVariablesReadyChanged += Lvars_VariablesReadyChanged;
			_LvarsSvc.OnValuesChanged += Lvars_OnValuesChanged;
			_LvarsSvc.Init(this.Handle); // <= Required, without no events are fired, nothing happens
			_LvarsSvc.LVARUpdateFrequency = 6; // Get new lvar values 10 times per second (Hz)

			_LvarsSvc.Start();
		}

		private void _Teardown()
		{
			_LvarsSvc.Stop();
		}

 

Link to comment
Share on other sites

Quote

Changed call from _LvarsSvc.Init() to _LvarsSvc.Init(this.Handle), 

Okay - well I guess John was wrong that you can just pass 0 or any other value. I'll remove this from the next version.

Quote

The program '[18140] MSFSLvarsWinformsApp.exe' has exited with code -1073741819 (0xc0000005) 'Access violation'.

I'll look into this over the weekend.

Paul

Link to comment
Share on other sites

Quote

Okay - well I guess John was wrong that you can just pass 0 or any other value. I'll remove this from the next version.

I believe the handle is used to pump messages (ie notifications) that contain Lvar information to user's app. I haven't read the sim SDK but that's just my past experiencing working with WIN32 api and one of the uses of the window handle.

Thanks for looking into this.

Link to comment
Share on other sites

I got MSFS for a month so I can test this properly here. Sadly I can't reproduce the access violation at all.  I've tried with my test code and your exact code from three posts up and it runs flawlessly. I did a few 30-minute flights with no problems. I've tried a few different aircraft but I can't see any CRJ so I guess that's in a better version of MSFS or it's third-party. So it could be something with so with the CRJ.

Do you also get access violations with the built-in aircraft?

Paul

Link to comment
Share on other sites

Okay, ... I think I got it to crash on a stock aircraft. Select the "Cessna CJ4" (the one that comes with the sim, not the FBW one.

Use my code that I have provided in previous post (On changed event should iterate over all Lvars not  (LVarsChanged) collection, just like posted in my sample. Then, .. in the CJ4 cockpit, under lights there's a "Panel Lighting Brightness" knob (center knob, under dimming labelled "Panel"), start turning it left and right (from min to max), keep doing it until you get a crash. If it is not crashing, stop the app (not the sim), and start it again and repeat the process. Sometimes the crash is not induced.

If that doesn't work, try an aircraft with lots of lvars, maybe a320 by FBW. Then try changing switches back and forth, those that are mapped to lvars and in rapid succession.

Since this is a memory thing, it might hard to reproduce, but if you can get the CRJ, it should happens for sure since that's what happens to me.

UPDATE: My observation is that the crash is induced as the Lvars are changed constantly and therefore changing any controls that read/write LVars will cause/may cause a crash.

Link to comment
Share on other sites

I've followed your instructions for the stock CJ4 - changing the panel brightness quickly from 0 to 100. No crashes. Tried 5 restarts of your test app.

I also tried the stock a320 using the upper and lower display brightness and also no crashes.

Paul 

Link to comment
Share on other sites

Update/ FYI

I will not be using the "MSFSVariableServices" class for now since it crashes with the CRJ but to update you, John has fixed the FSUIPC code and it works fine with the mapped offsets (to lvars) using ini file. 

I noticed that reading the mapped offsets (that are mapped to lvars) is quite slower compared to reading standard offsets. This is not much of an issue with the buttons/LEDs (not as noticeable) but you notice the slowness when I am refreshing the hdg/speed/alt displays on my Goflight hardware, it is so sluggish. Also, turning the encoders is kind of sluggish when sending data back to the CRJ (ie updating the lvars). I wonder if this is because of WASM.

Link to comment
Share on other sites

Hey Paul!  The updated dll seems to work great, with one exception; specifically, I continue to get crashes (faulty FSUIPC_WAPID.dll  module).  Interesting enough, the crash only occurs when using the Aerosoft CRJ; plus, the crash happens without initiated an FSUIPC connection; it happens seconds after vs.Start() is called. 

Link to comment
Share on other sites

Hi,

Quote

Interesting enough, the crash only occurs when using the Aerosoft CRJ

Yes, another use above has the same issue with a CRJ aircraft. I assume it's Aerosoft.

I think it's something to do with the high number of variable this aircraft has. It was too many for the limits baked into WASM module.

I can see in the GitHub project that John has expanded the capacity in version 0.5.3. I'm hoping that will fix the issue.

The fsuipc.com page still has 0.5.2 so we'll need to wait until John releases the new version to try it.

Paul

 

Link to comment
Share on other sites

29 minutes ago, Paul Henty said:

Hi,

Yes, another use above has the same issue with a CRJ aircraft. I assume it's Aerosoft.

I think it's something to do with the high number of variable this aircraft has. It was too many for the limits baked into WASM module.

I can see in the GitHub project that John has expanded the capacity in version 0.5.3. I'm hoping that will fix the issue.

The fsuipc.com page still has 0.5.2 so we'll need to wait until John releases the new version to try it.

Paul

 

That's exactly what I was thinking too, Paul.  Thanks,buddy! 

Link to comment
Share on other sites

1 - A new version of the DLL is now on NuGet - 3.2.10

The MSFSVariableServices has had some changes to make it work better. Unfortunately most are breaking changes but they're not that drastic:

The VariablesReady property has been removed as that never really worked after it was initially set to true.

The OnVariablesReadyChanged event has been replaced with OnVariableListChanged. This fires whenever the WASM module detects new LVars or HVars. You can use this to know when the variables have been detected and are ready to read.

2 - Example Code / Test Project

I've added an example project for the MSFSVariableServices to the website:

http://fsuipc.paulhenty.com/#downloads

C# only at the moment. I'll convert to VB.NET if anyone requests it.

3 - Requirements

This new version should be used with version 0.5.3 of the FSUIPC_WAPID.dll or later.

Also required is FSUIPC7 V7.2.7 (or later) as this will install the 0.5.3 WASM module into MSFS.

Both can be download from 

http://fsuipc.com/

4 - Access Violations in CRJ

This may or not be fixed with this version. John has increased the number of LVars that can be handled in 0.5.3 which might have have been the problem.

Paul

  • Like 1
Link to comment
Share on other sites

Hi @Paul Henty,
it is possible to have a specific list/array of LVras and fire just one event if only one in that list changes, instead of having a method for each of them?

Now I think I have one method for every one, or I have to read all of them and just see if the one I need changed.
...
this.lVarListen1 = this.VS.LVars["A32NX_ADIRS_KNOB_1"];
this.lVarListen1.OnValueChanged += lVarListen1_OnValueChanged;

this.lVarListen2 = this.VS.LVars["A32NX_ADIRS_KNOB_2"];
this.lVarListen2.OnValueChanged += lVarListen2_OnValueChanged;

 private void lVarListen1_OnValueChanged(object sender, LVarEvent e)
 {....}

 private void lVarListen2_OnValueChanged(object sender, LVarEvent e)
 {....}
And so on...

is there any chance that lVarListen is a list or array?

Thanks

Link to comment
Share on other sites

You can achieve the same thing by using the same event handler for all the LVars you want to monitor.

The eventargs (e) will tell you which LVar has changed...

Something like this:

this.lVarListen1 = this.VS.LVars["A32NX_ADIRS_KNOB_1"];
this.lVarListen1.OnValueChanged += lVar_OnValueChanged;

this.lVarListen2 = this.VS.LVars["A32NX_ADIRS_KNOB_2"];
this.lVarListen2.OnValueChanged += lVar_OnValueChanged;

 private void lVar_OnValueChanged(object sender, LVarEvent e)
 {
    // One of your LVars has changed.
    // The changed one is e.LVar
    Log(e.LVar.Name + " has changed to " + e.Lvar.Value.ToString("F4");
 }

Will that do what you want?

Paul

  • Like 1
Link to comment
Share on other sites

  • 3 weeks later...

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.