This is how you get data from X-Plane or send data to X-Plane to use for whatever purposes you like,
including running custom cockpits, motion platforms, or anything else you can think of.

••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••

First things first: You can write a PLUG-IN to get data from X-Plane. This is a small little program that you write yourself that you drop into the PLUGINS folder of X-Plane that will then run whenever you run X-Plane. You can make it read 'data-refs', which are various variables inside X-Plane. With that information, you can make your program draw graphics, send data over a network or serial port, or anything else you want to code! Learn all about plug-ins here: http://www.xsquawkbox.net/xpsdk/phpwiki/index.php

Another way to get data from X-Plane is to go to the SETTINGS menu, and then to the DATA OUTPUT screen. From there, you can output various data to the screen for observation during flight, to a graphical display for observation in X-Plane right AFTER your flight, to the disk for perusal as a text file or spreadsheet, or to an ethernet cable as explained below.

So, there are a number of ways to get data from X-Plane, and there are all sorts of variables you can get... for the most difficult one (sending data to an ethernet cable) read on!

••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
Setting up the X-Plane network:

Hook up the computer that you are going to use to drive your special hardware or run your special software to the computer running X-Plane by a simple 100-base-t ethernet cable. If you are hooking up only a single machine directly to the X-Plane machine, then you have to use a CROSSOVER ethernet cable for the machines to talk to each other. If you are hooking up to a switch or router which can have plenty of machines all hooked up at once, then you should use a REGULAR ethernet cable to hook each machine to the switch. Windows users may need to buy ethernet cards for each machine. Macs come with ethernet support out of the box.

Now that you have the machines hooked together, go to the Data Input & Output screen in the Settings menu of the copy of X-Plane running on each computer. Select either of the Internet tabs. Using the settings in these windows, you can get your copies of X-Plane networked in all sorts of ways. To ouput data for your own strange needs, the Data Output tab will send data out via ethernet... the left-most button is to go out via UDP, and you enter the IP address to go out to in one of the Internet tabs.

NOTE: X-PLANE ALWAYS RECEIVES ON PORT 49000.

NOTE: GO TO THE SETTINGS MENU, OPTIONS AND WARNINGS SCREEN, AND TURN ON THE "OUTPUT NET-ERROR FILE" (or similar) to have X-Plane dump the data that it is being given to the error.out file. This will slow down the sim a little, and take up some drive space, but you can leave it on for a little while as you get started, so that if your dtata transfer does NOT work, you can quit X-Plane, open the error.out file with a text editor, and see what (if any) error messages X-Plane is giving you.

••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
The UDP-Message Overview:

So you want to know how to read the data that X-Plane spits out?
No problem... You send data to X-Plane and get it out by sending messages by UDP.
And here are the data formats for getting data in and out of X-Plane, which we are happy for you to do, to suit your own dark agendas.

You will see some variable types that are defined internally to X-Plane, and here they are:

XCHR (character, in local byte-order for the machine you are on)
XINT (4-byte int, in local byte-order for the machine you are on)
XFLT (4-byte ints and floats, in local byte-order for the machine you are on)
XDOB (double-precision float, in local byte-order for the machine you are on)
strDIM is 500
vehDIM is 10

You may notice that we often pass around STRINGS TO REPRESENT NUMBERS, like the null-termed string "123" to represent the number 123.
This is simply to avoid having to do byte-order conversion.
Any time you send or receive a structure, the struct alignment must be 4 bytes!

All the UDP messages have the same format, which is:

5-character MESSAGE PROLOUGE (to indicate the type of message)

and then a

DATA INPUT STRUCTURE (containing the message data that you want to send or receive)

••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
The UDP-Message Prolouge:

So what is the 5-char message prolouge? Easy!

The first 4 chars are the message type,
the 5th char is internal-use INDEX-BYTE for X-Plane (you can enter 0 here when sending data),

SAMPLE CODE TO SEND A MESSAGE:

xchr data_send[net_SIZE_buff];

void NET_send(xchr label[5],xchr* data_in,xint data_len,xint ip_index_to)
{
data_send[0]=label[0];
data_send[1]=label[1];
data_send[2]=label[2];
data_send[3]=label[3];
data_send[4]=0;
memcpy(&data_send[5],data_in,data_len); // load in the data
data_len+=5;

#if APL
TUnitData unitdata;
unitdata.addr.len =sizeof(struct InetAddress);
unitdata.addr.buf =(UInt8*)&their_address[ip_index_to];
unitdata.opt.len =0;
unitdata.opt.buf =0;
unitdata.udata.len=data_len;
unitdata.udata.buf=(UInt8*)data_send;
OSStatus retval =my_ep->SndUData(&unitdata);
xint send_failed =(retval!=kOTNoError);
#endif
#if IBM
SOCKADDR_IN addr_otherguy;
memset(&addr_otherguy,0,sizeof(addr_otherguy));
addr_otherguy.sin_family =AF_INET;
addr_otherguy.sin_port =htons(str_to_int(net.their_port_str[ip_index_to]));
addr_otherguy.sin_addr.s_addr=their_address[ip_index_to];
xint send_failed=(sendto(my_socket,data_send,data_len,0,(LPSOCKADDR)&addr_otherguy,sizeof(struct sockaddr))!=data_len);
#endif
#if LIN
struct sockaddr_in addr_otherguy;
memset(&addr_otherguy,0,sizeof(addr_otherguy));
addr_otherguy.sin_family =AF_INET;
addr_otherguy.sin_port =htons(str_to_int(net.their_port_str[ip_index_to]));
addr_otherguy.sin_addr.s_addr =their_address[ip_index_to];
xint send_failed=(sendto(my_socket,data_send,data_len,0,(const struct sockaddr*)&addr_otherguy,sizeof(struct sockaddr_in))!=data_len);
#endif
}

••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
The Data Input Structures:

So here are various DATA INPUT STRUCTURE formats you can send and receive right after the 5-char MESSAGE PROLOUGE, each identified by the first 4 chars mentioned above as the message type:

DATA

Go to the Data Input & Output screen in the Settings menu, Data tab. You can output all manner of data there! All the data you select for internet output will now go to the IP address and port you entered the Internet tab over the ethernet cable. While this could be any IP address on the net, you are most likely to be going to a computer on your own LAN. For each data selection that you make in the Data Output screen, X-Plane will send a little packet over the ethernet cable many times per second. (if you send data to another copy of X-Plane, be sure you check it's DATA RECIEVER option in the Internet tab in this same window) Here is what the "packet" or "structure" looks like for each data selection:

DATA INPUT STRUCTURE is the following stuct

struct data_struct
{
int index; // data index, the index into the list of variables you can output from the Data Output screen in X-Plane.
float data[8]; // the up to 8 numbers you see in the data output screen associated with that selection.. many outputs do not use all 8, though.
};

Now, if you have 10 data output selections, then there will be 10 of these structures sent in one big blob of data every few frames or so. NOW HERE IS AN INTERESTING TIP: YOU CAN ALSO SEND DATA PACKETS RIGHT BACK TO X-PLANE! So, for example, to enter radios or control deflections by UDP, simply send the DATA message described above TO X-Plane by UDP, and X-Plane will use those messages for input and control of the sim! You may send joystick deflections to fly the plane with your own hardware, or send in any number of other variables selectable in the data output screen... whatever can come out, you can send right back in with an identical message but the values of the number changed! Easy!

SEND A -999 FOR ANY VARIABLE IN THE SELECTION LIST THAT YOU JUST WANT TO LEAVE ALONE, OR RETRUN TO DEFAULT CONTROL IN THE SIMULATOR RATHER THAN UDP OVER-RIDE.

DSEL/USEL/DCOC/UCOC

DATA INPUT STRUCTURE is any series of XINTs

Now, say that you are writing an add-on or something for X-Plane and you want your motion-platform or cockpit to send in a request to X-Plane to send a bunch of data out like this, because you are getting tired of going into the data output screen and making selections of data to output all the time. In that case you will SEND a packet just like the one above to X-Plane, but the label will be "DSEL". The data will be a series of integers indicating which data output you want! (1 for the first in the list, 2 for the second, etc).

So "DSEL0456" would request that X-Plane send the fourth, fifth, and sixth items in the data output screen many times per second to the IP address listed in the Internet Settings screen. DSEL is in characters, but 4 5 6 are YOUR MACHINE-BYTE-ORDER integers.

Use DSEL to select data to send via UDP output.

Use USEL to UN-select data to send via UDP output.

Use DCOC to select data to the COCKPIT rather than UDP output.

Use UCOC to UN-select data to the COCKPIT rather than UDP output.

MOUS
DATA INPUT STRUCTURE is an 8-char string

Simulates a mouse-click, where thedata will be a text string indicating where to act like a MOUSE-CLICK has occurred. This is useful to control any number of instruments on the panel... Just enter the location where you would like the mouse clicked in the blank above, and X-Plane will pretend you have just clicked the mouse there! The location will simply be an 8-character-long string, where the first 4 digits are the x value (0 at the left) and the second 4 digits are the are the y value (0 at bottom).

CHAR

DATA INPUT STRUCTURE is a char

You can send this UDP message to X-Plane to act as a keypress. This opens up a lot of possibilities! Menu Selections, landing gear and other equipment... anything that has a keypress you can do simply by sending in that key after the IP address string.

MENU
DATA INPUT STRUCTURE:

The data part of this message is simply a menu item number you wish to select in string form.
See the Resources/Menus/English/X-Plane.txt file to see the number of each menu item.

SOUN
DATA INPUT STRUCTURE:

struct soun_struct{ // play any sound
xflt freq,vol; xchr path[strDIM];};

Use this to simply play a WAV-file sound. Enter the path of the WAV file in the struct. The freq and volume scale 0.0 to 1.0. Easy!

DREF
SET DATAREF STRUCTURE:

struct dref_struct{
xflt var; xchr dref_path[strDIM];};

Use this to set ANY data-ref by UDP! With this power, you can send in any floating-point value to any data-ref in the entire sim! Just look up the datarefs at http://www.xsquawkbox.net/. Easy!

FAIL
DATA INPUT STRUCTURE:

Fail a system, where the data will indicate which system to fail. The system to fail is sent as an ASCI STRING (ie: "145"), where the 0 is the first failure listed in the failure window in X-Plane (currently the vacuum system) and incremented by 1 from there.

RECO
DATA INPUT STRUCTURE:

Recover a system, where the data will be an integer indicating which system to recover. The system to recover is sent as an ASCI STRING (ie: "145"), where the 0 is the first failure listed in the failure window in X-Plane (currently the vacuum system) and incremented by 1 from there.

PAPT

Use this to place the aircraft at an airport. Just use the PAPT message with the following struct filled in:

DATA INPUT STRUCTURE:

struct papt_struct
{
xchr apt_ID[5] ; // ID to go to, null-termed
xint type_start ; // 601 for takeoff, 602 for final approach, 603 for far-away final approach
xint lcl_rwy_ram; // which runway or ramp-start location to use, starting at 0 for each airport
xint backwards ; // 0 or 1, depending on if you want to appraoch from the other direction
};

VEHN
DATA INPUT STRUCTURE:

struct vehN_struct{
xint p;
xchr path_rel[150];
xchr att_file[24][40];};

NOTE: FOR THIS MESSAGE, YOU MUST ENTER 17 AS THE VALUE RIGHT AFTER THE 4-CHAR LABEL.

Use this to load a vehicle (an airplane). Just enter wich plane to load as 'p', and the path of the plane as the path. Send this in and X-Plane will load this plane. Send in 1->19 to load the other planes! The path clearly cannot exceed 150 chars! As well, you can specify up to 24 WEAPONS attached to the airplane, each weapon name being up to 40 chars long. This is nice to arm planes as you like for multi-player fun... of course just leave these blank to have no weapons.

VEH1/VEHA

You can send the VEH1 "ONE-VEHICLE" UDP to move an airplane wherever you like. This way, you can easily have X-Plane do the graphics for your own flight model, whatever that flight model may be! It is really easy... just fill in a structure with the small amount of data needed to indicate the craft's location and orientation and send it in!

DATA INPUT STRUCTURE:

struct VEH1_struct // byte-align 4
{
xint p; // this is the plane you wish to control.. 0 for your plane, but you can enter up to 9 here
xdob lat_lon_ele[3];
xflt psi_the_phi[3];
xflt gear_flap_vect[3];
}

Here is what those array are:

DOUBLE-PRECISION FLOAT array of dimension 3, with the latitude, longitude, and elevation of the aircraft. The elevation of the plane is in meters above sea-level.

SINGLE-PRECISION FLOAT array of dimension 3, with the heading, pitch, and roll, all in degrees, positive up and right.

Gear, flap, and thrust-vectors... single-precision floats, all RATIOS 0->1,

When you set one plane's location at a time, planes tend to "jiggle" a bit with respect to each other since their locations come in at different times. To avoid this annoyance, use the ALLP message. It is exactly like the ONEP message, except that lat, lon, elevation, the, psi, and phi are each dimmed 10 (index 0 to 9) and the index that you send in is the NUMBER OF PLANES that you want to control. Send in an index of 5, for example, to control planes with indices 0 through 4. Easy! As well, we snuck a little tidbit in the struct for you: the pilots VIWPOINT location. Send in ZERO for these if you are happy with X-Plane's default viewing locations, or the lat, lon, elevation, theta, psi, and phi if not. Here is the total structure you must send in, entering ZERO for unused params:

Or, with the VEHA message, control the locations of MORE THAN ONE PLANE at a time.

struct vehA_struct
{
xint num_p;

xdob lat_lon_ele[vehDIM][3];
xflt psi_the_phi[vehDIM][3];
xflt gear_flap_vect[vehDIM][3];

xdob lat_view,lon_view,ele_view;
xflt psi_view,the_view,phi_view
};

Where vehDIM is 10, send in any number p from 1 to 10 to control how many planes you want to set, and send in a non-zero value for the view locations if you want to control the viewpoint location as well.

OBJN
DATA INPUT STRUCTURE:

struct objN_struct{ // object name: draw any object in the world in the sim
xint index;
xchr path[strDIM];};

Just like the airplane struct, but with any OBJ7 object (see the San Bernardino "KSBD_example.obj" sample object in the Custom Scenery folder for an example of an OBJ7 object. With this message, simply send in the path of any object that you have on the drive and you want X-Plane to display! The location is controlled with the struct below.

OBJL
DATA INPUT STRUCTURE:

struct objL_struct{ // object location: draw any object in the world in the sim
xint index;
xdob lat_lon_ele[3];
xflt psi_the_phi[3];
xint on_ground; // is this object on the ground? if so, simply enter 0 for the elevation, x-plane will put it on the ground
xflt smoke_size;}; // is this object smoking? if so, simply indicate the size of the smoke puffs here

Enter the location of the object you loaded here. It can be a tank driving around on the ground, a missile firing, or anythng else you can imagine.

GSET

This allows you to set up graphics options for X-Plane without touching it. This is useful if you have a simulator with many displays, and do not want to manually set the texture res, offsets, etc, for each copy of X-Plane.

DATA INPUT STRUCTURE:

struct gset_struct{xint index;xflt change_it_to;};

The index indicates what you want to change, the change_it_to indicates... oh you can guess.

0->tex_res
1->x_res_req
2->y_res_req
3->col_res_req
4->set_res_req
5->num_acf
6->render detail
7->object level
8->road level
9->draw_boats
10->draw_birds
11->draw_fires
12->draw_texlites
13->draw_shadows
14->draw_gload
15->off_lat_deg
16->off_lat_rat
17->off_vrt_deg
18->off_vrt_rat
19->FOV
20->vert1
21->vert2

ISET

This allows you to set up internet options for X-Plane without touching it. This is useful if you have a simulator with many displays, and do not want to manually set the IP options for each copy of X-Plane. Simply send this structure:

DATA INPUT STRUCTURE:

struct iset_struct{
xint index; // (0->20 in the lsit below)
xchr str_ipad_them[16]; // IP's we are sending to, in english
xchr str_port_them[6]; // ports are easier to work with in STRINGS!
xint use_ip ;}; // to use this option, 0 not to.

IP of multiplayer1=0
IP of multiplayer19=18

IP of master this is exteranl viewpoint=27
IP of master this is cockpit=28
IP of master this is external any=29
IP of master this is IOS=30
IP of IOS=50
IP of data receiver=52

BOAT
DATA INPUT STRUCTURE is a 12-char string

This command is simply a 12-character long string to steer a boat around. (Aircraft carrier, frigate, sailboat, whatever).

It might look like this: "000275010"

That means take boat index 000 (the carrier) turn it to heading 275 degrees true, and run it along at 10 meters per second.

The frigate is index 1, and the sailboats are currently indices 2->12.

Send in the new command data whenever you like... every frame or once per hour... I don't care. Easy as heck!