• 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.

MSFS SimConnect_AddToFacilityDefinition in C#

Messages
8
Country
germany
Hi,
I'm desperately trying to get airport information from MSFS using the relatively new SimConnect_AddToFacilityDefinition function.

Sending the request and receiving some kind of data is working fine. However, I'm not able to get more than a single int.
I've made a bare-minimum example for VS2022 in .NET 6 for you to test it yourself easily: https://github.com/Clamb94/SimconnectAirportDataTest

It's obviously very simple. It opens the SimConnect connection and checks every 500ms for a new message.
Once it get's the OSimConnect_OnRecvOpen message, it request the latitude and number of runways in Frankfurt.

C#:
            OSimConnect.AddToFacilityDefinition(sd, "OPEN AIRPORT");
            OSimConnect.AddToFacilityDefinition(sd, "LATITUDE");
            OSimConnect.AddToFacilityDefinition(sd, "N_RUNWAYS");
            OSimConnect.AddToFacilityDefinition(sd, "CLOSE AIRPORT");

            OSimConnect.RequestFacilityData(sd, rd, "EDDF", "");

Shortly thereafter, I'll receive a response on OSimConnect_OnRecvFacilityData(SimConnect sender, SIMCONNECT_RECV_FACILITY_DATA data).
Now comes the problem: I can't make anything useful out of the data member.

When I'm only requesting a single INT32, like "N_RUNWAYS", the data.Data[0] variable holds a value of 4, which is correct for Frankfurt.

When I'm only requesting a single FLOAT64, like "LATITUDE", the data.Data[0] variable holds an UInt32 with value 1550843904, which doesn't make any sense to me.
I tried casting it to an double, but this throws an exception:

Code:
double lat = (double)data.Data[0];

throws:
{"Unable to cast object of type 'System.UInt32' to type 'System.Double'."}    System.Exception {System.InvalidCastException}

Obviously, I'm also not able to request more than one value at a time and get a useful response.
I tried casting it to a struct like this, but this also throws a System.InvalidCastExcpetion.
(That's the version on GitHub)

C#:
        [StructLayout(LayoutKind.Sequential, Pack = 1)]
        struct airport
        {
            public double latitude;
            public int nRunways;
        };

       airport a = (airport)data.Data[0];
       Console.WriteLine($"Lat: {a.latitude}; Rwys: {a.nRunways}");

There is an example C++ included in the SDK samples called FacilityDataDefinition, they also cast the reply in a struct.
But I can't seem to replicate the C++ code in C#.

Any ideas how to solve this?
Thanks :)

Best regards
Axel
 
airport a = (airport)data.Data
That gives me a compile time error:
Error CS0030 Cannot convert type 'object[]' to 'SimconnectAirportDataTest.Program.airport' SimconnectAirportDataTest C:\GitHub\SimconnectAirportDataTest\Program.cs 73 Active
 
Am I correct in believing that your variable you call data is the SIMCONNECT_RECV_FACILITY_DATA struct that is returned, yes?

Also, I see some errors in the SDK's documentation... so... maybe there are a few that aren't so obvious as this one:

C#:
HRESULT SimConnect_AddToFacilityDefinition(
    HANDLE hSimConnect,
    SIMCONNECT_DATA_DEFINITION_ID DefineID,
    const char * FieldName
    );

FieldNameSpecifies the client defined request ID. This will be returned along with the data.Integer
 
Am I correct in believing that your variable you call data is the SIMCONNECT_RECV_FACILITY_DATA struct that is returned, yes?
Correct.
I have the feeling we are on the right track, but the conversion from one object type to another is not working properly.
I’m just running out of ideas what else to try.
(Even chatGPT can’t help me)
 
ChatGPT uses a database of similar replies, it only ever copies and pastes a synthesis of existing statements. If none exist as in your case, CGPT is waiting for you to educate it. You do know it lies, right? Ask it about aliens, or the Anunnaki, CGPT is duty driven to be the ultimate authority on anything, just like Pinocchio.
 
I'm starting to think there is an error in the C# sim connect library.
When trying to receive two INT32 value, like those below, the response message only contains the actual value of the first request.

Code:
            OSimConnect.AddToFacilityDefinition(sd, "N_ARRIVALS"); //Should be 45
            OSimConnect.AddToFacilityDefinition(sd, "N_RUNWAYS"); //Should be 4

If I make those two request for EDDF, the SIMCONNECT_RECV_FACILITY_DATA response contains a member:
public object[1] Data.
This contains only one INT32 with value 45, which is correct for the requested N_ARRIVALS parameter.
No sign of the N_RUNWAYS parameter which has been requested as well.
 
Nevermind, problem is fixed.
I got a reply an reply here.
After adding the following line, I didn't get the System.InvalidCastExcpetion anymore.
Code:
    OSimConnect.RegisterFacilityDataDefineStruct<airport>(SIMCONNECT_FACILITY_DATA_TYPE.AIRPORT);

I'll update the code on GitHub accordingly, just in case someone needs a reference in the future.
 
Well, that's not even in the SDK... so.. not sure how one is supposed to know it needs to be utilized?

Also, yet another shining example of why C# is a horrible language, in my opinion.
 
That's the code behind it in the .dll

C#:
        public void RegisterFacilityDataDefineStruct<T>(SIMCONNECT_FACILITY_DATA_TYPE dwType)
        {
            RegisterStruct<SIMCONNECT_RECV_FACILITY_DATA, T>(dwType);
        }

        public void RegisterStruct<RECV, T>(Enum dwID) where RECV : SIMCONNECT_RECV
        {
            Dictionary<uint, Type> value = null;
            if (!m_RegisteredStructs.TryGetValue(typeof(RECV), out value))
            {
                value = new Dictionary<uint, Type>();
                m_RegisteredStructs.Add(typeof(RECV), value);
            }

            value[(uint)Convert.ToInt32(dwID)] = typeof(T);
        }

But of course it should be documented somewhere. Well, for now I'm just happy that it's working.
 
Nevermind, problem is fixed.
I got a reply an reply here.
After adding the following line, I didn't get the System.InvalidCastExcpetion anymore.
Code:
    OSimConnect.RegisterFacilityDataDefineStruct<airport>(SIMCONNECT_FACILITY_DATA_TYPE.AIRPORT);

I'll update the code on GitHub accordingly, just in case someone needs a reference in the future.
Very useful for me. Thanks
 
Back
Top