PMDG NGX Data and Events Server

This program will also work for P3D/PMDG NGX

!!!  Added TCP/IP interface to facilitate network based hardware to directly access PMDGData and Events. See below for details.
!!! CDU screen content availble, no screen scraping anymore!


In the past it was a big challenge to use PMDG NG with SIOC (or any other hardware). In order to move switches, set controls or click buttons we were forced to use keyboard ‘key combinations’. Specific events are assigned a key combination. These key combinations are send to the NG using the virtual keyboard of SIOC. In SIOC script we have to configure the key combinations in another format.

This method can be used with the PMDG 737 NGX as well. Here you need to configure the key-combinations, per event, using the CDU as an input device. Pppfffffff. it’s a time consuming job to do. Then you have to make sure that the same key combinations are set within the SIOC virtual keyboard config. This is a painstaking process.

The number of key combinations is limited, Especially when all the CDU keys have to be set as well. There is a solution for the CDU by using the virtual joystick of FSIUPC for the CDU.  Never the less ….


Starting with the NGX 737 PMDG (rev c) released a SDK that allows programmers to write programs to read data and access all control elements of the cockpit that are also available on screen with the mouse/keyboard.

Revision Sp1D
With the release of SP1D Precision manuals also released an updated SDK. I did not make a list of all the additions and corrections that were made. I noticed that one bug I had with SP1C is the MCP AT Arm Annunciator is now solved.
Number of Data fields increased from 433 to 506 and the number of event went from 433 to 506. I noticed Electric Metering and IRS display items available.And more.

To allow access to the PMDG Data and Events made available by the SDK I made:


FSIO Software Components

In the picture above the position of the PMDGDataEventServer within the system. The PMDGDataEventServer program is not an integrated part of the FSIO hardware so it can be used independent by anybody that uses SIOC.

The program uses the PMDG SDK to retreive PMDG data and send it to SIOC variable. It uses PMDG SDK to send PMDG events it receives from SIOC.


Before anything else, do not forget the enable the PMDG SDK as it is by default disabled. Below is taken from the SDK.

// NOTE - add these lines to the 737NGX_Options.ini file: 


The SDK in principle has 2 sections that I’m going to explain:

  • Event definitions
  • Data structure


Initialy I had some trouble understanding the word Events here. Think of it as EVENTS seen from the PMDG software. You (you, your mouse and hardware) will cause these Events for the PMDG software to react on.

Events can be also explained as the message we need to send the PMDG NGX to do ‘commands’ like: button clicks to panel elements and other controls of the aircraft. It is also used to set data in e.g. MSP display like course, heading etc.


PMDG data are values of indicators and gauges that PMDG uses, no more no less.


The program written in C#, using  “PMDG Wrapper.dll” to connect to FSX /PMDG.

On the other end, the DataEventServer will connect to SIOC over TCP/IP. This is basicaly the same code that I also use for FSIOControl.

As the design goal of FSIO is to have ONE and only ONE place of configuration data, the SIOC script (SSI) is used to configure what data we want to get from PMDG and what events/commands we want to send to PMDG.
So the SIOC script (.SSI) has been (and will remain) the single place of configuration data.

Ofcause SIOC (script) does not have provisions for my PMDG Server. But somewhere I need to specify the relation between a PMDG variable SIOC Var. Or likewise between a PMDG Event SIOC Var.

The first idea was to use the SIOC variable name to set the relation SIOC Variable / PMDG NGX data or event.  However, the SDK event names are in most cases longer than the SIOC Variable name field allows. This would mean I had to create my own list of PMDG variable names and Event names. I tried to do this via an algorithm to automate this, but that did not work. Too bad!? No, I think the solution I use now is far better then having an other (extra) list of Data and Event names. Better stick to the original PMDG variable and event names.

I decided to use the comment field of the SIOC script line. By doning so, SIOC can be configured to receive specific data from the PMDG in a configured variable. The SIOC script then takes care of sending this date to e.g. indicators, display, relays, servos etc.

On a ‘per Event’ basis, the PMDG DataEventServer can be configured to listen to SIOC variables. When such a variable changes, SIOC will then send the Var data to PMDG Event.
On its turn the PMDG DataEventServer will trigger the specific event to FS / PMDG.

I’m going to explain this below by a few examples of SIOC script lines.

SIOC Script and the PMDG DataEventServer

I am going to show how to get the ‘Left FD indicator’ from the MCP panel into a SIOC variable and display this variable on an indicator of a IOCard.

Look at the line below:

Var 0011, name MCPLED, Link IOCARD_OUT, Device 0, Output 2   // MCP_annunFD_0

In the comment field you see: // MCP_annunFD_0

The // is an important delimiters. Right behind the //  you need to put the name of the PMDG variable you need. The spelling of this data element is (needs to be) exactly as from the PMDG SDK. When configuring the SIOC script, you can use Ctr-C and Ctr-V from the program’s display sreen to copy the exact spelling to your script.

You can put additional comment behind the as long as you leave a space.

What this will do is: tell the PMDG DataEventServer: – when the value of ‘MCP_annunFD_0’ changes – send this new value to SIOC variable 0011.

At the same time, when Var 0011 changes, SIOC will send the new value to Device 0, output 2.

This means that the indicator at output 2 will be lit if MCP_annunFD_0  == 1.

Simple, isn’t it? Just ONE line!!

An other example:

Var 0030, name CRSLEFTdisplay, Link IOCARD_DISPLAY, Device 1, Digit 0, Numbers 3 // MCP_Course_0

This will tell the PMDG DataEventServer: if the value of MCP_Course_0 changes -> sent this value to Var 0030. At the change of Var 0030 SIOC will transmit this value to the hardware and Digits 0-2 will display the Left Course.

Again! ONE LINE of SIOC script to get the Course from PMDG to your hardware display.

An example with some manipulation.

Var 0034, name VSdisplay, Link IOCARD_DISPLAY, Device 1, Digit 7, Numbers 4 // MCP_VertSpeed ,
   IF &VSdisplay = -16960
   &VSdisplay = -999999
   &VSminus = 0
       IF &VSdisplay < 0
       &VSminus = 1
       &VSminus = 0

It should be clear now that Var 0034 will receive the vertical speed from PMDG. This value cannot be sent to the display as received. Furthermore the – sign in this design is not a display but a single indicator. When we receive -16960 from PMDG this means the display is blank. SIOC for blank display is -999999. If not blank we leave the value received and set the Minus sign according the value.

Note: With this script the value of  -16960 will be send to the hardware as any change of a Var will trigger SIOC to do that. However, a few milliseconds after that the value will again change to -999999. 
There are more ways to achieve the same avoiding the extra communication of the -16960.

So now you know how to request data from PMDG into a variable of SIOC. Once in SIOC your script needs to take care of the rest. As you saw, in a number of cases this is easy and can be done within the same line where you request the Data.

PMDG SDK and broken numbers.

SIOC Vars can only be integer numbers. (SIOC can do floating calculations, but the result is always interger)
For most PMDG data this is no problem. However, some values in PMDG data are broken numbers.

e.g. MAIN_TEFlapsNeedle_0

This value is in degrees range 0 to 40. PMDGDataEventServer can only send integer numbers to to SIOC. This does not allow for all intermediate postions of the needle. To solve this I created the possibility to multilpy the value by 100 before sending to SIOC. This will result in an accuracy of 1%.
You can ask DataEventServer to send the data multiplied by 100 by putting an * behind the PMDG data mnemonic.

Var 606, name Flaps // MAIN_TEFlapsNeedle_0*

There is NO Space between the data mnemonic and the  ‘*’ !

Now when the flaps needle moves, the value from 0 to 4000 will be sent to SIOC. This should be enough to program perfect moving needle.

Sending Events

What Events allow you to do is, to send several types of mouse-clicks to control elements of the PMDG NGX cockpit. Some control elements also accept direct data.
To find out what you need to send to cause some action, think of what you would need to do with your mouse on that ellement on the screen.

Alle switches accept mouse clicks (like on the screen), but you can also set a switch direct to a certain position by sending a value to this switch.


The EFIS range switch can be turned back and forth by the appropriate mouse click, but can also directly set by a value between 0 and 6. Same for EFIS buttons. Toggle them with mous click or set direct with value 0 of 1.

Sending left- or right mouse clicks to the MCP-Course knob will increment or decrement the value of the MCP Course setting. However you can also directly set a value to the MCP Course. Witch method you chose depends on your script and hardware.

Let’s look at an example:

Var 0060, name FDswitch, Link IOCARD_SW, Input 25     // EVT_MCP_FD_SWITCH_L

The comment field of the line holds: EVT_MCP_FD_SWITCH_L . This will tell PMDG DataEventServer to monitor variable 0060. When that variable changes, PMDG DataEventServer will receive the new value and send it to PMDG event:  EVT_MCP_FD_SWITCH_L

So with this one line you connect the hardware switch directly to the PMDG switch.

The MCP FS switch can also be toggled by a mouse click but this is one example where it is better to set the value direct.

In PMDG a switch that is up has a value of 0, down a value of 1 (2,… ). So we should wire the switch on input 25 to send a 0 if up and a 1 of down. If it is wired the other way around you can use a Type X parameter to invert the value received(FSIO only)

Isn’t it simple?

On other example sending mouse events.

Var 0062, name N1bp, Link IOCARD_SW, Input 3    
     if &N1bp = 1
     &N1 = -3
     &N1 = -99
Var 0562, name N1                    // EVT_MCP_N1_SWITCH ,

The PMDG SDK allows to send all kinds of mouse events to the PMDG controls. In order to send a mouse event one needs to send a special number to the event. The list of mouse events is shown at the end of this chapter.
PMDG mouse-event-numbers are large hexadecimal numbers, not easy to program in SIOC script. PMDG DataEventServer will use negative numbers -1 to -20 to send mouse events. PMDG DataEventServer will translate these negative numbers to the right value for the Event.

Look above. On Input 1 there is a pushbutton that will send a 1 when pressed and a 0 when released. The MSP N1 button will be pushed by a mouse event. PMDG DataEventServer will monitor Var 0562.

If input 3 sends a 1 value we will set 0562 to -3. (left mouse click)

This -3 value is received by PMDG DataEventServer that will translate the -3 value into the right mouse click internal value and sent it to the N1 control button of the MCP.

Next we will also send -99 to Var 0562.
The reason is that SIOC and our software will only react on changes. Leaving the variable to -3 will prevent us from sending a subsequent mouse click. So we need to clear a variable. Clearing the Var to 0 will not work as 00 is a valid value. This would set the switch to 00 position. We use -99. Sure, that value will be picked up by the Event server, but -99 is a NOP value and will not send any value to the event. So by putting -99 in Var 0562 that Variable is ready to receive a next event/value.
The above is not the only way of programming this. One could send the -99 on release of the hardware butten when this button sends 00.

Look at this example:

Var 0116, name tstRot2, Link IOCARD_ENCODER, Input 24, Aceleration 1, Type 1
  IF &tstRot2 < 0
    &CRSRIGHT = -1   
    &CRSRIGHT = -99   
    &CRSRIGHT = -3   
    &CRSRIGHT = -99   
Var 0585, name CRSRIGHT            // EVT_MCP_COURSE_SELECTOR_R ,

Rotary encoders in my design will send a -1 or +1 value depending on the direction of turn. The rotary encoder on input 24 will send a value to Var 0116. The script lines following will send right-or left mouse clicks to the course selector knob.

This is not the only way to set the course. You can maintain your own value of the course in a variable in SIOC.

Var 0123, name CRSRIGHT    //EVT_MCP_CRS_L_SET,
Var 0116, name tstRot2, Link IOCARD_ENCODER, Input 24, Aceleration 5, Type 1
&CRSRIGHT = &CRSRIGHT + &tstRot2     

The script snippet above will directly add the value received from the encoder to the value of the variable. This looks simpler, however you would need some code to maintain the value between o and 359. This will than make it more complicated. Also, in this example the refreshrate of the PMDG data ( about 10/sec) will not be sufficient to get a smooth value change.

In the next example I will toggle the Captains WXT setting in 2 different ways.

Using mouse events to toggle the Captains WXT setting.

Var 0400, Name BT8, Link IOCARD_SW, Device 10, Input 56
    IF &BT8 = 1
    &PM211 = -3        // Left mouse click
    &PM211 = -99       // Clear to Ignore  
Var 0711, name PM211 // EVT_EFIS_CPT_WXR,

Var 400 (BT8) is connected to button input 56. Var 0400 will thus be 1 if BT8 is pushed and 0 if released. The script lines will set the mouse event to Var 0711 -> to PMDG and that will toggle the WXR setting. At the release of the button Var 0400 will be set to -99. The Var value -99 will be send to PMDG events server,  but will be ignored.

I cases like above there is no need to use mouse events as the position of the EFIS can be set directly (most of these similare buttons and swiches).
In FSIO this requires just ONE line in SIOC.

Var 0003, name BT0, Link IOCARD_SW, Device 10, Input 75, Type P   // EVT_EFIS_CPT_WPT

Variable 3 directly links to the Captains EFIS Waypoint setting in PMDG.
Variable 3 is set by button BT0 and as BT0 is of type P (every push will alternately send 0 or 1. This value is send to PMDG event server and thus set the WPT value of PMDG.

CDU Events

The PMDG SDK lists one Event for every button on the CDU. So that are about 140 events. In order to avoid having to make a lengthy script that will translate the key code received from the keyboard hardware into the right event, PMDG DataEventServer has a special feature that allows you to create a translate table that will translate the key code received from the hardware into PMDG CDU event.

PMDG DataEventServer will monitor 2 special variables where the hardware (USB KeyBoard) will set the key code of the key pressed. PMDG DataEventServer will then translate that code to the right event and send it to PMDG.

Var 0002, name CDUkeybL, Link USB_KEYS, Device 11
Var 0003, name CDUkeybR, Link USB_KEYS, Device 13

You can set the Var  to any value, I will show later how PMDG DataEventServer will know where to look for the key value.

So the SIOC script for CDU is very simple. Just one line per CDU.

When we discuss the program itself I will show how you can create and save the translate table.

Running the PMDG DataEventServer

When you start the PMDG DataEventServer for the first time it will request to specify the location of the SIOC.INI file. Navigate to that folder and click ok. The program now stores this folder location so next time it knows.

Schermafdruk 2015-06-17 17.56.31

After that you will see the main window organised as a Avionics control unit. Immediately after it starts, the program will start reading the SIOC script file. (.SSI). The program will wait for this to finish before proceding.

PMDGDataEventServer 2.01

Controlling PMDG DataEventServer.

The bottom line is the input line.

You control the program by suing the L1 – L8 and R1 – R8 pushbuttons.

With these buttons you either transfer the input line to the line value or you toggle the adjacent value,

L1 is to set the IP address of the PC where SIOC runs. (location of the SIOC.INI file)
The default ip adress is ‘local host’. But you can change the IP to any address by putting the IP in  the right format on the input line and then transfer that value with the L1 key. The IP address is then stored in the programs settings store.

Note here: PMDGDataEventServer needs to run on the same PC as FSX/PMDG. SIOC does not in some setups (using FSWide). Make sure the program can access the current SIOC.ini and .SSI file.

R1 The port number is taken from the SIOC.INI file. So no need to change.

L2 and R2 are to set the value of the left- and right CDU keyboard variable. These are the variables that PMDGDataEventServer will monitor for CDU keyboard codes.

L3, L4 and L5 will toggle the adjacent auto-connect parameters. If set ON, the program will automatically connect to FSX and or SIOC. This setting is maintained in the program settings. So the next start it will try to connect automaticaly.

When everything (your script) is stable you would set L3 – L5 to ON. This way you can start and forget.

R3, R4 and R5 will perform (manual) immediate (dis)connection to FSX, SIOC or hide.

If the program is Hidden, you will find an icon in your tray. Double click to reopen the window.

R6 will bring up the CDU translate table. You can edit the table by specifying the keyboard hardware code to the right key event. See below for how to create the translate table.

L6 will click to one of 3 positions.
The first position is the control window as you see it after start-up of the program.

2nd Postion:
When clicked once the window will extend to the right and show the PMDG DATA table.
The screendump shows the PMDGDataEventServer with the Data window open on top of FSX/PMDG.

PMDG DataEventServer Data Window

Here all PMDG variables are listed by there PMDG-SDK name.

The Index Column is the program internal index number. This column will removed in later releases.

When the PMDGDataEventServer has read the SIOC script (.SSI) it will connect (automatically or manually) to FSX and start reading all Variables and display them in the column ‘Value’.
Note: The first time you open this window it will take a few seconds before the first data appears. After that the table is updated 4/sec.
As you can see, the values of MCP course, IAS, HDG, ALT etc are all present. You can move the table up/down to view al variables.

The next column [ SIOC ] list the SIOC Var number that this PMDG data value is assigned to. So PMSGDataEventServer will send MCP_Course_0 to SIOC Var 13 if that value changes. With this window you can both verify correct reading of the PMDG variables and verify the if the correct variable is assigned to the correct event.

When writing you script, refer to this window for the correct spelling of the PMDG Data Variable. Highlight the DataName, Ctr-C and then go to your script and Crt-V (paste it) in the script.

3rd Position:

If you click L6 a second time, you will see the PMDG Events.

PMDG DataEventServer Events open

  • SIOC
  • Value

The first field list the SIOC variable this event is connected to. So here you can see if your script is correctly pointing to the right event.

Same here, to build your script Copy-paste the Event Name to your script. (btw: You do not need FSX of SIOC running for that).

The [Value] field allows you to test send an event to PMDG.

Set a value in the Value field of an event. Rtrn will leave and set the field. Now click on the value. The value will now be send to PMDG. This way you can test the events, eventualy  find out witch mouse click is best etc.


In order to use the TCP/IP interface of the PMDGDataEventServer you need to start it by entering a port number here. I suggest using 8094. See below for more details about CDU screen data.


If you want to change the SIOC directory you can copy the current directory by pushing the [L7] key to the input line. Change the directory name and push [L7] again. This will completely reinitialize the program.
This can also be used after you changes the SIOC script. By pushing [L7] twice. The directory if SIOC will be the same, but the program re-initializes.

Logging Window

PMDGDateEventServer has a logging facility where you can see what values are transferred between SIOC and the program and see what events are fired to PMDF.

You open the log Window by pulling the main window to the left yourself. Of the logging

SPECIAL CDU variable

As mentioned before, you can assign special variables (SIOC Var for left CDU and right CDU).

A value that your script places in this variable will be interpreted as an index to the key list of the PMDG left or right CDU.

Your keyboard hardware will send some code if you press a key. You will have to map this key value to the right PMDG event. You could do this by making a SIOC script with about 70 ‘if’ statements. The PMDG EVENT SERVER has a build-in “hardware-key-value” to “PMDG event” translation table.

The picture below shows the table open:

.Schermafdruk 2015-03-15 14.59.02

You can open this table by pushing the R6 key.

This are just some test numbers. In the picture: if the keyboard hardware sends a value of 22 to Variable 2, the Left CDU L1 key will be pressed. A value of 34 will press the L2 key. In this way you build your translate table, save it.

The same table is used by the right CDU. So a if the hardware sends a value of 22 to Variable 3, the right CDU L1 key will be pressed.

You need to fill this table yourself, do not forget to save!!

So now you can configure the CDU keyboard in SIOC with one line:

Var 0002, name CDUkeybL, Link USB_KEYS, Device 11
Var 0003, name CDUkeybR, Link USB_KEYS, Device 13

That’s all!!


This will open a rudimentary CDU check screen below. This is not a corretly formatted screen, just bare data as a check.

Note to using PMDG Mouse events.

If you set a SIOC variable to a mouse event value, that value will be sent to the PMDG. For SIOC to send a next value the variable needs to change. So inbetween 2 mouse events the variable needs to be cleared. Clearing to 0 will send a 0 to the event. In most cases this will result in setting the function at hand to 0, basicaly whiping out the effect of the mouse event. PMDG EVENTS SERVER will ignore alle values < -20, so if you clear the variable to e.g. -99 this will do nothing and the next mouse event can be sent.

Control Values (Mouse Flag Codes)

-15  MOUSE_FLAG_WHEEL_FLIP     // invert direction of mouse wheel
-16  MOUSE_FLAG_WHEEL_SKIP    // look at next 2 rect for mouse wheel commands

Network Interface

The Software Development Kit from revision 1.1 (SP1D) of PMDG NGX included CDU screen data. I do not see it feasible to allow SIOC to request this screen data as SIOC could not really handle it and I cannot think of a SIOC connected CDU screen either.

That is why I added a TCP/IP server interface.
This allows connection to PMDG Data and Event using hardware with Network connection. This hardware then bypasses SIOC. Think of using an ESP8266 (WiFi) or Raspberry Pi or….

NOTE:  ALL PMDG data and events are accessible through this interface!  With TCP/IP based hardware you do not need SIOC per sé.

As I do not want to write the same thing twice the explanation about how to access the TCP/IP interface is here: scroll down to “TCP/IP Interface” on this page,

PMDGDataEventServer 2.01

Starting the TCP/IP interface

When you start the PMDGDataEventServer for the first time the TCP/IP server interface is not started. If you do not use it leave it off.

In order to get the TCP/IP interface started you need to specify a port number. I suggest to use 8094.

Enter 8094 in the input line and press L7. The port number will be set. You need to restart the program. As of now the TCP/IP interface will start and listen for clients to connect to port 8094.

In the picture above, look at the line next to L7. Here you see that the TCP/IP server is running (because the port number is specified) and there are 2 clients (0 and 1) connected.


Until now, if we wanted to make a CDU, we had to use a LCD  panel connected as a screen to our graphics card. This was the only way to get a decent CDU screen. If you cannot, or do not want this, people have come up with screen capture programs. For all these solutions the CDU had to be displayed one way or the other on one of your screens,

One of the major additions to the SKD is that PMDG made the CDU screen content available. This allows us to build a CDU and build the screen on external hardware. I could imagine to implement a CDU on i-Pad, of a Android pad. But also a screen driven from Arduino, Raspberry or system alike.

I created a Virtual CDU that connects as a client to the PMDGDataEventServer over TCP/IP. This allows you to offload the CDU screens to an other computer in your network.

Read about the Virtual CDU and CDUScreen here,


All software and firmware that I talk about on this site can be downloaded (free). You will find download links on my forum about FSIO . Each first item of a forum will hold the appropriate dowload link. The forum is members only, so you need to register.The good thing, it’s free. I just want you to enjoy and drop me a line if you do.


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s