••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
THIS DOCUMENT
••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••

This document will tell you how to get data from or send data to X-Plane!
Use this data for whatever purposes you like, including running custom cockpits, motion platforms, or anything else you can think of.
I made X-Plane to be used, so you should use these messages to drive it, or listen to it, in any way you can imagine, without restriction.
This document shows how to send data to and from X-Plane by UDP messages over ethernet cable or WIFI,
but you can also google “plugins for X-Plane” to write a plugin to actually RUN INSIDE X-PLANE ITSELF, giving much faster control of X-Plane variables…
but you have to learn how to write a plugin to do that. With the UDP messages described in this document,
you don’t have to learn much at all if you already know how to send and receive UDP messages from your App.

••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
PROLOUGE
••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••

You will send and receive various structs by UDP to talk to and listen to X-Plane, so you need to declare some structs in your code.
The byte-alignment of your structs must match the current Intel 64-bit X-Code alignment (because that is what we use, on Mac anyway).
This alignment is to the nearest 4 bytes if the struct contains INTS or FLOATS, and the nearest 8 bytes if the struct has DOUBLES!
So, even an INT will take 8 bytes of space in the struct if there is only one of them, and the struct contains DOUBLES!
Basically, there is padding in between the smaller variables to make them fall to the next-available 4-byte or 8-byte bound,
depending on whether or not the struct has doubles in it.

Sometimes people with different compilers and compiler settings and languages do not have that padding inserted, and the message is therefore the wrong size.
To see if this is happening to you, run X-Plane, go to the SETTINGS menu, OPERATIONS AND WARNINGS screen,
turn on the DUMP NET DATA TO LOG.TXT, and then send your messages.
Then exit X-Plane and open the log.txt file to see what size structs X-Plane expected, versus what you sent.
Add padding as needed as explained above.
The best thing about standards is that there are so many of them.

••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
JUST LET ME GET OUTPUT BY UDP TO DRIVE A VISUAL OR MAP: RPOS
••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••

This doc will go into lots of detail of all the ways to get data to and from X-Plane:

1: by plugins (an App you can write that runs on the same computer as X-Plane, reading and writing data as desired) and
2: by UDP (to and from any program running on any computer in the world that can send data by UDP to and from X-Plane).

BUT, the thing that the vast majority of people seem to want is simple: A UDP output from X-Plane to drive their own visuals or moving map!

So, while the document below will show you how to read and write all the various variables in X-Plane by plugin or UDP, we made a way to have X-Plane
just output the data you need to drive an external visual or moving map to any IP address and port number by UDP.
From your App that NEEDS the map and attitude data, simply send the 5-char message:

“RPOS” (null-terminated!), and then this struct:

struct rpos_struct_in
{
	xint rpos_freq;
};

rpos_freq IS ACTUALLY THE NUMBER OF TIMES PER SECOND YOU WANT X-PLANE TO SEND THIS DATA! ENTER 0 TO NOT SEND IT AT ALL!) to X-Plane by UDP, sending to port 49000.

Now, each frame, X-Plane will send the minimum data needed to drive an external visual or moving map to the same IP address and port number you sent this message from! Easy!
This will simply be the 5 chars “RPOS” (plus a NULL at the end!) followed by a struct as follows: (machine-native floats and doubles, 4-byte struct alignment)

struct position_struct
{
	double longitude,latitude;				// double is needed for smooth data here. this is good for simple 2-d maps
	float elevation_MSL,elevation_AGL;		// we have AGL so you can correct the heigh above ground for your visuals to match X-Plane, if desired
	float pitch,heading,roll;				// this is for making your own visuals
	float Vx,Vy,Vz;						// Vxyz are the speeds in the east, up, and south directions, in meters per second. you can use these to predict longitude, latitude, and elevation smoothly.
	float Pdeg,Qdeg,Rdeg;				// P Q R are the roll, pitch, and yaw rates, in aircraft axis, in degrees per second. you can use these to predict pitch, heading, and roll smoothly.
}

So, this is very simple, but will let you drive moving maps and external visuals, which is the most commonly used output from X-Plane!
Obviously, it is up to you to find the ground track, ground speed, climb angle, total speed, etc, based on the Vx, Vy, and Vz.

NOW, if you want MORE stuff from X-Plane than this, or you want to CONTROL stuff in X-Plane, then read on!
You will see how to read and write every variable that X-Plane makes available, by either plugin (on the same machine as X-Plane) or UDP (run on any program, in any language, on any machine, you can imagine).

••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
PLUGINS
••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••

First things first: To get the maximum control right from the start, you can write a PLUG-IN to get data to and from X-Plane.
A plugin is a small program that you write yourself and drop into the PLUGINS folder in your X-Plane folder.
This little plugin is a program that will run whenever you run X-Plane.
You can make your plugin read and write things called ‘datarefs', which are various variables inside X-Plane.
With that plugin, you can also make your program draw graphics, send data over a network or serial port, or anything else you can imagine!
Learn all about plug-ins here:
	http://www.xsquawkbox.net/xpsdk/phpwiki/index.php

••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
DATA AND NET CONNECTION SCREENS
••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••

So you can write a plugin to read and write data from X-Plane.
But there are other ways to send and receive data from X-Plane as well.

In X-Plane, go to the SETTINGS menu, DATA INPUT AND OUTPUT screen.
From there, you can output various data to observe in flight.
The FIRST button by each label goes to the screen for observation during flight.
The SECOND, to a graphical display for observation in X-Plane right AFTER your flight.
The THIRD, to the disk for perusal after the flight as a text file or spreadsheet.
The FOURTH, to an IP address of your choice, for data-reception on some other computer!

So, there are a number of ways to get data to and from X-Plane!

Let’s look at that fourth button a little more: Sending data to an IP address.

Hook up the computer running your App that wants to receive data from X-Plane to the computer running X-Plane by ethernet or WIFI connection.

Now that the machine running your App and the machine running X-Plane are on the same Local Area Network, launch X-Plane.
Go to the  SETTINGS menu, DATA INPUT AND OUTPUT screen.
Check the FOURTH button by any label to send that data to the IP address of the computer running your App.

Now, go to the NET CONNECTIONS window, then the DATA tab.
Check the box for “IP of data receiver” and enter the IP address of the computer running your App, and the port as well.
Now, when flying, X-Plane will send the data you have selected in the Date Output Screen to the IP address and port you entered in the NET CONNECTIONS window!
Receive this data in your App and do with it as you like.

••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
UDP MESSAGES TO X-PLANE
••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••

So now you have seen Plugins to get data to and from X-Plane, and the Data and Net Connections screens to get data from X-Plane… what about sending data TO X-Plane by UDP?

You can send various different UDP messages TO X-Plane as well, and here are the rules for that:

NOTE: X-Plane always receives on port 49000.
NOTE: Any strings that you send should be null-terminated!
NOTE: Any time you send or receive a structure, the struct alignment must be 4 bytes, or 8 bytes if the struct has any doubles in it!
NOTE: GO TO THE SETTINGS MENU, OPERATIONS AND WARNINGS SCREEN, AND TURN ON THE “dump net data to log.txt” button to have X-Plane dump log data to the file error.out.
This will slow down the sim a little, but you can leave it on for a little while as you get started, so that if your data 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!

Below, 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 20

You may notice that we sometimes pass around STRINGS TO REPRESENT NUMBERS, like the null-termed string "123" to represent the number 123.
This is simply to avoid byte-order conversion head-aches.

So, now you see some notes about the port to send to, the need to null-term your strings, the struct alignment, and variable names and dimensions that we use.
Now you need to know what the format is to send messages to X-Plane by UDP!
All of the UDP messages have the same format, which is:

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

and then a

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

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

The first 4 chars are the message type,
the 5th char is a byte of value zero, to null-term the label,
and after that comes the data to send!

So, to send a UDP message to X-Plane, just send:
-the 4-letter label
-a byte of value ‘0’
-the message data you want to send

••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
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;							// we send in the data plus the 4-letter label and the 0 at the end of the label, so we add 5 chars to the length to send!

	#if MACINTOSH
		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 WINDOWS 
		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 LINUX
		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
}

••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
DISCOVER X-PLANE BY A BEACON
••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••

In order to send and receive UDP messages to talk to X-Plane, you must know the IP-address of that machine within your network. You can either enter the IP-address manually, or you can use the BEACON that each instance of X-Plane running in your network broadcasts to announce its presence. 

The BEACON message uses a mechanism called multicast, which is a special IP-address range that you can subscribe to in order to get announcements from X-Plane. 

In order to subscribe to X-Plane's BEACON, you must join the multicast group 239.255.1.1 and listen on port 49001. While this looks like an IP-address that is not in your network, it is really a group identifier. Consult your operating system's documentation on how to join a multicast group with a UDP socket. You will want to read the documentation of the setsockopt() function and the IP_ADD_MEMBERSHIP parameter.

Once you are receiving the BEACON messages from X-Plane, the struct must be interpreted as follows:

5-character MESSAGE PROLOGUE which indicates the type of the following struct as
BECN\0

struct becn_struct
{
	uchar beacon_major_version;		// 1 at the time of X-Plane 10.40
	uchar beacon_minor_version;		// 1 at the time of X-Plane 10.40
	xint application_host_id;			// 1 for X-Plane, 2 for PlaneMaker
	xint version_number;			// 104014 for X-Plane 10.40b14
	uint role;						// 1 for master, 2 for extern visual, 3 for IOS
	ushort port;					// port number X-Plane is listening on
	xchr	computer_name[strDIM];		// the hostname of the computer 
};

Parsing this struct allows you to find any instance of X-Plane running in the network, find out which version of X-Plane is running, see the name of the computer and find out whether it's configured as a master or visual slave machine, and lastly find out if X-Plane's receive port has been changed from the default of 49000.

You can expect the struct to be compatible within the same major version of the BEACON. Expect structs to change when the major version changes, so you will want to abort parsing when you discover a mismatch of the beacon_major_version.

••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
THE MESSAGES YOU CAN SEND
••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••

So now you see how to send messages to X-Plane… your final question is: What are the messages I can send?

Well, I will tell you now!

Following are various DATA STRUCTURES that you can send (right after the 5-char MESSAGE PROLOGUE, each being 4 chars (plus a zero byte) as mentioned above):

••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
SET 1 OR ALL AIRCRAFT LOCATIONS: VEH1/VEHA (SET ONE AIRCRAFT LOCATION TO DRIVE X-PLANE AS A VISUAL SYSTEM!)
••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••

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!

So you would send in VEH1, a null to term that, and then the struct below, all on one message, with net data logging turned on in the Operations and Warnings window if you like to have X-Plane log any errors it gets in understanding the data it is getting from you…
using 8-byte struct align since this struct has doubles, and in intel byte-order. Whew!

struct veh1_struct
{
	p_index p;
	xdob lat_lon_ele	[3];
	xflt psi_the_phi		[3];
	xflt gear_flap_vect	[3];
};

Here is what those arrays 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,

Now, 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 VEHA message. It is exactly like the VEH1 message, except that lat, lon, elevation, the, psi, and phi are each dimmed 20 (index 0 to 19) to control ALL the airplanes, and num_p is the NUMBER OF PLANES that you want to control.
Send in num_p 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 VIEWPOINT location and angle.
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
{
	p_index 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 20, send in any number p from 1 to 20 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.

••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
SEND ME ALL THE DATAREFS I WANT: RREF
••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••

So this one is cool: Send in the 5 chars RREF (null-terminated!) plus this struct:

struct dref_struct_in
{
	xint dref_freq		;
	xint dref_en		;
	xchr dref_string[400]	;
};

Where dref_freq IS ACTUALLY THE NUMBER OF TIMES PER SECOND YOU WANT X-PLANE TO SEND THIS DATA!
Where dref_en is the integer code you want X-Plane to send back with the dataref value so you can tell WHICH dataref X-Plane is giving you! (since you are likely to ask for MANY different datarefs!)
Where dref_string is the dataref string that you want X-Plane to send to you!

And, if the dataref is to an ARRAY of values (like engine thrust, since there can be 8 engines), just add [xxx] to the end, where “xxx” is the array index you want X-Plane to send!
The [ and ] should simply surround the number to indicate that the number is the index you want.
So, send in “sim/flightmodel/engine/POINT_thrust[1] “to have X-Plane send the second engine, for example (since we start at 0!)

X-Plane will send the message right back to the IP address and port number you sent the RREF command from.
You will get:

struct dref_struct_out
{
	xint dref_en	;
	xflt dref_flt	;
};

Where dref_en is the integer code you sent in for this dataref in the struct above.
Where dref_flt is the dataref value, in machine-native floating-point value, even for ints!

So, of course, you can send in all the RREF messages you want, to get all the dataref values back that you want!
Easy!

Send in a “dref_freq” of 0 to stop having X-Pane send the dataref values.

••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
SET A DATAREF TO A VALUE: DREF
••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••

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!

IMPORTANT: NULL TERMINATION MEANS THE NULL CHARACTER MUST BE PLACED AT THE END OF dref_path THEN SHOULD BE FILLED WITH BLANK
SO YOUR TYPICAL MESSAGE SHOULD LOOK LIKE THIS

DREF0+(4byte byte value)+dref_path+0+spaces to complete the whole message to 509 bytes

AN EXAMPLE TO TURN ON AN ANTI-ICE SWITCH WOULD BE

DREF0+(4byte byte value of 1)+ sim/cockpit/switches/anti_ice_surf_heat_left+0+spaces to complete to 509 bytes

DO NOT ADD ANY + SIGNS. THIS IS JUST TO SHOW THE PARTS OF THE MESSAGE TO BE ADDED AS ONE SINGLE BLOCK

REMEMBER: You can go to the SETTINGS menu, OPERATIONS AND WARNING window, to turn on a diganostics option that will output what data X-Plane thinks it is getting from you to a log file!
Turn this on during development to see what X-Plane THINKS it is getting from you!

••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
SET A DATA OUTPUT TO A VALUE: DATA
••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••

Remember how you can output data from the Data Output Screen?
You can also SET data as well with the DATA message!
You just send in the variables that you want to SET!
(Now, you can NOT set ALL the variables! Mach number, for example, is determined by the speed of the plane… so you cannot change that, for example).

But, to enter radios or control deflections by UDP, simply send the DATA message described below 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! (Just realize that some messages will be over-ridden by X-Plane!)

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.
};

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

So, to send in a DATA message to control some value in X-Plane, send in:
“DATA” (4 chars)
0 (1 char of val 0)
data_struct (a filled-in data struct as per above, with struct alignment 4)

Do this, and you should be able to control some of the variables in X-Plane by UDP!

••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
RUN A COMMAND: CMND
••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••

DATA INPUT STRUCTURE is a string

The data part of this message is simply the command that you want X-Plane to intitiate!
Easy!
To see the (plethora) of X-Plane commands, run X-Plane and go to the Settings menu, Joystick and Equipment screen, Buttons:Advanced tab.
The commands are the group name you see in the center of the screen, PLUS command string in the right side, all run together.
So, for example, the first command in the sim is: “none/none”.
OK that was a boring one.
But there are more! Lots more!

TYPICAL MESSAGE TO GET FLAPS ONE NOTCH UP WILL LOOK LIKE

CMND0+sim/flight_controls/flaps_up

••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
SELECT OR DE-SELECT DATA OUTPUT TO NOT OR COCKPIT DISLPAY: 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 DISPLAY rather than UDP output.

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

••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
CLICK THE MOUSE SOMEWHERE: MOUS
••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••

DATA INPUT STRUCTURE is an 8-char string

Simulates a mouse-click, where the data 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).

••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
CLICK A KEYBOARD KEY: 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.

••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
ACTIVATE A MENU ITEM: MENU
••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••

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.

••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
PLAY A SOUND: SOUN
••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••

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!

••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
PLAY A LOOPING SOUND: LSND and SSND
••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••

struct loop_struct
{
	xint index				;
	xflt freq,vol			;
	xchr soun_path[strDIM]	;
};

Use this to simply play a WAV-file sound THAT LOOPS, with index 0 to 4 (so you can have 5 going at once)

LSND starts it, SSND stops it.

••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
FAIL A SYSTEM: FAIL
••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••

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.

••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
RECOVER A SYSTEM: RECO
••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••

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.

••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
PLACE TO AN AIRPORT: PAPT
••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••

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

struct papt_struct							// place at apt... this is used here and there
{
	xchr apt_ID[8]			;
	init_flt_enum type_start	;
	xint lcl_rwy_ram		;
	xint rwy_dir			;
};

PAPT MESSAGE DOES NOT REQUIRE A FIXED LENGTH LIKE DREF. SO THE TYPICAL MESSAGE WILL LOOK LIKE

PAPT0+AIRPORT ID(SUCH AS KSFO)+0000+TYPE_START (THE RUNWAY REFERENCE NUMBER IN apt.dat	FILE+RWY_RAM(WHERE TO START)+DIR(BACKWARDS meaning you can put the airplane at the other end of the runway by setting this to 1)

••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
LOAD AN AIRCRAFT: ACFN
••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••

struct acfn_struct							// veh name and livery, used here and there
{
	xint		acfn_p				;
	xchr		acfn_path_rel[net_strDIM];
	xint		livery_index			;
};

Use this to load a vehicle (an airplane). Just enter which 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!

••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
LOAD AN OBJECT: OBJN
••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••

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.

••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
PLACE AN OBJECT: OBJL
••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••

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 anything else you can imagine.

••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
SET UP THE INTERNET OPTIONS: 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:

struct iset_struct			// IP settings
{
	xint index;
	xchr snd_ip_str[16]	;	// IP's we are sending to, in english
	xchr snd_pt_str[ 6]	;	// ports are easier to work with in STRINGS!
	xint snd_use_ip	;	// 1 or 0 to turn this option on or off
};

And following are a list of the indices as of X-Plane 10.40:

	ip_mplayer_00	=0						,	// p==p01 on THIS machine!!!
	ip_mplayer_18	=ip_mplayer_00+18			,	// p==p19 on THIS machine!!!
	ip_mon_00							,
	ip_mon_19	=ip_mon_00+19			,
	ip_master_view						,
	ip_unused_1							,	// available placeholders - here to avoid changing following enums
	ip_unused_2							,
	ip_master_00_IOS						,	// p==p00 on THIS machine!!! this machine is the ios.
	ip_master_19_IOS=ip_master_00_IOS+19	,	// p==p19 on THIS machine!!! this machine is the ios.
	ip_single_IOS							,	// send ALL data to this IOS!
	ip_multi_IOS							,	// do NOT send other planes or birds! the ios will get the other planes from them, and cannot handle 10 different ideas of flock location!
	ip_data_we_send						,
	ip_FLIR								,
	ip_remote								,	// iphone joystick
	ip_EFIS_0							,	// iphone efis-app
	ip_EFIS_1							,	// iphone efis-app
	ip_EFIS_2							,	// iphone efis-app
	ip_EFIS_3							,	// iphone efis-app