MobiFlight WASM module - question about efficiency

I’m addressing this question directly to @MobiFlight. I choose not to post it in the MobiFlight forum, because it is rather a generic WASM/SimConnect question.

As a learning experience, I am analyzing the source code of the MobiFlight WASM module, to understand its internal workings. Not sure if I’m dealing with the latest version, but I found it here.

I see that in “module_init” the WASM module registers for EVENT_FRAME.

hr = SimConnect_SubscribeToSystemEvent(g_hSimConnect, EVENT_FRAME, "Frame");

In the MyDispatchProc, this event is captured to call “ReadSimVars()”. As far as I understand, this is happening every frame.

case SIMCONNECT_RECV_ID_EVENT_FRAME: {
	SIMCONNECT_RECV_EVENT* evt = (SIMCONNECT_RECV_EVENT*)pData;
	int eventID = evt->uEventID;

	ReadSimVars();
	break;
}

“ReadSimVars()” is then itterating through each SimVar and reads its value using “execute_calculator_code”.

// Read a single SimVar and send the current value to SimConnect Clients
void ReadSimVar(SimVar &simVar) {
	FLOAT64 val = 0;
	execute_calculator_code(std::string(simVar.Name).c_str(), &val, NULL, NULL);
	
	if (simVar.Value == val) return;
	simVar.Value = val;

	WriteSimVar(simVar);

#if _DEBUG
	fprintf(stderr, "MobiFlight: SimVar %s with ID %u has value %f", simVar.Name.c_str(), simVar.ID, simVar.Value);
#endif
}

// Read all dynamically registered SimVars
void ReadSimVars() {
	for (auto& value : SimVars) {
		ReadSimVar(value);
	}
}

Now my question: Isn’t that very inefficient, reading all LVars every frame? Isn’t there a way to use a call similar to RequestDataOnSimObject using a flag SIMCONNECT_DATA_REQUEST_FLAG.CHANGED, and then trigger the client that something changed? Or is that the only way to deal with these LVars?

Unfortunately I don’t think there is a much better way right now. Those variables are not readable as a structure or over SimConnect for example.

Here is how I implemented a class to read and manage local variables, but the same principe applies. I don’t now if there is a difference between execute calculator code or reading a registered variable.

1 Like

Hello @AGuther,

I am a newbie in WASM, only having some experience with SimConnect. Can you explain a bit more? I’m also very confused in the naming conventions. SimVars, LVars, HVar… sometimes I have the feeling that people mix things (including me of course).

I’m talking about LVars and HVars, which can only be accessed through a WASM module. I know that external clients will only be able to retrieve them through SimConnect using ClientArea.

In a first attempt to build a WASM module, I try to read some LVar. I subscribed to EVENT_FRAME and there print the LVar about every second. I seem to get some value for the units enum (84 for “knots”, 143 for “enum”), but for the LVar enum I’m getting 0. Because of that, I’m not surprised that I’m getting a value of 0.000000. I guess that indicates I’m doing something wrong?

The code is below. Any idea what is wrong here?

case SIMCONNECT_RECV_ID_EVENT_FRAME:
{
	if (counter == 0)
	{
		counter = 60;

		ENUM e1 = get_aircraft_var_enum("A32NX_EFIS_L_OPTION");
		ENUM e2 = get_units_enum("enum");
		FLOAT64 Value1 = aircraft_varget(e1, e2, 0);
		fprintf(stderr, "HABI: WASM_Module1 - test1 %u sec %u %u %f.\n", seconds, e1, e2, Value1);
	}
	else
		counter--;
}

The result:

image

A good overview on variable types: Variables Overview

I don’t think you can read L variables with aircraft_varget (see also aircraft_varget, documentation is referring only simulation variables).

The function execute_calculator_code (see also execute_calculator_code) is different and can do more things.

This page might be of help for you: C: XML Variables in C Gauges - FSDeveloper Wiki

In general, I would recommend you read and write local variables with:

You can find an overview of the Gauge API here: Gauge API

Great Stuff!! More pieces of the puzzle are coming together.

I must say that I have the impression that the Prepar3D documentation of SimConnect is a lot better than the original of Microsoft, don’t you think?

I used check_named_variable first to get the ID of an existing variable, and then used get_named_variable_value and it worked! I now realize that @Umberto67 already gave that same feedback here, but I realized only now that this is what I needed.

I see that these functions only return double. But if an LVar returns a string, what function can be used? I assume in that case that only “execute_calculator_code” can come to the rescue, because that allows to return a FLOAT64, SINT32 or PCSTRINGZ? Or are there other options? (I looked in the SDK documentation, but couldn’t find any).