• Which the release of FS2020 we see an explosition of activity on the forun and of course we are very happy to see this. But having all questions about FS2020 in one forum becomes a bit messy. So therefore we would like to ask you all to use the following guidelines when posting your questions:

    • Tag FS2020 specific questions with the MSFS2020 tag.
    • Questions about making 3D assets can be posted in the 3D asset design forum. Either post them in the subforum of the modelling tool you use or in the general forum if they are general.
    • Questions about aircraft design can be posted in the Aircraft design forum
    • Questions about airport design can be posted in the FS2020 airport design forum. Once airport development tools have been updated for FS2020 you can post tool speciifc questions in the subforums of those tools as well of course.
    • Questions about terrain design can be posted in the FS2020 terrain design forum.
    • Questions about SimConnect can be posted in the SimConnect forum.

    Any other question that is not specific to an aspect of development or tool can be posted in the General chat forum.

    By following these guidelines we make sure that the forums remain easy to read for everybody and also that the right people can find your post to answer it.

New SimConnect API for C#

Messages
26
Country
netherlands
[If the below feels like I am a "Grumpy old man" then please humor me. 57 years and developing since before the 8086 and 8088 came around should entitle me to that. I still have the TRS-80 version of Flight Simulator somewhere, if the floppy is still readable]

I am a reasonably experienced developer in C/C++, a very experienced one in Java, and a beginner in C#. My background is mostly server-side with quite a bit of HTML UI interfacing, but only some (very) limited experience in old-school Windows UI interfacing. I have done some experiments with C++ and SimConnect, but my sense of "Good Programming" led me to immediately hide the (IMHO) ugly SimConnect API in a few classes, using multi-threading to take care of the communication. Send in a request that will eventually get me a reply in the stream of messages? Good, that's a "Future" and I'll provide a lambda to pick up the reply whenever it comes. Works beautifully, until I want a UI.

Writing UIs in Windows is a total mess. The Windows XP age is definitely gone, so I'd rather not go down the path of CWindows and CDialogs, which are still supported and happily used by a lot of FlightSim tools I see around but force me to constantly worry about their implementation details. Also, the messaging infrastructure of Windows keeps rearing its ugly head in the most unfortunate places, which forces you to lug HWND values around even if you don't care about using anything graphical. C# and XAML are a lot closer to what you'd want to use nowadays, but make the wrong choice when you create the project and your application won't run until you send it in for distribution through the Microsoft Store. Don't mind, to be honest, but the hassle of registration and packaging takes the fun out of it quickly.

So Microsoft is now into .Net and the CLR, with C# (and to some degree F#) as the big stars, and there is even DotNet Core which allows you to (somewhat) forget Windows altogether and create applications that are (source) compatible across platforms, allowing you to write something that will work on Linux and macOS just as well as on Windows, meaning I can write server software that does not need a monitor and mouse/keyboard combo to work. XAML UIs even work using Xamarin, so that is actually pretty neat. Great, but SimConnect is stuck in the past. There is a network protocol for it; must be because I can connect across networks to Prepar3D (and probably/eventually MSFS), but it is not very well documented or at least not well published. Somebody wrote "jsimconnect", so there is a reverse-engineered Java implementation of it, but let's not go into that... for now.

So I took a look at the Prepar3D documentation for the Managed Code version of SimConnect, and it is like someone grudgingly acknowledged that such a thing needs to exist, but let's not put too much effort into being fancy about it. Maybe they're still mad that Adobe finally pulled the plug on Flash (didn't that feel like a relief?) just when they were set to allow Flash gauges.

So, time to do some serious Software Architecting and Developing, which is what my daytime job states I should do, and find or build something that means I can do productive and modern software development while communicating with a flight simulator. Am I duplicating efforts here? I am not intending to build a commercial empire around this, so my intention is that all the source code will end up on GitHub.

Bert Laverman
 

rhumbaflappy

Administrator
Staff member
Resource contributor
Messages
5,944
Country
us-wisconsin
I don't believe you are duplicating anyone's efforts. Long ago we had an implementation in Delphi. And beetle (one of the MS Aces) had a C# solution, but that has disappeared I think.
 

scruffyduck

Administrator
Staff member
FSDevConf team
Resource contributor
Messages
34,854
Country
unitedkingdom
There is at least one C# library for FSUIPC connectivity. But I am not aware of a C# library for SimConnect. In any case we are always better for having more than one solution to give users a choice
 
Messages
26
Country
netherlands
Ok, I've got a small start now. All the code is up on GitHub, under the Apache 2.0 license. This means any code in this repository is copyrighted, but you are free to use it in private and commercial applications. See here for the details on the license, or a short explanation on Wikipedia.

The solution (CsSimConnect) is comprised of three parts:
  • The first step is an unmanaged C++ DLL named CsSimConnectInterOp, which links in the C static SimConnect library.
  • The actual C# Class Library is a managed DLL.
  • A small test/demo app, which is a WPF C# program demonstrating how to interact with the class library.
Currently, all it can do is connect, poll for messages, and provide a few event handlers.

How you can contribute:
  • If you just want to look at or use the code and are unfamiliar with Git and GitHub, use the friendly big green button to get a ZIP file, or browse it online.
  • If you want to suggest additions/improvements/next steps, use the "Issues" tab and create stories or bug reports.
  • If you want to fix things or provide code, send me an email and I can add you as a contributor, so you can create branches/PRs and push commits.
Important design issue:
I'm very much used to the way Java handles concurrency. This takes a data-oriented approach, where you create "Futures" or "Streams" (Project Reactor's "Mono"s and "Flux"s) that you can return immediately, while the caller can choose to wait for actual data to become available, or start a separate thread that processes the data whenever it comes. The C# approach however is a more imperative approach, where you create an "IEnumerable" that provides the same function to the caller, but is the active producer of the results. So with Futures, you can split off producer and consumer, and the Future itself is the clearinghouse in between, while IEnumerables should produce the result themselves.​
For SimConnect we have an external source of data, which is represented by a communication channel that gives us messages (The SIMCONNECT_RECV struct and its extensions), so we have a source of messages that pumps the data into one or more sinks, depending on who asked for that message. I so far implemented two possible sinks, one for system state requests, where messages are matched with the requestor based on the Request ID, and one for events, which uses an Event ID. Later on, we'll also get data definitions.​
So if I send a request for the current aircraft loaded, the Java approach would be to create a Future or a Mono and return that, while keeping it stored, keyed to the Request ID. When the message comes in, we notice the Request ID, retrieve the Future, and complete it with the result. If it is a subscription rather than a request, we use an Event ID instead and use something like a project Reactor "Flux", which corresponds to a stream (or enumerable) of futures. If we get an exception message and are able to correlate it to the request, we pass that into the Future/Mono, so the caller gets an exception thrown, or provides a handler for exceptions.​
On the caller's side, this means I have an object that I can keep pulling data from, without being bothered by the mechanics of handling messages. Because the message stream is split up into separate streams based on who asked for the data, this means I could have a UI component that e.g. shows the location of the aircraft, where the implementation just creates a define for the coordinates, then requests updates for it every second, and split off a Task that pumps that stream into the UI. Very clean and simple.​
I need to come up with a fitting implementation of that concept. Have a single producer of data, the "yield returns" to one of a group of consumers. Should be possible, but still searching.​

Update: I probably need to study up on Reactive Extensions and Rx. That seems to be what I missed.

Cheers,
Bert
 
Last edited:
Messages
15
Country
switzerland
What am I missing? Look at the SimvarWatcher sample in the SDK. Present since last August: Its a SimConnect, C#, WPF (means XAML and all but not UWP) app.

Another example: pushbackHelper

I would also disagree, that Windows UI programming is a mess. Since writing MFC applications with VS98 I enjoyed UI designers, that actually worked. Something at least I never encountered on any other platform with any other programming language. Later with WPF/XAML/Blend the UI designer tools were perfected.
 
Messages
26
Country
netherlands
Well, for what it's worth, the pushbackHelper app won't work with Prepar3D, because of the SimConnect namespace; "Microsoft.FlightSimulator.SimConnect" vs "LockheedMartin.Prepar3D.SimConnect".

Sidestepping that, let's take a snippet from the pushbackHelper's "SimConnectManager" class:
C#:
simClient.AddToDataDefinition(DefinitionsEnum.RefreshDataStruct, "Plane Heading Degrees True", "degrees", SIMCONNECT_DATATYPE.FLOAT64, 0.0f, SimConnect.SIMCONNECT_UNUSED);
simClient.AddToDataDefinition(DefinitionsEnum.RefreshDataStruct, "Pushback State", "Enum", SIMCONNECT_DATATYPE.INT32, 0.0f, SimConnect.SIMCONNECT_UNUSED);
simClient.AddToDataDefinition(DefinitionsEnum.RefreshDataStruct, "Brake Parking Position", "Bool", SIMCONNECT_DATATYPE.INT32, 0.0f, SimConnect.SIMCONNECT_UNUSED);
simClient.AddToDataDefinition(DefinitionsEnum.PushbackWait, "Pushback Wait", "Bool", SIMCONNECT_DATATYPE.INT32, 0.0f, SimConnect.SIMCONNECT_UNUSED);
simClient.AddToDataDefinition(DefinitionsEnum.VelocityX, "Velocity Body X", "feet per second", SIMCONNECT_DATATYPE.FLOAT64, 0.0f, SimConnect.SIMCONNECT_UNUSED);
simClient.AddToDataDefinition(DefinitionsEnum.VelocityY, "Velocity Body Y", "feet per second", SIMCONNECT_DATATYPE.FLOAT64, 0.0f, SimConnect.SIMCONNECT_UNUSED);
simClient.AddToDataDefinition(DefinitionsEnum.VelocityZ, "Velocity Body Z", "feet per second", SIMCONNECT_DATATYPE.FLOAT64, 0.0f, SimConnect.SIMCONNECT_UNUSED);
simClient.AddToDataDefinition(DefinitionsEnum.RotationX, "Rotation Velocity Body X", "feet per second", SIMCONNECT_DATATYPE.FLOAT64, 0.0f, SimConnect.SIMCONNECT_UNUSED);
simClient.AddToDataDefinition(DefinitionsEnum.RotationY, "Rotation Velocity Body Y", "feet per second", SIMCONNECT_DATATYPE.FLOAT64, 0.0f, SimConnect.SIMCONNECT_UNUSED);
simClient.AddToDataDefinition(DefinitionsEnum.RotationZ, "Rotation Velocity Body Z", "feet per second", SIMCONNECT_DATATYPE.FLOAT64, 0.0f, SimConnect.SIMCONNECT_UNUSED);
I would absolutely prefer to be able to only write:
C#:
class PushBackData {
    [DataDefinition("Plane Heading Degrees True", Units = "degrees", Type = DataType.Float64)]
    public double heading;
    [DataDefinition("Pushback State", Units = "Bool", Type = DataType.Int32)]
    public int pushbackState;
    // etc...
}
I don't mind doing everything by hand once, but having the library take care of all the "AddToDataDefinition" calls for me is definitely preferable. Also, the current managed SimConnect library allows you to simply add handlers for types of messages, but it is still up to you to find out which particular request that message relates to, while in my approach that is taken care of for you. You get an object you can iterate over, or you give it a delegate (or lambda) that only gets the data you asked for.

As for the UI work, XAML is a definite improvement, being more like a Web front-end. Fluid designs are up-front, so making resizable dialog boxes is a lot easier. Take the FSUIPC dialog: you can do everything you need, but it is fighting for space. Anyways, if working with MFC and ATL is your thing, then, by all means, go ahead. I admit I am not a fan, so I am definitely prejudiced. When Windows XP ruled, it was definitely top of the line, but nowadays we generally do things differently. I may be old (57 is old in the programmer space), but I learned to keep learning and adapting, and I agree with the move onwards.

That SimVarWatcher example makes a valid point though, which is the dynamic use-case: What if you want to specify at runtime which variable you want to request. I still think you don't want to do all the "plumbing" yourself though, so a nice approach would be to provide the library with a collection of "DataDefinition" objects. Good point, will take that along.

Cheers,
Bert
 
Messages
15
Country
switzerland
Sorry, I missed that P3D was targeted.

Anyways, if working with MFC and ATL is your thing, then, by all means, go ahead.
I have not programmed MFC anymore since 10 years+. I just say, the tools were good. Windows Forms (the easiest for small GUIs), WPF, UWP (which is a very nice and streamlined version of WPF) are of course much more modern. Even more is .NET core.
 
Top