C++ continous data transmission with and without SysEvent subscription

Hey there

i’m working on an SimConnect/Serial interface written in C++.
It works fine so far but is a bit slow to my liking.
I’m requesting data on a 6Hz basis using:

hr = SimConnect_SubscribeToSystemEvent(hSimConnect, EVENT_SixHertz, “6Hz”);

That totally works fine.
To speed things up i tried to use the SystemEvent “Frame” but somehow it didn’ work.
Is the frame sysevent supposed to work?
Are there other system events that i could use instead?

Thanks for your input

cheers André

This is from the MSFS SDK SimConnect documentation.

It says Auto test Succes for Frame just like it does for 6Hz

Has somebody actually gotten Frame to work?

If I subscribe to 6Hz i can print out the requested data like this:

If I change the subscription from 6Hz to Frame i get this:
grafik

I mean the 7s that are coming in seem to be printed at the framerate. So the subscription somehow seems to work but what happened to my requested data?
Why is it gone when i don’t change any other parts of the code?

Hi Andre,

how are you defining the data you are interested in? When using SimConnect_RequestDataOnSimObject() you have a SIMCONNECT_PERIOD parameter where you should be able to choose visual frame, sim frame or even to only send when the data has changed which reduces strain. Like this you don’t have to subscribe to the sim event directly.

Greets,
Ben

Nevermind… I found the Problem
The SystemEvent Frame has its own SIMCONNECT_RECV_ID
which is SIMCONNECT_RECV_ID_EVENT_FRAME
and not SIMCONNECT_RECV_ID_EVENT

Hi Ben
Seems like what you are describing is a more elaborate way to do what i want.
But i’m not shure i get it. I’m looking for this SIMCONNECT_PERIOD parameter now…
i will come back at you

I’m doing this now:

so what you’re saying is tha i could use
SimConnect_RequestDataOnSimObject()
instead of
SimConnect_RequestDataOnSimObjectType()
?

Thank You very much!
this seems to be a valuable function


i’m not entirely shure what to do with all those parameters yet but i will try to figure it out
a look into SimConnect.h shoudl help i guess
let’s see if i get it to run
Thanks!!!

Which SIMCONNECT_PERIOD Member would allow me to only send data when it has changed?

nevermind… found it

You have to also look into the Flags parameter where you can define that you only want to have the data once it has changed under certain conditions pertaining to how you’ve defined your DEFINITION_1, especially it’s data type. I’m not at my system right now, so that’s all I can say for now ;). Best is to also look at the SDK of P3D which lays out the proceedings quite well.

Greets, Ben

Thank You! This allready helped me A LOT!
cheers André

1 Like

It does work all now. Values are only sent when they are changed and i dont need to subscribe to systemevents. This is fantastic :smiley:

@ AndreZwicky Any chance you could share your code as a complete example?

@MSGamerTag01 I might do that once i finished the project.
I’m working on a motorized throttle quadrant that comunicates via serial, So the program i am writing is basically a homebrewed SimConnect/Serial interface and the code will be quite specific. Not shure how helpful this will be. If you just wanna look at C++/SimConnect code examples you are probably better off checking the p3d simconnect sdk examples. They are very useful.
You can find them here: https://www.prepar3d.com/SDKv5/LearningCenter.php

Or just ask a question here…
what do you need?

merry christmas

Thanks Andre - merry xmas! I’m looking for any sample simconnect program that uses the RequestDataOnSimObject as intended i.e. you do NOT have a client-side timer and loop there polling for data from the sim. Instead you ‘subscribe’ for the data and the sim CALLS your callback.

Examples for this are incredibly rare, with developers naively copying e.g. the Request Data sample or the SimvarsWatcher sample which ‘poll’ for data which only works for the most basic low-rate apps.

I am curious about this, too. In fact, polling is an „accepted“ way of querying sim vars, as it seems. As you say, all tutorial examples I have found so far - including actual applications on e.g. github.com - use either a timer or a „polling loop“ (even as mercilessly to the CPU as „while (true) loop… sleep(1) end loop“)

Interestingly though:

http://www.prepar3d.com/SDKv4/sdk/simconnect_api/references/general_functions.html#SimConnect_CallDispatch

„ It is important to call this function sufficiently frequently that the queue of information received from the server is processed (typically it is coded within a while loop that terminates when the application is exited)“

So this seems to confirm that polling is the way to go. But…

„ However, if the project involves developing a library (DLL) rather than an application (EXE) then only one call to this function is necessary. This call will store the name of the callback in a cache, and whenever a packet is sent to the client, the callback function will be run“.

An example DLL setup with int __stdcall DLLStart(void) and void __stdcall DLLStop(void) is given.

So from what I understand from this, if you implement your SimConnect logic in a DLL:

  • You connect to the flight simulator when the DLL is loaded (started), and…
  • … call SimConnect_CallDispatch in that same „start“ function, but only once.
  • Due to some black magic the actual SimConnect.dll logic then „remembers“ (caches) your callback and - according to the documentation - calls it whenever messages (sim vars, possibly also sim events…) arrive

Now why one cannot register the callback by other means such that it is called whenever messages arrive (except this DLL voodoo magic) is beyond me. And quite possibly this may be specific to the Prepar3D implementation!

And there is an obvious disadvantage, too: the flight simulator already needs to be up and running in order to be able to connect when the DLL is loaded.

(Not sure whether the same mechanism works when dynamically loading/unloading the DLL (as a „plugin“), which would allow to „reconnect“ dynamically at runtime of the client application).

I haven‘t tried this DLL approach just yet (I am only like three days into my own experiments ;)), but would be interested in any findings, too. Especially whether there is not another way to register the callback, such that we can avoid calling „dispatch“ in a polling way.

The people (person?) that developed Simconnect back in the early 2000’s absolutely knew what they were doing. Gaming code has been ‘event driven’ for ages. It’s just mainstream programmers have never really seen the async style of programming and so get it wrong over and over again (so yes, there is a huge amount of polling code out there, but it’s pretty much all wrong). Back in 2000 the only mainstream method available for async programming was the ‘callback’, so simconnect supports this. More generalised capabilties have been added to languages more recently (async/await) but the callback method works fine (and is the central style of programming in javascript on mouseclicks, keystrokes, http data return, etc).

Simconnect has ‘Simconnect_CallDispatch()’ where you can define a completely general callback which the sim will call once per its internal update cycle. Inside your CallDispatch callback you basically have a case statement where you work out what events have occurred since you last got called, including new simvar data available for previous RequestData subscriptions.

Simconnect also has RequestDataOnSimObject(… …). This is similarly ‘event driven’ but this time specifically giving your callback the simvar values on each update cycle (which you can set as per frame, per second, …).

Neither Simconnect_CallDispatch() or RequestDataOnSimObject() should be considered ‘polling’, as both result in your code being called by the sim, not the other way round.

An example of why polling is problematic: at the moment I am looking at data through simconnect with a program that polls for the data 10 times/second. It is clear MSFS is updating the underlying simvars I’m using 18 times/second (e.g. if I ask for “E:ABSOLUTE TIME, seconds” it always changes on a 0.0556 second boundary). The difference between the sim update cycle and the polling frequency effecfively represents a ‘jitter’ in the values that has to be programmed around.

1 Like

My understanding is that a DLL runs in the same process as the simulator, so your callbacks can be called directly. A separate executable, however, has to have data routed through some sort of shared memory segment, and a win32 user-defined message event is used to wake up your process and tell it it’s time to go through the memory segment dispatching incoming events.

So calling SimConnect_CallDispatch is not “polling” in the sense that it doesn’t make any inter-process communication calls; it most likely just reads event records from a ring buffer.

But it does have to be called in a C/C++ executable, or its C# managed equivalent SimConnect.ReceiveMessage, to dispatch the callbacks.

I think maybe the CallDispatch call blocks inside simconnect until the data is ready, without blocking the main sim. Not sure.