Sign in to follow this  
jfjoubert

PMDG 737NGX SDK C# P3D

Recommended Posts

Hi,

 

I'm busy writing an application in Visual C# 2010 to interface with the 737 NGX CDU's via the SDK. So far I'm able to control the key press events on both CDU's and I'm able to catch all the events returned from P3D when the data on the CDU has changed.

 

I'm struggling with marshalling the PMDG_NGX_CDU_Cell and PMDG_NGX_CDU_Screen structs to managed code in C# to be able to read the CDU screen data.

The PMDG_NGX_Control struct was straight forward to marshal.

I'm not too sure how to define these structs and which method(s) to call to register them:

  • simconnect.AddToDataDefinition
  • simconnect.RegisterDataDefineStruct
  • simconnect.RegisterStruct

Has anyone managed to do this in C#? My C++ Console app is working 100%, but I'm not a C++ expert and I would like to have a GUI for my app.

 

Any help would be greatly appreciated.

 

PS: I know I can just go and buy VAInterface... but this app will be the "poor" simmers option.  ^_^

Share this post


Link to post
Share on other sites
Help AVSIM continue to serve you!
Please donate today!

private enum DATA_REQUEST_ID : byte
{
    DATA_REQUEST = 100,
    CONTROL_REQUEST,
    CDU_REQUEST
}

PMDG_NGX_CDU_Screen cdu_Screen;

simconnect.MapClientDataNameToID(PMDG_NGX_CDU_0_NAME, PMDG_NGX_CDU_0_ID);
simconnect.AddToClientDataDefinition(PMDG_NGX_CDU_0_DEFINITION, 0, (uint)System.Runtime.InteropServices.Marshal.SizeOf(cdu_Screen), 0, 0);
simconnect.RegisterStruct<SIMCONNECT_RECV_CLIENT_DATA, PMDG_NGX_CDU_Screen>(PMDG_NGX_CDU_0_DEFINITION);    
simconnect.RequestClientData(PMDG_NGX_CDU_0_ID, DATA_REQUEST_ID.CDU_REQUEST, PMDG_NGX_CDU_0_DEFINITION, SIMCONNECT_CLIENT_DATA_PERIOD.ON_SET, SIMCONNECT_CLIENT_DATA_REQUEST_FLAG.CHANGED, 0, 0, 0);
  

Should be what you need.

 

Best wishes

Steve

Share this post


Link to post
Share on other sites

Just a question, If this is for andoid tablets, please maximize the screen space...I've got a Nexus 7 and the other FMC app leaves some blank space around the edge that looks nice, but I'd rather have the biggest buttons I can on my small screen. 

Share this post


Link to post
Share on other sites

Hi Steve,

 

Thanks for the info... I really appreciate it.

 

Would you mind showing me how you've declared your PMDG_NGX_CDU_Screen and PMDG_NGX_CDU_Cell structs in C#? 

Here's my struct code so far... I'm not sure as to how to declare the screen struct containing the cell struct and whether I'm using the correct StructLayouts and Marshal settings:

// NGX CDU Screen Cell Structure
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
struct PMDG_NGX_CDU_Cell
{
    public char Symbol;
    public char Color;
    public char Flags;
}

// NGX CDU Screen Data Structure

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
struct PMDG_NGX_CDU_Screen
{
    [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.Struct)]
    public PMDG_NGX_CDU_Cell[,] Cells;
    [MarshalAs(UnmanagedType.Bool)]
    public bool Powered; // true if the CDU is powered
}
Any help with this would once again be greatly appreciated.

 

Thanks and regards,

Share this post


Link to post
Share on other sites
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 4)]
public struct PMDG_NGX_CDU_Cell
{
    public char Symbol;
    public char Color;
    public char Flags;
}

[StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Ansi)]
public struct PMDG_NGX_CDU_Screen
{
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 24)]
    public CDUROWS[] cduCols;

    [StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Ansi)]
    public struct CDUROWS
    {
         [MarshalAs(UnmanagedType.ByValArray, SizeConst = 14)]
         public PMDG_NGX_CDU_Cell[] cduRows;
    }

    public Boolean Powered;	// true if the CDU is powered
 };

You'll need something like this (sorry not at my development PC, so can't check):

Share this post


Link to post
Share on other sites

Steve,

 

Thanks. Using your code above for the Screen struct has the unfortunate side-effect of blocking/breaking all simconnect_OnRecvClientData events... I'm not getting any updates back from the CDU. Weird...

 

Anyhow, I'll play around with this to see if I can figure out why.

 

If you don't mind could you perhaps check your code on your dev pc... when you have a moment? I'll really appreciate it.

 

I know I'm close with this because my silly screen struct was returning portions of the CDU data, albeit not very useful.

 

Thanks and regards,

Share this post


Link to post
Share on other sites

Hi Jean,

 

Just realised my mistake. Change "public Boolean Powered;" to "public byte Powered;". I would also change Color and Flags to byte as they are bit mapped.

 

Final thought is that you have remembered to add these entries into the 737NGXOptions.ini file:

 

[sDK]
EnableDataBroadcast=1
EnableCDUBroadcast.0=1
EnableCDUBroadcast.1=1

 

I'm sure that will make it work OK now.

 

Best wishes

Steve

Share this post


Link to post
Share on other sites

Steve,

 

You're the man.

 

I couldn't understand why my OnRecvClientData event wasn't triggered... turns out to be the space occupied by a boolean instead of a byte in managed code. 

I actually modified your recommendation slightly to keep a bool in c#, by marshalling it to a 1-byte signed integer: (perfect for handling C-style bool values)

[MarshalAs(UnmanagedType.I1)]
public bool Powered;	// true if the CDU is powered

Thanks ever so much for all your assistance. I really appreciate it.

 

Regards,

Jean

Share this post


Link to post
Share on other sites

Easily overlooked mistake caused much head scratching! Glad its working OK.

 

Best wishes

Steve

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this