SimConnect + WASM combined project using VS2019

I still wonder though why it is hanging at all if I start the simconnect in a separate thread. That isn’t supposed to freeze the application then is it?

EDIT: Brainwave: that’s probably because it is using the window handle of course…

If you use the window handle of you main window, then it might indeed be that you are blocking this messagepump. That’s why people like @Dragonlaird use an approach with a separate (hidden) window and pass this handle to SimConnect instead (see this post).

My application is intended as the basis for a kind of a Hardware hub, which is normally going to run in the background anyway, just offering some features for monitoring and testing during development. That means that I’m not so afraid of the blocking of the window for a while. But if it would really get annoying, then I would go back to the “separate message pump approach”.

1 Like

Great suggestion, thank you!

Addendum 3: A more responsive Connect method

As indicated by @TFEV1909 above, the Connect method can be blocking the main UI thread if connecting over the network. Especially when trying to connect over the network while MSFS2020 is not running. I never tried myself to connect over the network, but I have experience with WinSockets that have the same kind of behavior. The connection will retry several times until a timeout occurs, which blocks the call for several seconds.

@TFEV1909 came with a solution that uses async methods. We simply launch the connection in a different thread using Task.Run(), and await for this thread to finish. The await keyword will make sure that the call to Task.Run() immediately returns to the UI thread, which avoids the blocking. Once the connection is finished, whether it is successful or not, the code after the await continuous to execute. All this hocus pocus happens in the Task Parallel Library (TPL).

When you want to await for a Task, then you must precede your calling method with async. Visual Studio will make it very easy and even suggest these changes automatically. Below you will see my revised Connect method which is now preceded by async. The name of the method is also changed to ConnectAsync(). This is only a naming convention, and not mandatory. But it helps if you would provide your code in a DLL to the outside world. By using the Async suffix, you let consumers of your DLL know that this method is Async and uses await statements.

The revision of the Connect method is below. All credits to @TFEV1909.

public async Task ConnectAsync()
{
    if (_bConnected)
    {
        LogResult?.Invoke(this, "Already connected");
        return;
    }

    try
    {
        await Task.Run(() => _oSimConnect = new SimConnect("SimConnectHub", _handle, WM_USER_SIMCONNECT, null, 0));

        // Listen for connect and quit msgs
        _oSimConnect.OnRecvOpen += SimConnect_OnRecvOpen;
        _oSimConnect.OnRecvQuit += SimConnect_OnRecvQuit;

        // Listen for Exceptions
        _oSimConnect.OnRecvException += SimConnect_OnRecvException;

        // Listen for SimVar Data
        _oSimConnect.OnRecvSimobjectData += SimConnect_OnRecvSimobjectData;

        // Listen for ClientData
        _oSimConnect.OnRecvClientData += SimConnect_OnRecvClientData;

        LogResult?.Invoke(this, "Connected");
    }
    catch (COMException ex)
    {
        LogResult?.Invoke(this, $"Connect Error: {ex.Message}");
    }
}

If you want to read a very good article about this asynchroneous concept, then I can definitly recommend Async Programming With the Task Parallel Library written by Nate Cook. It looks like this is a paid site, but I could click through the whole series for free.

Goto Addendum 3: Packing structures

3 Likes

@HBilliet @Dragonlaird I just wanted to let you both know what I created with help of your tutorials, see https://forums.flightsimulator.com/t/easycontrols-for-msfs-1-click-controllers-adjustment-per-aircraft

Thanks a lot for my questions answered by both of you. My project is still work in progress, but wouldn’t have been so far right now without your assistance!

Hello @TFEV1909,

Very impressive! I’m really glad to read that our tutorials have been a bit of help.

In the meantime, I’m rebuilding a complete application adding a USB server that allows connecting Hardware modules based on (for example) Arduino. I might write a new tutorial in the Third Party Addon section for this. So stay tuned!

Great job, glad we helped in some small way, that’s what the tutorial is for. Hope it really takes off (pun intended) :grinning_face_with_smiling_eyes:

Addendum 3: Packing structures

I had an issue with a structure I was using between my WASM Module and my SimConnect Client. When I was changing one of the datatypes from UInt16 to double, then suddenly my implementation stopped working and even completely crashed.

Below is the originally structure in both my WASM Module and SimConnect Client where all worked fine (this structure is not used in the implementation mentioned in this tutorial, but for a newer version for which I will soon create a new post).

WASM Module:

struct LVar {
	UINT16 lvID;
	UINT16 DefineID;
	UINT16 Offset;
	UINT16 Value;
	char Name[MESSAGE_SIZE];
	char Event[EVENT_NAME_SIZE];
};

SimConnect Client:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
public struct LVarAck
{
    public UInt16 lvID;
    public UInt16 DefineID;
    public UInt16 Offset;
    public UInt16 Value;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
    public String str;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
    public String sEvent;
};

But when I changed the field “Value” into a FLOAT64 (double), things got wrong.

WASM Module:

struct LVar {
	UINT16 lvID;
	UINT16 DefineID;
	UINT16 Offset;
	FLOAT64 Value;
	char Name[MESSAGE_SIZE];
	char Event[EVENT_NAME_SIZE];
};

SimConnect Client:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
public struct LVarAck
{
    public UInt16 lvID;
    public UInt16 DefineID;
    public UInt16 Offset;
    public double Value;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
    public String str;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
    public String sEvent;
};

It took a while for me to realize that the issue was caused by the setting “Pack = 1”. Here you can read the full story what this pack exactly does.

Bottom line is that by default, the fields in a structure are using an alignment that is defined by the settings of the compiler. In my compilers in VS2019 this is by default set to “Pack = 8”. You can read the details in the above mentioned link, but the result is that memory mapping of the LVar structure in my WASM Module looks like this:

Address 0: UINT16 lvID
Address 2: UINT16 DefineID
Address 4: UINT16 Offset
Address 6: padding             < this padding is automatically added to align at 8 bytes
Address 8: FLOAT64 Value
Address 16: ...

But in the SimConnect Client, the packing was forced to use “pack = 1”, which means that the below structure is expected:

Address 0: UInt16 lvID
Address 2: UInt16 DefineID
Address 4: UInt16 Offset
Address 6: double Value < HERE THE MISALINGMENT STARTS
Address 14: ...

Because “Pack = 1”, there are no gaps or padding used. You can clearly see the misalignment of 2 bytes, because no padding is added. If I used a UInt16 in both structures for the field Value, all worked well, but this is pure coincidence!

A way to solve this is to instruct the C++ compiler also to use “pack = 1”, but you need to use #pragma directives for this.

#pragma pack(push, 1) // packing is now 1
struct LVar {
	UINT16 lvID;
	UINT16 DefineID;
	UINT16 Offset;
	FLOAT64 Value;
	char Name[MESSAGE_SIZE];
	char Event[EVENT_NAME_SIZE];
};
#pragma pack(pop) // packing is 8 again

You could also remove the “pack = 1” in C#, in which case the #pragma directive in C++ isn’t necessary, because both compilers then use the (same) default packing. But in my opinion, it is safer to explicitly control the packing of the structures, because you never know what the default is.

Don’t hesitate to comment if you think I’m wrong :nerd_face:

2 Likes

@HBilliet very good write up! Thanks for mentioning https://mobiflight.com and https://hubhop.mobiflight.com - I can clearly see that a lot of your work is based on the MobiFlight WASM module - so i am happy it was useful.

Please feel invited to contribute to the MobiFlight WASM Module in case you’re seeing areas for improvement or if it is missing anything important. Your documentation would be a great addition to the repository too.

Just these days we added multi-client support to be able to let one instance be used by many clients at the same time.

I also added an improvement to make sure the client detects the WASM module once it is loaded.

I’m honored to receive these compliments from MobiFlight! Thank you very much. The MobiFlight sources have indeed been a great starting point. Without them, it would have taken me a lot more time to reach the point of writing this tutorial. I still have the printout of some modules next to me, full of notes and writeups of ideas :slight_smile: This together with the posts of @Dragonlaird got me started, combined with the feedback and tips of several other people on this forum. That’s why this is such a great forum!

MobiFlight is a great tool for people that are not so familiar with programming themselves. I have used it myself, and in most cases it did exactly what I wanted. It’s a great balance between being usable without the need of having to write one single line of code, but still flexible enough to configure and tweak the behavior.

I’m now working on a version of my software that connects with USB devices (even hot swappable!), as long as the devices support the “serial over USB” protocol (like Arduino). This implementation will be intended for people that like to write their own software in the USB device, which will provide greater flexibility, but at the cost of having to write your own code. I will again share my findings in a new post within a couple of weeks. So stay tuned!

Thanks for the invitation to contribute to MobiFlight. But I currently have not even enough time to finish my own projects. But don’t hesitate to connect with me if you want to discuss any topic. As I said before, I’m definitely not a professional programmer. I’m just doing this as a hobby, and like to analyze complex stuff. Just call me a nerd :nerd_face:

contribution is not limited by coding but also by posting ideas/improvements or submitting bug reports. good luck with your project.

Hi!

First things first: Your tutorial is A W E S O M E! Thank you for that!

So, my question is that I can’t set values using calculator code. I click Send button but nothing happens:

But requesting values works normally:

And another problem is setting value from variables, I get DATA_ERROR exception:

Whats the problem and how to fix it?

And extra question: what is the best place to find variables names, and is possible to set BOOL values using your tool?

Thanks again.

Hello @Cerb4ro,

First of all, thanks for your nice words. It gives a good feeling that my tutorial is being appreciated. And there is more to come. Based on this tutorial, I’m adding connectivity with USB connected Serial Port devices (like Arduino). So stay tuned!

1. Issue with setting variables

There are still mysteries in SimConnect and MSFS2020 for me as well. And I also have seen that some variables seem not to be settable for some reason. The KOHLSMAN SETTING variables are a good example. Looking in the SimConnect documentation, they should be settable:

But also if I try to set them, I get the DATA_ERROR. Setting them with execute_calculator_code has no effect neither.

I tried with the FlyByWire A32NX (which is an add-on), but also with the standard A320 neo, and in both cases I get the same issue.

Maybe @MobiFlight has an idea, as they have already expertise for many years? If I would investigate the problem (which I will do later for sure), I would try it first with their tool (MobiFlight has been a bit a “reference” for me). If that works… then it is a problem with my methodology, and then I’m sure I will be able to figure out why. But I’m curious to see if they have issues as well.

2. Where to find information about variables

There are a lot of sources. The ones I’m using are mentioned in my post here.

3. What about "Bool"

Although “Bool” exists as Unit, I think I have read somewhere that it is treated as a normal value such as INT32. A value of 0 is false, and any other value is true. At least, that is what I can read in the documentation here.

I wanted to try it with “CABIN SEATBELTS ALERT SWITCH”, which is a writable bool, but also there I got again the DATA_ERROR. I hope that @MobiFlight might shed some light on setting variables - maybe I’m doing something completely wrong.

1 Like

Let’s prevent a 30 days closure on this… Thanks for this topic… I did some hobbying in 2021 that can be found here changing a an SDK example to show a Dutch compass gauge (silly little change) it is fun to play with, you took it a lot further ! I also have a link for you, that is the github of Nguyễn Quý Hi which shows a very well structured example of a flight recorder using SimConnect from C#

Hi
First of all, congratulations for all you´ve done, it looks great and I´m sure that lots of people out there are going to make good use of your tool. It could work for me, at least I´m hopping that it will, but, I had the same feeling when trying out MobyFlight, and that didn´t work at all, they could find and answer to my issue. I have a A320 complete scaled Throttle that runs on a FTDI board and it work fine with XP11, but no signal whatsoever on MSFS2020. Now my question is, is there any chance of you coming up with a tool that wont need any code writing or any code programing needed? something simple that would recognize the FTDI and would let me tell it what to do?
Thank you again.
Paul

Hello @Xpress690,

I have no clue how your Throttle is communicating - can you be more specific about the brand/type to be able to reveal some technical details? As far as I know, an FTDI board is just converting RS232 into USB, but that doesn’t tell anything about what type of commands or data are required to communicate with your Throttle.

One thing is for sure - if you require a solution in which you don’t need to write code, then my post won’t be a lot of help. Even the second post I wrote (see here) is meant for people who write their own software in the controller (Arduino or other type that supports serial over USB). So I would think you should be more successful with @MobiFlight , but if you say that they couldn’t help, then I’m afraid that it ends here. Maybe there are other forums out there that can help?

Have you looked at Lorby-SI’s Axis and Ohs? It is pretty versatile software, that seems to detect most HID and USB devices out of the box. I believe they have a 15 day free trial - so give it a try.

If that doesn’t help - I don’t know anything specifically about the FTDI devices, so it would help if you give a few more clues by letting us know what kind of device Windows thinks it is. You should be able to see it in Device Manager > Human Interface Devices as either “HID-compliant consumer control device” or “USB Input Device”. If you can, right click on the entry, and click on “Properties”. Then select “Details” . If you get that far, you should be able to get enough information to post here so that someone can help you with the next step. If it’s a HID with a PID and VID, it’s pretty easy to communicate with using something like Axis and Ohs, SpadNext or any generic HID communicating software. It shouldn’t be too complicated once one knows what it is.

1
2
3
4

The answer to your question is, no, I haven´t. Never heard of them before.
I hope this helps, but the guys from MobiFlight tried to help and they couldn´t do anything for me.
The Throttle is the from fscockpit.eu, but they haven´t came up with a driver for MSFS2020 yet.
Thank you for all the help
Paul

Thanks. Axis and Ohs is pretty popular here and they had a huge thread for ages, but had to move it because it was too much Third Party support. It’s now on Avsim. AxisAndOhs Support - The AVSIM Community

Their web site is here: AXIS AND OHS - Home (weebly.com) . It would be well worth while trying, because your device looks like a pretty standard USB/HID device. It shouldn’t need any special MSFS drivers; it’s just a HID device that can be communicated with by something like Axis and Ohs, or SpadNext. Axis and Ohs is very easy to use and low price; SpadNext a tad more difficult and more expensive.

I’ve written my own HID communicator software which can probably communicate with your device OK, but of course I’ve got no means of testing that and it’s not in the sort of state where I’d like it to go public…

The screen you showed is from “Devices and Printers” btw. Useful, but better would be the one next to it “Device Manager”. That should show specifically where the device is located in the devices hierarchy

5

I´ve got into their page, don´t know yet how to use it, but will give a try.

thank you again