@@ -1,192 +0,0 @@
|
||||
X-Plane Connect-C (XPC-C) Readme
|
||||
|
||||
DESCRIPTION
|
||||
XPC-C is a series of C functions that facilitate communication with X-Plane.
|
||||
|
||||
-----------------------------------
|
||||
SETUP
|
||||
Before using XPC Functions you must
|
||||
1. Copy the folder "[XPC Directory]/xpcPlugin/XPlaneConnect" to the "[X-Plane Directory]/Resources/plugins" directory.
|
||||
2. Put in X-Plane CD 1 or X-Plane USB Key.
|
||||
3. Start X-Plane.
|
||||
4. #include "xplaneConnect.h"
|
||||
|
||||
-----------------------------------
|
||||
BASIC FUNCTIONS
|
||||
1. openUDP opens a UDP Socket for communication. This is used to send data or receive.
|
||||
INPUT:
|
||||
port (unsigned short): Port Number (ex:49067)
|
||||
xpIP (char *): IP Address of the computer running x-plane
|
||||
xpPort (unsigned short): Port number that the X-Plane/ xpcPlugin Receives on (send -1 for default (49009), Typically xpcPlugin is 49009)
|
||||
|
||||
OUTPUT:
|
||||
socket (xpcSocket): The Opened Socket
|
||||
|
||||
USE:
|
||||
unsigned short portNumber = 49067;
|
||||
struct xpcSocket theSocket = openUDP(portNumber, “127.0.0.1”, 49009);
|
||||
|
||||
2. closeUDP closes an opened UDP Socket for communication. This is to be done after the program has finished using that socket. Use opedUDP to open socket.
|
||||
INPUT:
|
||||
socket (xpcSocket): The Opened Socket
|
||||
|
||||
USE:
|
||||
closeUDP(theSocket);
|
||||
|
||||
3. setCONN sets the return port for requested datarefs.
|
||||
INPUT:
|
||||
socket (xpcSocket): Socket to use to send the command
|
||||
recPort (unsigned Short): Port number for requested dataref values to be sent to
|
||||
|
||||
OUTPUT:
|
||||
status (short): 0 if successful
|
||||
|
||||
USE:
|
||||
char IP[16] = "127.0.0.1";
|
||||
struct xpcSocket theSocket = openUDP(49067);
|
||||
setCONN(theSocket,IP,49009,49022); // Sets receive address to 49022;
|
||||
|
||||
4. pauseSim pauses/resumes the x-plane simulation
|
||||
INPUT:
|
||||
socket (xpcSocket): Socket to use to send the command
|
||||
pause (short): 1=Pause, 0=Resume
|
||||
|
||||
OUTPUT:
|
||||
status (short): 0 if successful
|
||||
|
||||
USE:
|
||||
char IP[16] = "127.0.0.1";
|
||||
struct xpcSocket theSocket = openUDP(49067);
|
||||
pauseSim(theSocket, IP, 49009, 1);
|
||||
|
||||
5. sendDATA set the value of a state in the "DATA Input & Output" Table
|
||||
INPUT:
|
||||
socket (xpcSocket): Socket to use to send the command
|
||||
dataArray (float[][9]): Array of data to be sent. The first element of each row is the item # (corresponding to the number on the X-Plane "DATA Input & Output" Screen). Send -999 to leave the value unchanged.
|
||||
rows (unsigned short): Number of rows of data being sent
|
||||
|
||||
OUTPUT:
|
||||
status (short): 0 if successful
|
||||
|
||||
USE:
|
||||
char IP[16] = "127.0.0.1";
|
||||
struct xpcSocket theSocket = openUDP(49067);
|
||||
float data[] = {{14, 1, -999, -999, -999, -999, -999, -999, -999},{25, 0.8, 0.8, -999, -999, -999, -999, -999, -999}}; // Gear and Throttle
|
||||
sendDATA(theSocket,IP,49009,data,2);
|
||||
|
||||
6. sendPOSI set the position of an aircraft
|
||||
INPUT:
|
||||
socket (xpcSocket): Socket to use to send the command
|
||||
ACNum (short): Number of aircraft to be moved, use 0 for main aircraft (ownPlane).
|
||||
numArgs (short): Number of Arguments to be sent (size of position array)
|
||||
position (float []): Arguments corresponding to aircrafts position
|
||||
position[0] = Latitude
|
||||
position[1] = Longitude
|
||||
position[2] = Altitude (m MSL)
|
||||
position[3] = Roll (deg)
|
||||
position[4] = Pitch (deg)
|
||||
position[5] = True Heading (deg)
|
||||
position[6] = Gear (0=up, 1=down)
|
||||
|
||||
OUTPUT:
|
||||
status (short): 0 if successful
|
||||
|
||||
USE:
|
||||
char IP[16] = "127.0.0.1";
|
||||
struct xpcSocket theSocket = openUDP(49067);
|
||||
float posit[] = {37.5242422, -122.06899, 2500, 0, 0, 0, 1};
|
||||
sendPOSI(theSocket, IP, 49009, 7, posit);
|
||||
|
||||
7. sendCTRL send control commands to the aircraft
|
||||
INPUT:
|
||||
socket (xpcSocket): Socket to use to send the command
|
||||
numArgs (short): Number of Arguments to be sent (size of control array)
|
||||
control (float []): Arguments corresponding to aircraft control command
|
||||
control[0] = Latitudinal Stick [-1,1]
|
||||
control[1] = Longitudinal Stick [-1,1]
|
||||
control[2] = Pedal [-1, 1]
|
||||
control[3] = Throttle [-1, 1]
|
||||
control[4] = Gear (0=up, 1=down)
|
||||
control[5] = Flaps [0, 1]
|
||||
|
||||
OUTPUT:
|
||||
status (short): 0 if successful
|
||||
|
||||
USE:
|
||||
char IP[16] = "127.0.0.1";
|
||||
struct xpcSocket theSocket = openUDP(49067);
|
||||
float ctrl[] = {0, 0, 0, 0.8, 0, 1};
|
||||
sendCTRL(theSocket, IP, 49009, 6, ctrl);
|
||||
|
||||
8. sendDREF set the value of a specific dataref. Dataref list found at http://www.xsquawkbox.net/xpsdk/docs/DataRefs.html
|
||||
INPUT:
|
||||
socket (xpcSocket): Socket to use to send the command
|
||||
dataRef (char *): Dataref to be set (with or without "sim/" preceeding it)
|
||||
length (short): length of dataref string
|
||||
values (float *): Array of values to be sent
|
||||
length2 (short): Number of values in values array
|
||||
|
||||
OUTPUT:
|
||||
status (short): 0 if successful
|
||||
|
||||
USE:
|
||||
char IP[16] = "127.0.0.1";
|
||||
struct xpcSocket theSocket = openUDP(49067);
|
||||
char theDREF[] = "cockpit/switches/gear_handle_status";
|
||||
float value = 1;
|
||||
sendDREF(theSocket, IP, 49009, theDREF, strlen(theDREF), &value, 1);
|
||||
|
||||
9. requestDREF Request the value of specific dref(s). Dataref list found at http://www.xsquawkbox.net/xpsdk/docs/DataRefs.html
|
||||
INPUT:
|
||||
outSocket (xpcSocket): Socket to use to send the command
|
||||
inSocket (xpcSocket): Socket to use to receive the result
|
||||
DREFArray (char[][100]): Array of DataRefs to be requested
|
||||
DREFSizes (int[]): Array of string lengths for each DataRef in DREFArray
|
||||
listLength (short): Number of DataRefs in DREFArray
|
||||
result (*float[]): Array of pointers to the values returned
|
||||
arrayLen (short[]): Array where each element corresponds to the number of elements in the float array.
|
||||
|
||||
OUTPUT:
|
||||
length (short): Number of Values Returned
|
||||
|
||||
USE:
|
||||
char IP[16] = "127.0.0.1";
|
||||
struct xpcSocket theSocket = openUDP(49067);
|
||||
char DREFArray[][100] = {"sim/cockpit/switches/gear_handle_status"};
|
||||
requestDREF(theSocket, IP, 49009, DREFArray, strlen(DREFArray[0]),1);
|
||||
|
||||
10. sendTEXT write some text to the screen.
|
||||
INPUT:
|
||||
outSocket (xpcSocket): Socket to use to send the command
|
||||
message (char*): The string to be wrote to the screen
|
||||
x (int): The x position where the text will be written. Set to -1 to use default position.
|
||||
y (int): The y position where the text will be written. Set to -1 to use default position.
|
||||
|
||||
-----------------------------------
|
||||
ADVANCED FUNCTIONS (These are mostly used by the xpcPlugin to read requests)
|
||||
1. sendUDP
|
||||
2. readUDP
|
||||
3. readDATA
|
||||
4. parseDATA
|
||||
5. readPOSI
|
||||
6. parsePOSI
|
||||
7. readCTRL
|
||||
8. parseCTRL
|
||||
9. readRequest
|
||||
10. parseRequest
|
||||
11. parseDREF
|
||||
12. readDREF
|
||||
|
||||
-----------------------------------
|
||||
PLANNED FUNCTIONS
|
||||
1. sendVIEW
|
||||
2. parseVIEW
|
||||
3. readVIEW
|
||||
4. sendWYPT
|
||||
5. parseWYPT
|
||||
6. readWYPT
|
||||
7. selectDATA
|
||||
|
||||
-----------------------------------
|
||||
CONTACT
|
||||
Email Christopher Teubert (christopher.a.teubert@nasa.gov) with any questions.
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,119 +1,217 @@
|
||||
//Copyright (c) 2013-2015 United States Government as represented by the Administrator of the
|
||||
//National Aeronautics and Space Administration. All Rights Reserved.
|
||||
//
|
||||
// xplaneConnect.h
|
||||
//
|
||||
// Created by Chris Teubert on 12/2/13.
|
||||
//DISCLAIMERS
|
||||
// No Warranty: THE SUBJECT SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY OF ANY KIND,
|
||||
// EITHER EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, ANY WARRANTY THAT
|
||||
// THE SUBJECT SOFTWARE WILL CONFORM TO SPECIFICATIONS, ANY IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR FREEDOM FROM INFRINGEMENT, ANY WARRANTY
|
||||
// THAT THE SUBJECT SOFTWARE WILL BE ERROR FREE, OR ANY WARRANTY THAT DOCUMENTATION, IF PROVIDED,
|
||||
// WILL CONFORM TO THE SUBJECT SOFTWARE. THIS AGREEMENT DOES NOT, IN ANY MANNER, CONSTITUTE AN
|
||||
// ENDORSEMENT BY GOVERNMENT AGENCY OR ANY PRIOR RECIPIENT OF ANY RESULTS, RESULTING DESIGNS,
|
||||
// HARDWARE, SOFTWARE PRODUCTS OR ANY OTHER APPLICATIONS RESULTING FROM USE OF THE SUBJECT
|
||||
// SOFTWARE. FURTHER, GOVERNMENT AGENCY DISCLAIMS ALL WARRANTIES AND LIABILITIES REGARDING
|
||||
// THIRD-PARTY SOFTWARE, IF PRESENT IN THE ORIGINAL SOFTWARE, AND DISTRIBUTES IT "AS IS."
|
||||
//
|
||||
// Waiver and Indemnity: RECIPIENT AGREES TO WAIVE ANY AND ALL CLAIMS AGAINST THE UNITED STATES
|
||||
// GOVERNMENT, ITS CONTRACTORS AND SUBCONTRACTORS, AS WELL AS ANY PRIOR RECIPIENT. IF
|
||||
// RECIPIENT'S USE OF THE SUBJECT SOFTWARE RESULTS IN ANY LIABILITIES, DEMANDS, DAMAGES, EXPENSES
|
||||
// OR LOSSES ARISING FROM SUCH USE, INCLUDING ANY DAMAGES FROM PRODUCTS BASED ON, OR RESULTING
|
||||
// FROM, RECIPIENT'S USE OF THE SUBJECT SOFTWARE, RECIPIENT SHALL INDEMNIFY AND HOLD HARMLESS THE
|
||||
// UNITED STATES GOVERNMENT, ITS CONTRACTORS AND SUBCONTRACTORS, AS WELL AS ANY PRIOR RECIPIENT,
|
||||
// TO THE EXTENT PERMITTED BY LAW. RECIPIENT'S SOLE REMEDY FOR ANY SUCH MATTER SHALL BE THE
|
||||
// IMMEDIATE, UNILATERAL TERMINATION OF THIS AGREEMENT.
|
||||
#ifndef xplaneConnect_h
|
||||
#define xplaneConnect_h
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef xplaneConnect_h
|
||||
#define xplaneConnect_h
|
||||
#include "stdlib.h"
|
||||
#ifdef _WIN32 /* WIN32 SYSTEM */
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#pragma comment(lib,"ws2_32.lib") //Winsock Library
|
||||
#elif (__APPLE__ || __linux)
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32 /* WIN32 SYSTEM */
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#pragma comment(lib,"ws2_32.lib") //Winsock Library
|
||||
#elif (__APPLE__ || __linux)
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
struct xpcSocket {
|
||||
short open;
|
||||
unsigned short port;
|
||||
|
||||
// X-Plane IP and Port
|
||||
char xpIP[16];
|
||||
unsigned short xpPort;
|
||||
|
||||
#ifdef _WIN32 /* WIN32 SYSTEM */
|
||||
SOCKET sock;
|
||||
#elif (__APPLE__ || __linux) //OS X/Linux
|
||||
int sock;
|
||||
#endif
|
||||
};
|
||||
typedef struct xpcSocket
|
||||
{
|
||||
unsigned short port;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float pitch;
|
||||
float roll;
|
||||
float yaw;
|
||||
float throttle;
|
||||
char gear;
|
||||
float flaps;
|
||||
char aircraft;
|
||||
} xpcCtrl;
|
||||
// X-Plane IP and Port
|
||||
char xpIP[16];
|
||||
unsigned short xpPort;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
double latitude;
|
||||
double longitude;
|
||||
double altitude;
|
||||
} Waypoint;
|
||||
#ifdef _WIN32
|
||||
SOCKET sock;
|
||||
#else
|
||||
int sock;
|
||||
#endif
|
||||
} XPCSocket;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
xpc_WYPT_ADD = 1,
|
||||
xpc_WYPT_DEL = 2,
|
||||
xpc_WYPT_CLR = 3
|
||||
} WYPT_OP;
|
||||
typedef enum
|
||||
{
|
||||
XPC_WYPT_ADD = 1,
|
||||
XPC_WYPT_DEL = 2,
|
||||
XPC_WYPT_CLR = 3
|
||||
} WYPT_OP;
|
||||
|
||||
// Low Level UDP Functions
|
||||
|
||||
typedef struct
|
||||
{
|
||||
WYPT_OP op;
|
||||
Waypoint points[20];
|
||||
size_t numPoints;
|
||||
} xpcWypt;
|
||||
|
||||
// Basic Functions
|
||||
struct xpcSocket openUDP(unsigned short port, const char *xpIP, unsigned short xpPort);
|
||||
void closeUDP(struct xpcSocket);
|
||||
short sendUDP(struct xpcSocket recfd, char my_message[], short messageLength);
|
||||
short readUDP(struct xpcSocket recfd, char *dataRef, struct sockaddr *recvaddr);
|
||||
|
||||
// Configuration
|
||||
short setCONN(struct xpcSocket recfd, unsigned short recPort);
|
||||
short pauseSim(struct xpcSocket recfd, short);
|
||||
|
||||
// UDP DATA
|
||||
short parseDATA(const char my_message[], short messageLength, float dataRef[][9]);
|
||||
short readDATA(struct xpcSocket recfd, float dataRef[][9]);
|
||||
short sendDATA(struct xpcSocket recfd, float dataRef[][9], unsigned short rows);
|
||||
|
||||
// Position
|
||||
short parsePOSI(const char my_message[], float resultArray[], int arraySize, float *gear);
|
||||
short readPOSI(struct xpcSocket recfd, float resultArray[], int arraySize, float *gear);
|
||||
short sendPOSI(struct xpcSocket recfd, short ACNum, short numArgs, float valueArray[]);
|
||||
|
||||
// Controls
|
||||
xpcCtrl parseCTRL(const char data[]);
|
||||
xpcCtrl readCTRL(struct xpcSocket recfd);
|
||||
short sendCTRL(struct xpcSocket recfd, short numArgs, float valueArray[]);
|
||||
short sendpCTRL(struct xpcSocket recfd, short numArgs, float valueArray[], char acNum);
|
||||
|
||||
// DREF Manipulation
|
||||
short readDREF(struct xpcSocket recfd, float *resultArray[], short arraySizes[]);
|
||||
short parseDREF(const char my_message[], char *dataRef, unsigned short *length_of_DREF, float *values, unsigned short *number_of_values);
|
||||
short sendDREF(struct xpcSocket recfd, const char *dataRef, unsigned short length_of_DREF, float *values, unsigned short number_of_values);
|
||||
short requestDREF(struct xpcSocket sendfd, struct xpcSocket recfd, char DREFArray[][100], short DREFSizes[], short listLength, float *resultArray[], short arraySizes[]);
|
||||
int parseGETD(const char my_message[], char *DREFArray[], int DREFSizes[]);
|
||||
short parseRequest(const char my_message[], float *resultArray[], short arraySizes[]);
|
||||
short readRequest(struct xpcSocket recfd, float *dataRef[], short arraySizes[], struct sockaddr *recvaddr);
|
||||
/// Opens a new connection to XPC on an OS chosen port.
|
||||
///
|
||||
/// \param xpIP A string representing the IP address of the host running X-Plane.
|
||||
/// \returns An XPCSocket struct representing the newly created connection.
|
||||
XPCSocket openUDP(const char *xpIP);
|
||||
|
||||
// Waypoints
|
||||
xpcWypt parseWYPT(const char data[]);
|
||||
short sendWYPT(struct xpcSocket sendfd, WYPT_OP op, float points[], int numPoints);
|
||||
/// Opens a new connection to XPC on the specified port.
|
||||
///
|
||||
/// \param xpIP A string representing the IP address of the host running X-Plane.
|
||||
/// \param xpPort The port of the X-Plane Connect plugin is listening on. Usually 49009.
|
||||
/// \param port The local port to use when sending and receiving data from XPC.
|
||||
/// \returns An XPCSocket struct representing the newly created connection.
|
||||
XPCSocket aopenUDP(const char *xpIP, unsigned short xpPort, unsigned short port);
|
||||
|
||||
// Screen Text
|
||||
short sendTEXT(struct xpcSocket sendfd, char* msg, int x, int y);
|
||||
/// Closes the specified connection and releases resources associated with it.
|
||||
///
|
||||
/// \param sock The socket to close.
|
||||
void closeUDP(XPCSocket sock);
|
||||
|
||||
// Configuration
|
||||
|
||||
/// Sets the port on which the socket sends and receives data.
|
||||
///
|
||||
/// \param sock A pointer to the socket to change.
|
||||
/// \param port The new port to use.
|
||||
/// \returns 0 if successful, otherwise a negative value.
|
||||
int setCONN(XPCSocket* sock, unsigned short port);
|
||||
|
||||
/// Pause or unpause the simulation.
|
||||
///
|
||||
/// \param sock The socket to use to send the command.
|
||||
/// \param pause 0 to unpause the sim; any other value to pause.
|
||||
/// \returns 0 if successful, otherwise a negative value.
|
||||
int pauseSim(XPCSocket sock, char pause);
|
||||
|
||||
#endif //ifdef _h
|
||||
// X-Plane UDP DATA
|
||||
|
||||
/// Reads X-Plane data from the specified socket.
|
||||
///
|
||||
/// \details This command is compatible with the X-Plane data API.
|
||||
/// \param sock The socket to use to send the command.
|
||||
/// \param data A 2D array of data rows to read into.
|
||||
/// \param rows The number of rows in dataRef.
|
||||
/// \returns 0 if successful, otherwise a negative value.
|
||||
int readDATA(XPCSocket sock, float data[][9], int rows);
|
||||
|
||||
/// Sends X-Plane data on the specified socket.
|
||||
///
|
||||
/// \details This command is compatible with the X-Plane data API.
|
||||
/// \param sock The socket to use to send the command.
|
||||
/// \param data A 2D array of data rows to send.
|
||||
/// \param rows The number of rows in dataRef.
|
||||
/// \returns 0 if successful, otherwise a negative value.
|
||||
int sendDATA(XPCSocket sock, float data[][9], int rows);
|
||||
|
||||
// DREF Manipulation
|
||||
|
||||
/// Sets the specified dataref to the specified value.
|
||||
///
|
||||
/// \details dref names and their associated data types can be found on the XPSDK wiki at
|
||||
/// http://www.xsquawkbox.net/xpsdk/docs/DataRefs.html. The size of values should match
|
||||
/// the size given on that page. XPC currently sends all values as floats regardless of
|
||||
/// the type described on the wiki. This doesn't cause any data loss for most datarefs.
|
||||
/// \param sock The socket to use to send the command.
|
||||
/// \param dref The name of the dataref to set.
|
||||
/// \param values An array of values representing the data to set.
|
||||
/// \param size The number of elements in values.
|
||||
/// \returns 0 if successful, otherwise a negative value.
|
||||
int sendDREF(XPCSocket sock, const char* dref, float value[], int size);
|
||||
|
||||
/// Gets the value of the specified dataref.
|
||||
///
|
||||
/// \details dref names and their associated data types can be found on the XPSDK wiki at
|
||||
/// http://www.xsquawkbox.net/xpsdk/docs/DataRefs.html. The size of values should match
|
||||
/// the size given on that page. XPC currently sends all values as floats regardless of
|
||||
/// the type described on the wiki. This doesn't cause any data loss for most datarefs.
|
||||
/// \param sock The socket to use to send the command.
|
||||
/// \param dref The name of the dataref to get.
|
||||
/// \param values The array in which the value of the dataref will be stored.
|
||||
/// \param size The number of elements in values. The actual number of elements copied in will
|
||||
/// be set when the function returns.
|
||||
/// \returns 0 if successful, otherwise a negative value.
|
||||
int getDREF(XPCSocket sock, const char* dref, float values[], int* size);
|
||||
|
||||
/// Gets the value of the specified dataref.
|
||||
///
|
||||
/// \details dref names and their associated data types can be found on the XPSDK wiki at
|
||||
/// http://www.xsquawkbox.net/xpsdk/docs/DataRefs.html. The size of values should match
|
||||
/// the size given on that page. XPC currently sends all values as floats regardless of
|
||||
/// the type described on the wiki. This doesn't cause any data loss for most datarefs.
|
||||
/// \param sock The socket to use to send the command.
|
||||
/// \param drefs The names of the datarefs to get.
|
||||
/// \param values A 2D array in which the values of the datarefs will be stored.
|
||||
/// \param count The number of datarefs being requested.
|
||||
/// \param size The number of elements in each row of values. The size of each row will be set
|
||||
/// to the actual number of elements copied in for that row.
|
||||
/// \returns 0 if successful, otherwise a negative value.
|
||||
int getDREFs(XPCSocket sock, const char* drefs[], float* values[], unsigned char count, int sizes[]);
|
||||
|
||||
// Position
|
||||
|
||||
/// Sets the position and orientation of the specified aircraft.
|
||||
///
|
||||
/// \param sock The socket to use to send the command.
|
||||
/// \param values An array representing position data about the aircraft. The format of values is
|
||||
/// [Lat, Lon, Alt, Pitch, Roll, Yaw, Gear]. If less than 7 values are specified,
|
||||
/// the unspecified values will be left unchanged.
|
||||
/// \param size The number of elements in values.
|
||||
/// \param ac The aircraft number to set the position of. 0 for the player aircraft.
|
||||
/// \returns 0 if successful, otherwise a negative value.
|
||||
int sendPOSI(XPCSocket sock, float values[], int size, char ac);
|
||||
|
||||
// Controls
|
||||
|
||||
/// Sets the control surfaces of the specified aircraft.
|
||||
///
|
||||
/// \param sock The socket to use to send the command.
|
||||
/// \param values An array representing position data about the aircraft. The format of values is
|
||||
/// [Elevator, Aileron, Rudder, Throttle, Gear, Flaps]. If less than 6 values are
|
||||
/// specified, the unspecified values will be left unchanged.
|
||||
/// \param size The number of elements in values.
|
||||
/// \param ac The aircraft number to set the control surfaces of. 0 for the player aircraft.
|
||||
/// \returns 0 if successful, otherwise a negative value.
|
||||
int sendCTRL(XPCSocket sock, float values[], int size, char ac);
|
||||
|
||||
// Drawing
|
||||
|
||||
/// Sets a string to be printed on the screen in X-Plane.
|
||||
///
|
||||
/// \param sock The socket to use to send the command.
|
||||
/// \param msg The message to print of the screen.
|
||||
/// \param x The distance in pixels from the left edge of the screen to print the text.
|
||||
/// \param y The distance in pixels from the bottom edge of the screen to print the top line of text.
|
||||
/// \returns 0 if successful, otherwise a negative value.
|
||||
int sendTEXT(XPCSocket sock, char* msg, int x, int y);
|
||||
|
||||
/// Adds, removes, or clears a set of waypoints. If the command is clear, the points are ignored
|
||||
/// and all points are removed.
|
||||
///
|
||||
/// \param sock The socket to use to send the command.
|
||||
/// \param op The operation to perform. 1=add, 2=remove, 3=clear.
|
||||
/// \param points An array of values representing points. Each triplet in the array will be
|
||||
/// interpreted as a (Lat, Lon, Alt) point.
|
||||
/// \param count The number of points. There should be 3 * count elements in points.
|
||||
/// \returns 0 if successful, otherwise a negative value.
|
||||
int sendWYPT(XPCSocket sock, WYPT_OP op, float points[], int count);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -16,38 +16,17 @@
|
||||
#define sleep(n) Sleep(n * 1000)
|
||||
#endif
|
||||
|
||||
int main() {
|
||||
int i, j;
|
||||
struct xpcSocket sendfd, readfd;
|
||||
float data[4][9] = { 0 };
|
||||
char DREF[100] = { 0 };
|
||||
char DREFArray[100][100];
|
||||
char DREFArray2[100][100];
|
||||
short DREFSizes[100];
|
||||
float *recDATA[100];
|
||||
float POSI[9] = { 0.0 };
|
||||
float CTRL[5] = { 0.0 };
|
||||
float gear;
|
||||
char IP[16] = "127.0.0.1"; //IP Address of computer running X-Plane
|
||||
short PORT = 49009; //xpcPlugin Receiving port (usually 49009)
|
||||
int main()
|
||||
{
|
||||
printf("XPlaneConnect Example Script\n- Setting up Simulation\n");
|
||||
|
||||
printf("xplaneconnect Example Script\n- Setting up Simulation\n");
|
||||
|
||||
for (i = 0; i < 100; i++) {
|
||||
recDATA[i] = (float *)malloc(40 * sizeof(float));
|
||||
memset(DREFArray[i], 0, 100);
|
||||
memset(DREFArray2[i], 0, 100);
|
||||
}
|
||||
|
||||
// Open Sockets
|
||||
readfd = openUDP(49055, IP, PORT); //Open socket for receiving
|
||||
sendfd = openUDP(49077, IP, PORT); //Open socket for sending
|
||||
|
||||
// Set up Connection
|
||||
setCONN(sendfd, 49055); // Setup so data will be received on port 49055
|
||||
// Open Socket
|
||||
const char* IP = "127.0.0.1"; //IP Address of computer running X-Plane
|
||||
XPCSocket sock = openUDP(IP);
|
||||
|
||||
// Set Location/Orientation (sendPOSI)
|
||||
// Set Up Position Array
|
||||
float POSI[9] = { 0.0 };
|
||||
POSI[0] = 37.524; // Lat
|
||||
POSI[1] = -122.06899; // Lon
|
||||
POSI[2] = 2500; // Alt
|
||||
@@ -56,22 +35,30 @@ int main() {
|
||||
POSI[5] = 0; // Heading
|
||||
POSI[6] = 1; // Gear
|
||||
|
||||
sendPOSI(sendfd, 0, 7, POSI);
|
||||
// Set position of the player aircraft
|
||||
sendPOSI(sock, POSI, 7, 0);
|
||||
|
||||
POSI[0] = 37.52465; // Move a second aircraft a bit North of us
|
||||
POSI[4] = 20; // Give that aircraft a bit or right roll
|
||||
sendPOSI(sendfd, 1, 7, POSI);
|
||||
// Set position of a multiplayer aircraft
|
||||
sendPOSI(sock, POSI, 7, 1);
|
||||
|
||||
// Set Rates (sendDATA)
|
||||
|
||||
for (i = 0; i < 4; i++) { // Set array to -999
|
||||
for (j = 0; j < 9; j++) data[i][j] = -999;
|
||||
float data[3][9] = { 0 };
|
||||
// Initialize data values to -998 to not overwrite values.
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
for (int j = 0; j < 9; j++)
|
||||
{
|
||||
data[i][j] = -998;
|
||||
}
|
||||
}
|
||||
// Set up Data Array (first item in row is item number (example: 20=position)
|
||||
data[0][0] = 18; // Alpha
|
||||
data[0][1] = 0;
|
||||
data[0][3] = 0;
|
||||
|
||||
data[1][0] = 3;//21; //Velocity
|
||||
data[1][0] = 3; //Velocity
|
||||
data[1][1] = 130;
|
||||
data[1][2] = 130;
|
||||
data[1][3] = 130;
|
||||
@@ -82,21 +69,19 @@ int main() {
|
||||
data[2][2] = 0;
|
||||
data[2][3] = 0;
|
||||
|
||||
sendDATA(sendfd, data, 3); // Velocity/Alpha/PQR
|
||||
sendDATA(sock, data, 3);
|
||||
|
||||
// Set CTRL
|
||||
// Set throttle on the player aircraft using sendCTRL
|
||||
float CTRL[5] = { 0.0 };
|
||||
CTRL[3] = 0.8; // Throttle
|
||||
|
||||
sendCTRL(sendfd, 4, CTRL);
|
||||
sendCTRL(sock, CTRL, 5, 0);
|
||||
|
||||
// pauseSim
|
||||
pauseSim(sendfd, 1); // Sending 1 to pause
|
||||
|
||||
// Pause for 5 seconds
|
||||
sleep(5);
|
||||
pauseSim(sock, 1); // Sending 1 to pause
|
||||
sleep(5); // Pause for 5 seconds
|
||||
|
||||
// Unpause
|
||||
pauseSim(sendfd, 0); // Sending 0 to unpause
|
||||
pauseSim(sock, 0); // Sending 0 to unpause
|
||||
printf("- Resuming Simulation\n");
|
||||
|
||||
// Simulate for 10 seconds
|
||||
@@ -105,28 +90,34 @@ int main() {
|
||||
// SendDREF (Landing Gear)
|
||||
printf("- Stowing Landing Gear\n");
|
||||
|
||||
strcpy(DREF, "sim/cockpit/switches/gear_handle_status"); // Gear handle data reference
|
||||
DREFSizes[0] = strlen(DREF);
|
||||
gear = 1; // Stow gear
|
||||
|
||||
sendDREF(sendfd, DREF, DREFSizes[0], &gear, 1); // Set gear to stow
|
||||
const char* dref = "sim/cockpit/switches/gear_handle_status"; // Gear handle data reference
|
||||
float gear = 0; // Stow gear
|
||||
sendDREF(sock, dref, &gear, 1); // Set gear to stow
|
||||
|
||||
// Simulate for 10 seconds
|
||||
sleep(10);
|
||||
|
||||
// Check Landing gear, Pause
|
||||
printf("- Confirming Gear Status\n");
|
||||
strcpy(DREFArray2[0], "sim/cockpit/switches/gear_handle_status");
|
||||
strcpy(DREFArray2[1], "sim/operation/override/override_planepath");
|
||||
for (i = 0; i < 2; i++) {
|
||||
DREFSizes[i] = (int)strlen(DREFArray2[i]);
|
||||
const char* drefs[2] =
|
||||
{
|
||||
"sim/cockpit/switches/gear_handle_status",
|
||||
"sim/operation/override/override_planepath"
|
||||
};
|
||||
float* results[2];
|
||||
int sizes[2] = { 20, 20 };
|
||||
for (int i = 0; i < 2; ++i)
|
||||
{
|
||||
results[i] = (float*)malloc(20 * sizeof(float));
|
||||
}
|
||||
requestDREF(sendfd, readfd, DREFArray2, DREFSizes, 2, recDATA, DREFSizes); // Request 2 values
|
||||
getDREFs(sock, drefs, results, 2, sizes);
|
||||
|
||||
if (*(recDATA[0]) == 0) {
|
||||
if (results[0][0] == 0)
|
||||
{
|
||||
printf("\tGear Stowed\n");
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
printf("\tERROR: Gear Stowage unsuccessful\n");
|
||||
}
|
||||
|
||||
|
||||
Binary file not shown.
@@ -82,7 +82,7 @@ public class Main
|
||||
"sim/cockpit/switches/gear_handle_status",
|
||||
"sim/operation/override/override_planepath"
|
||||
};
|
||||
float[][] results = xpc.requestDREFs(drefs);
|
||||
float[][] results = xpc.getDREFs(drefs);
|
||||
|
||||
if(results[0][0] == 1)
|
||||
{
|
||||
|
||||
@@ -44,8 +44,7 @@ import java.util.Arrays;
|
||||
public class XPlaneConnect implements AutoCloseable
|
||||
{
|
||||
private static int clientNum;
|
||||
private DatagramSocket outSocket;
|
||||
private DatagramSocket inSocket;
|
||||
private DatagramSocket socket;
|
||||
private InetAddress xplaneAddr;
|
||||
private int xplanePort;
|
||||
|
||||
@@ -54,7 +53,7 @@ public class XPlaneConnect implements AutoCloseable
|
||||
*
|
||||
* @return The incoming port number.
|
||||
*/
|
||||
public int getRecvPort() { return inSocket.getLocalPort(); }
|
||||
public int getRecvPort() { return socket.getLocalPort(); }
|
||||
|
||||
/**
|
||||
* Gets the port on which the client sends data to X-Plane.
|
||||
@@ -116,62 +115,55 @@ public class XPlaneConnect implements AutoCloseable
|
||||
*/
|
||||
public XPlaneConnect(int timeout) throws SocketException
|
||||
{
|
||||
this.inSocket = new DatagramSocket(49008);
|
||||
this.outSocket = new DatagramSocket(50000 + ++clientNum);
|
||||
this.socket = new DatagramSocket(0);
|
||||
this.xplaneAddr = InetAddress.getLoopbackAddress();
|
||||
this.xplanePort = 49009;
|
||||
this.inSocket.setSoTimeout(timeout);
|
||||
this.socket.setSoTimeout(timeout);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes a new instance of the {@code XPlaneConnect} class using the specified ports and X-Plane host.
|
||||
*
|
||||
* @param port The port on which the X-Plane Connect plugin is sending data.
|
||||
* @param xplaneHost The network host on which X-Plane is running.
|
||||
* @param xplanePort The port on which the X-Plane Connect plugin is listening.
|
||||
* @param xpHost The network host on which X-Plane is running.
|
||||
* @param xpPort The port on which the X-Plane Connect plugin is listening.
|
||||
* @param port The local port to use when sending and receiving data from XPC.
|
||||
* @throws java.net.SocketException If this instance is unable to bind to the specified port.
|
||||
* @throws java.net.UnknownHostException If the specified hostname can not be resolved.
|
||||
*/
|
||||
public XPlaneConnect(int port, String xplaneHost, int xplanePort)
|
||||
public XPlaneConnect(String xpHost, int xpPort, int port)
|
||||
throws java.net.SocketException, java.net.UnknownHostException
|
||||
{
|
||||
this(port, xplaneHost, xplanePort, 100);
|
||||
this(xpHost, xpPort, port, 100);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes a new instance of the {@code XPlaneConnect} class using the specified ports, hostname, and timeout.
|
||||
*
|
||||
* @param port The port on which the X-Plane Connect plugin is sending data.
|
||||
* @param xplaneHost The network host on which X-Plane is running.
|
||||
* @param xplanePort The port on which the X-Plane Connect plugin is listening.
|
||||
* @param xpHost The network host on which X-Plane is running.
|
||||
* @param xpPort The port on which the X-Plane Connect plugin is listening.
|
||||
* @param port The port on which the X-Plane Connect plugin is sending data.
|
||||
* @param timeout The time, in milliseconds, after which read attempts will timeout.
|
||||
* @throws java.net.SocketException If this instance is unable to bind to the specified port.
|
||||
* @throws java.net.UnknownHostException If the specified hostname can not be resolved.
|
||||
*/
|
||||
public XPlaneConnect(int port, String xplaneHost, int xplanePort, int timeout)
|
||||
public XPlaneConnect(String xpHost, int xpPort, int port, int timeout)
|
||||
throws java.net.SocketException, java.net.UnknownHostException
|
||||
{
|
||||
this.inSocket = new DatagramSocket(port);
|
||||
this.outSocket = new DatagramSocket(50000 + ++clientNum);
|
||||
this.xplaneAddr = InetAddress.getByName(xplaneHost);
|
||||
this.xplanePort = xplanePort;
|
||||
this.inSocket.setSoTimeout(timeout);
|
||||
this.socket = new DatagramSocket(port);
|
||||
this.xplaneAddr = InetAddress.getByName(xpHost);
|
||||
this.xplanePort = xpPort;
|
||||
this.socket.setSoTimeout(timeout);
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the underlying inSocket.
|
||||
* Closes the underlying socket.
|
||||
*/
|
||||
public void close()
|
||||
{
|
||||
if(inSocket != null)
|
||||
if(socket != null)
|
||||
{
|
||||
inSocket.close();
|
||||
inSocket = null;
|
||||
}
|
||||
if(outSocket != null)
|
||||
{
|
||||
outSocket.close();
|
||||
outSocket = null;
|
||||
socket.close();
|
||||
socket = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -181,14 +173,14 @@ public class XPlaneConnect implements AutoCloseable
|
||||
* @return The data send from X-Plane.
|
||||
* @throws IOException If the read operation fails
|
||||
*/
|
||||
private byte[] readUDP() throws IOException //TODO: Store data in a class level buffer to account for partial messages
|
||||
private byte[] readUDP() throws IOException
|
||||
{
|
||||
byte[] buffer = new byte[2048];
|
||||
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
|
||||
try
|
||||
{
|
||||
inSocket.receive(packet);
|
||||
return Arrays.copyOf(buffer, buffer[4]);
|
||||
socket.receive(packet);
|
||||
return Arrays.copyOf(buffer, packet.getLength());
|
||||
}
|
||||
catch (SocketTimeoutException ex)
|
||||
{
|
||||
@@ -197,22 +189,15 @@ public class XPlaneConnect implements AutoCloseable
|
||||
}
|
||||
|
||||
/**
|
||||
* Send the given data to the X-Plane plugin. This method automatically sets the length byte before sending,
|
||||
* overwriting any value previously stored in @{code buffer[4]}.
|
||||
* Send the given data to the X-Plane plugin.
|
||||
*
|
||||
* @param buffer The data to send.
|
||||
* @throws IOException If the send operation fails.
|
||||
*/
|
||||
private void sendUDP(byte[] buffer) throws IOException
|
||||
{
|
||||
if(buffer.length < 5 || buffer.length > 255)
|
||||
{
|
||||
throw new IllegalArgumentException("buffer must be between 5 and 255 bytes long.");
|
||||
}
|
||||
buffer[4] = (byte)buffer.length;
|
||||
|
||||
DatagramPacket packet = new DatagramPacket(buffer, buffer.length, xplaneAddr, xplanePort);
|
||||
outSocket.send(packet);
|
||||
socket.send(packet);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -236,9 +221,9 @@ public class XPlaneConnect implements AutoCloseable
|
||||
* @return A byte array representing data dependent on the dref requested.
|
||||
* @throws IOException If either the request or the response fails.
|
||||
*/
|
||||
public float[] requestDREF(String dref) throws IOException
|
||||
public float[] getDREF(String dref) throws IOException
|
||||
{
|
||||
return requestDREFs(new String[]{dref})[0];
|
||||
return getDREFs(new String[] {dref})[0];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -248,7 +233,7 @@ public class XPlaneConnect implements AutoCloseable
|
||||
* @return A multidimensional array representing the data for each requested dref.
|
||||
* @throws IOException If either the request or the response fails.
|
||||
*/
|
||||
public float[][] requestDREFs(String[] drefs) throws IOException
|
||||
public float[][] getDREFs(String[] drefs) throws IOException
|
||||
{
|
||||
//Preconditions
|
||||
if(drefs == null || drefs.length == 0)
|
||||
@@ -329,7 +314,7 @@ public class XPlaneConnect implements AutoCloseable
|
||||
/**
|
||||
* Sends a command to X-Plane that sets the given DREF.
|
||||
*
|
||||
* @param dref The name of the DREF to set.
|
||||
* @param dref The name of the X-Plane dataref to set.
|
||||
* @param value An array of floating point values whose structure depends on the dref specified.
|
||||
* @throws IOException If the command cannot be sent.
|
||||
*/
|
||||
@@ -375,33 +360,33 @@ public class XPlaneConnect implements AutoCloseable
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends command to X-Plane setting control surfaces on the player aircraft.
|
||||
* Sends command to X-Plane setting control surfaces on the player ac.
|
||||
*
|
||||
* @param ctrl <p>An array containing zero to six values representing control surface data as follows:</p>
|
||||
* <ol>
|
||||
* <li>Latitudinal Stick [-1,1]</li>
|
||||
* <li>Longitudinal Stick [-1,1]</li>
|
||||
* <li>Rudder Pedals [-1, 1]</li>
|
||||
* <li>Throttle [-1, 1]</li>
|
||||
* <li>Gear (0=up, 1=down)</li>
|
||||
* <li>Flaps [0, 1]</li>
|
||||
* </ol>
|
||||
* <p>
|
||||
* If @{code ctrl} is less than 6 elements long, The missing elements will not be changed. To
|
||||
* change values in the middle of the array without affecting the preceding values, set the
|
||||
* preceding values to -998.
|
||||
* </p>
|
||||
* @param values <p>An array containing zero to six values representing control surface data as follows:</p>
|
||||
* <ol>
|
||||
* <li>Latitudinal Stick [-1,1]</li>
|
||||
* <li>Longitudinal Stick [-1,1]</li>
|
||||
* <li>Rudder Pedals [-1, 1]</li>
|
||||
* <li>Throttle [-1, 1]</li>
|
||||
* <li>Gear (0=up, 1=down)</li>
|
||||
* <li>Flaps [0, 1]</li>
|
||||
* </ol>
|
||||
* <p>
|
||||
* If @{code ctrl} is less than 6 elements long, The missing elements will not be changed. To
|
||||
* change values in the middle of the array without affecting the preceding values, set the
|
||||
* preceding values to -998.
|
||||
* </p>
|
||||
* @throws IOException If the command cannot be sent.
|
||||
*/
|
||||
public void sendCTRL(float[] ctrl) throws IOException
|
||||
public void sendCTRL(float[] values) throws IOException
|
||||
{
|
||||
sendCTRL(ctrl, 0);
|
||||
sendCTRL(values, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends command to X-Plane setting control surfaces on the specified aircraft.
|
||||
* Sends command to X-Plane setting control surfaces on the specified ac.
|
||||
*
|
||||
* @param ctrl <p>An array containing zero to six values representing control surface data as follows:</p>
|
||||
* @param values <p>An array containing zero to six values representing control surface data as follows:</p>
|
||||
* <ol>
|
||||
* <li>Latitudinal Stick [-1,1]</li>
|
||||
* <li>Longitudinal Stick [-1,1]</li>
|
||||
@@ -415,23 +400,23 @@ public class XPlaneConnect implements AutoCloseable
|
||||
* change values in the middle of the array without affecting the preceding values, set the
|
||||
* preceding values to -998.
|
||||
* </p>
|
||||
* @param aircraft The aircraft to set. 0 for the player's aircraft.
|
||||
* @param ac The ac to set. 0 for the player's ac.
|
||||
* @throws IOException If the command cannot be sent.
|
||||
*/
|
||||
public void sendCTRL(float[] ctrl, int aircraft) throws IOException
|
||||
public void sendCTRL(float[] values, int ac) throws IOException
|
||||
{
|
||||
//Preconditions
|
||||
if(ctrl == null)
|
||||
if(values == null)
|
||||
{
|
||||
throw new IllegalArgumentException("ctrl must no be null.");
|
||||
}
|
||||
if(ctrl.length > 6)
|
||||
if(values.length > 6)
|
||||
{
|
||||
throw new IllegalArgumentException("ctrl must have 6 or fewer elements.");
|
||||
}
|
||||
if(aircraft < 0 || aircraft > 9)
|
||||
if(ac < 0 || ac > 9)
|
||||
{
|
||||
throw new IllegalArgumentException("aircraft must be non-negative and less than 9.");
|
||||
throw new IllegalArgumentException("ac must be non-negative and less than 9.");
|
||||
}
|
||||
|
||||
//Pad command values and convert to bytes
|
||||
@@ -439,16 +424,16 @@ public class XPlaneConnect implements AutoCloseable
|
||||
int cur = 0;
|
||||
ByteBuffer bb = ByteBuffer.allocate(22);
|
||||
bb.order(ByteOrder.LITTLE_ENDIAN);
|
||||
for(i = 0; i < ctrl.length; ++i)
|
||||
for(i = 0; i < values.length; ++i)
|
||||
{
|
||||
if(i == 4)
|
||||
{
|
||||
bb.put(cur, (byte) ctrl[i]);
|
||||
bb.put(cur, (byte) values[i]);
|
||||
cur += 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
bb.putFloat(cur, ctrl[i]);
|
||||
bb.putFloat(cur, values[i]);
|
||||
cur += 4;
|
||||
}
|
||||
}
|
||||
@@ -465,7 +450,7 @@ public class XPlaneConnect implements AutoCloseable
|
||||
cur += 4;
|
||||
}
|
||||
}
|
||||
bb.put(cur, (byte) aircraft);
|
||||
bb.put(cur, (byte) ac);
|
||||
|
||||
//Build and send message
|
||||
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
||||
@@ -476,11 +461,11 @@ public class XPlaneConnect implements AutoCloseable
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the position of the player aircraft.
|
||||
* Sets the position of the player ac.
|
||||
*
|
||||
* @param posi <p>An array containing position elements as follows:</p>
|
||||
* @param values <p>An array containing position elements as follows:</p>
|
||||
* <ol>
|
||||
* <li>Latitiude (deg)</li>
|
||||
* <li>Latitude (deg)</li>
|
||||
* <li>Longitude (deg)</li>
|
||||
* <li>Altitude (m above MSL)</li>
|
||||
* <li>Roll (deg)</li>
|
||||
@@ -495,17 +480,17 @@ public class XPlaneConnect implements AutoCloseable
|
||||
* </p>
|
||||
* @throws IOException If the command can not be sent.
|
||||
*/
|
||||
public void sendPOSI(float[] posi) throws IOException
|
||||
public void sendPOSI(float[] values) throws IOException
|
||||
{
|
||||
sendPOSI(posi, 0);
|
||||
sendPOSI(values, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the position of the specified aircraft.
|
||||
* Sets the position of the specified ac.
|
||||
*
|
||||
* @param posi <p>An array containing position elements as follows:</p>
|
||||
* @param values <p>An array containing position elements as follows:</p>
|
||||
* <ol>
|
||||
* <li>Latitiude (deg)</li>
|
||||
* <li>Latitude (deg)</li>
|
||||
* <li>Longitude (deg)</li>
|
||||
* <li>Altitude (m above MSL)</li>
|
||||
* <li>Roll (deg)</li>
|
||||
@@ -518,32 +503,32 @@ public class XPlaneConnect implements AutoCloseable
|
||||
* change values in the middle of the array without affecting the preceding values, set the
|
||||
* preceding values to -998.
|
||||
* </p>
|
||||
* @param aircraft The aircraft to set. 0 for the player aircraft.
|
||||
* @param ac The ac to set. 0 for the player ac.
|
||||
* @throws IOException If the command can not be sent.
|
||||
*/
|
||||
public void sendPOSI(float[] posi, int aircraft) throws IOException
|
||||
public void sendPOSI(float[] values, int ac) throws IOException
|
||||
{
|
||||
//Preconditions
|
||||
if(posi == null)
|
||||
if(values == null)
|
||||
{
|
||||
throw new IllegalArgumentException("posi must no be null.");
|
||||
}
|
||||
if(posi.length > 7)
|
||||
if(values.length > 7)
|
||||
{
|
||||
throw new IllegalArgumentException("posi must have 7 or fewer elements.");
|
||||
}
|
||||
if(aircraft < 0 || aircraft > 255)
|
||||
if(ac < 0 || ac > 255)
|
||||
{
|
||||
throw new IllegalArgumentException("aircraft must be between 0 and 255.");
|
||||
throw new IllegalArgumentException("ac must be between 0 and 255.");
|
||||
}
|
||||
|
||||
//Pad command values and convert to bytes
|
||||
int i;
|
||||
ByteBuffer bb = ByteBuffer.allocate(28);
|
||||
bb.order(ByteOrder.LITTLE_ENDIAN);
|
||||
for(i = 0; i < posi.length; ++i)
|
||||
for(i = 0; i < values.length; ++i)
|
||||
{
|
||||
bb.putFloat(i * 4, posi[i]);
|
||||
bb.putFloat(i * 4, values[i]);
|
||||
}
|
||||
for(; i < 7; ++i)
|
||||
{
|
||||
@@ -554,11 +539,41 @@ public class XPlaneConnect implements AutoCloseable
|
||||
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
||||
os.write("POSI".getBytes(StandardCharsets.UTF_8));
|
||||
os.write(0xFF); //Placeholder for message length
|
||||
os.write(aircraft);
|
||||
os.write(ac);
|
||||
os.write(bb.array());
|
||||
sendUDP(os.toByteArray());
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads X-Plane data
|
||||
*
|
||||
* @return The data read.
|
||||
* @throws IOException If the read operation fails.
|
||||
*/
|
||||
public float[][] readData() throws IOException
|
||||
{
|
||||
byte[] buffer = readUDP();
|
||||
ByteBuffer bb = ByteBuffer.wrap(buffer);
|
||||
int cur = 5;
|
||||
int len = bb.get(cur++);
|
||||
float[][] result = new float[bb.get(len)][9];
|
||||
for(int i = 0; i < len; ++i)
|
||||
{
|
||||
for(int j = 0; j < 9; ++j)
|
||||
{
|
||||
result[i][j] = bb.getFloat(cur);
|
||||
cur += 4;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends data to X-Plane
|
||||
*
|
||||
* @param data The data to send.
|
||||
* @throws IOException If the command cannot be sent.
|
||||
*/
|
||||
public void sendDATA(float[][] data) throws IOException
|
||||
{
|
||||
//Preconditions
|
||||
@@ -594,6 +609,36 @@ public class XPlaneConnect implements AutoCloseable
|
||||
sendUDP(os.toByteArray());
|
||||
}
|
||||
|
||||
/**
|
||||
* Selects what data X-Plane will export over UDP.
|
||||
*
|
||||
* @param rows The row numbers to select.
|
||||
* @throws IOException If the command cannot be sent.
|
||||
*/
|
||||
public void selectDATA(int[] rows) throws IOException
|
||||
{
|
||||
//Preconditions
|
||||
if(rows == null || rows.length == 0)
|
||||
{
|
||||
throw new IllegalArgumentException("rows must be a non-null, non-empty array.");
|
||||
}
|
||||
|
||||
//Convert data to bytes
|
||||
ByteBuffer bb = ByteBuffer.allocate(4 * rows.length);
|
||||
bb.order(ByteOrder.LITTLE_ENDIAN);
|
||||
for(int i = 0; i < rows.length; ++i)
|
||||
{
|
||||
bb.putInt(i * 4, rows[i]);
|
||||
}
|
||||
|
||||
//Build and send message
|
||||
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
||||
os.write("DSEL".getBytes(StandardCharsets.UTF_8));
|
||||
os.write(0xFF); //Placeholder for message length
|
||||
os.write(bb.array());
|
||||
sendUDP(os.toByteArray());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a message to be displayed on the screen in X-Plane at the default screen location.
|
||||
*
|
||||
@@ -643,6 +688,15 @@ public class XPlaneConnect implements AutoCloseable
|
||||
sendUDP(os.toByteArray());
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds, removes, or clears a set of waypoints. If the command is clear, the points are ignored
|
||||
* and all points are removed.
|
||||
*
|
||||
* @param op The operation to perform.
|
||||
* @param points An array of values representing points. Each triplet in the array will be
|
||||
* interpreted as a (Lat, Lon, Alt) point.
|
||||
* @throws IOException If the command cannot be sent.
|
||||
*/
|
||||
public void sendWYPT(WaypointOp op, float[] points) throws IOException
|
||||
{
|
||||
//Preconditions
|
||||
@@ -650,6 +704,10 @@ public class XPlaneConnect implements AutoCloseable
|
||||
{
|
||||
throw new IllegalArgumentException("points.length should be divisible by 3.");
|
||||
}
|
||||
if(points.length / 3 > 255)
|
||||
{
|
||||
throw new IllegalArgumentException("Too many points. Must be less than 256.");
|
||||
}
|
||||
|
||||
//Convert points to bytes
|
||||
ByteBuffer bb = ByteBuffer.allocate(4 * points.length);
|
||||
@@ -672,12 +730,12 @@ public class XPlaneConnect implements AutoCloseable
|
||||
/**
|
||||
* Sets the port on which the client will receive data from X-Plane.
|
||||
*
|
||||
* @param recvPort The new incoming port number.
|
||||
* @throws IOException If the command cannnot be sent.
|
||||
* @param port The new incoming port number.
|
||||
* @throws IOException If the command cannot be sent.
|
||||
*/
|
||||
public void setCONN(int recvPort) throws IOException
|
||||
public void setCONN(int port) throws IOException
|
||||
{
|
||||
if(recvPort < 0 || recvPort >= 0xFFFF)
|
||||
if(port < 0 || port >= 0xFFFF)
|
||||
{
|
||||
throw new IllegalArgumentException("Invalid port (must be non-negative and less than 65536).");
|
||||
}
|
||||
@@ -685,13 +743,14 @@ public class XPlaneConnect implements AutoCloseable
|
||||
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
||||
os.write("CONN".getBytes(StandardCharsets.UTF_8));
|
||||
os.write(0xFF); //Placeholder for message length
|
||||
os.write((byte) recvPort);
|
||||
os.write((byte) (recvPort >> 8));
|
||||
os.write((byte) port);
|
||||
os.write((byte) (port >> 8));
|
||||
sendUDP(os.toByteArray());
|
||||
|
||||
int soTimeout = inSocket.getSoTimeout();
|
||||
inSocket.close();
|
||||
inSocket = new DatagramSocket(recvPort);
|
||||
inSocket.setSoTimeout(soTimeout);
|
||||
int soTimeout = socket.getSoTimeout();
|
||||
socket.close();
|
||||
socket = new DatagramSocket(port);
|
||||
socket.setSoTimeout(soTimeout);
|
||||
readUDP(); // Try to read response
|
||||
}
|
||||
}
|
||||
|
||||
BIN
MATLAB/+XPlaneConnect/XPlaneConnect.jar
Normal file
BIN
MATLAB/+XPlaneConnect/XPlaneConnect.jar
Normal file
Binary file not shown.
@@ -1,33 +0,0 @@
|
||||
function socket = clearUDPBuffer(socket,varargin)
|
||||
% clearUDPBuffer Script that clears an UDP Socket Buffer by closing and
|
||||
% reopening the socket
|
||||
%
|
||||
% Inputs
|
||||
% Socket: UDP Socket to be cleared
|
||||
%
|
||||
% Outputs
|
||||
% Socket: UDP Socket
|
||||
%
|
||||
% Use
|
||||
% 1. import XPlaneConnect.*;
|
||||
% 2. Socket = openUDP(49005);
|
||||
% 3. Socket = clearUDPBuffer(Socket);
|
||||
%
|
||||
% Contributors
|
||||
% [CT] Christopher Teubert (SGT, Inc.)
|
||||
% christopher.a.teubert@nasa.gov
|
||||
%
|
||||
% To Do
|
||||
% 1. Verify Input
|
||||
%
|
||||
% BEGIN CODE
|
||||
|
||||
import XPlaneConnect.*
|
||||
|
||||
%% Close and reopen socket
|
||||
if ~socket.isClosed()
|
||||
port = socket.getLocalPort(); %get port of socket
|
||||
socket.close; %Close Socket
|
||||
socket = openUDP(port,varargin); %open new socket
|
||||
end
|
||||
end
|
||||
@@ -1,28 +1,31 @@
|
||||
function [socket] = closeUDP(socket)
|
||||
% closeUDP Script that closes a UDP Socket
|
||||
function closeUDP(socket)
|
||||
% closeUDP Closes the specified connection and releases resources associated with it.
|
||||
%
|
||||
% Inputs
|
||||
% Socket: UDP Socket to be closed
|
||||
%
|
||||
% Outputs
|
||||
% Socket: Closed Socket
|
||||
% socket: An XPC client to close
|
||||
%
|
||||
% Use
|
||||
% 1. import XPlaneConnect.*;
|
||||
% 2. Socket = openUDP(49005);
|
||||
% 3. Status = closeUDP(Socket);
|
||||
% 2. socket = openUDP();
|
||||
% 3. closeUDP(socket);
|
||||
%
|
||||
% Contributors
|
||||
% [CT] Christopher Teubert (SGT, Inc.)
|
||||
% christopher.a.teubert@nasa.gov
|
||||
%
|
||||
% To Do
|
||||
% 1. Verify Input
|
||||
%
|
||||
% BEGIN CODE
|
||||
% [JW] Jason Watkins
|
||||
% jason.w.watkins@nasa.gov
|
||||
|
||||
%% Close the socket
|
||||
assert(isequal(class(socket), 'gov.nasa.xpc.XPlaneConnect'),...
|
||||
'[closeUDP] ERROR: socket was not an XPC client.');
|
||||
socket.close;
|
||||
|
||||
assert(isequal(socket.isClosed(),1),'closeUDP: Error- Could not close socket');
|
||||
%% Track open clients
|
||||
global clients;
|
||||
for i = 1:length(clients)
|
||||
if socket == clients(i)
|
||||
clients = [clients(1:i-1) clients(i+1:length(clients))];
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
38
MATLAB/+XPlaneConnect/getDREFs.m
Normal file
38
MATLAB/+XPlaneConnect/getDREFs.m
Normal file
@@ -0,0 +1,38 @@
|
||||
function result = getDREFs( drefs, socket )
|
||||
%requestDREF request the value of a specific DataRef from X-Plane over UDP
|
||||
%
|
||||
%Inputs
|
||||
% drefs: Cell Array of DataRefs to be requested
|
||||
% socket (optional): The client to use when sending the command.
|
||||
%Outputs
|
||||
% result: cell array of resulting data.
|
||||
%
|
||||
%Use
|
||||
% 1. import XPlaneConnect.*;
|
||||
% 2. socket = opendUDP();
|
||||
% 3. drefs = {'sim/cockpit2/controls/yoke_heading_ratio','sim/cockpit2/controls/yoke_roll_ratio'};
|
||||
% 4. result = requestDREF(drefs, socket);
|
||||
%
|
||||
% Contributors
|
||||
% [CT] Christopher Teubert (SGT, Inc.)
|
||||
% christopher.a.teubert@nasa.gov
|
||||
% [JW] Jason Watkins
|
||||
% jason.w.watkins@nasa.gov
|
||||
|
||||
import XPlaneConnect.*
|
||||
|
||||
%% Get client
|
||||
global clients;
|
||||
if ~exist('socket', 'var')
|
||||
assert(isequal(length(clients) < 2, 1), '[getDREFs] ERROR: Multiple clients open. You must specify which client to use.');
|
||||
if isempty(clients)
|
||||
socket = openUDP();
|
||||
else
|
||||
socket = clients(1);
|
||||
end
|
||||
end
|
||||
|
||||
%% Send command
|
||||
result = socket.getDREFs(drefs);
|
||||
|
||||
end
|
||||
@@ -1,41 +1,42 @@
|
||||
function [socket] = openUDP(port, varargin)
|
||||
%openUDP Script that opens an UDP Socket
|
||||
function [ socket ] = openUDP(varargin)
|
||||
%openUDP Initializes a new instance of the XPC client and returns it.
|
||||
%
|
||||
%Inputs
|
||||
% port: UDP Port for socket
|
||||
% xpHost: The network host on which X-Plane is running.
|
||||
% xpPort: The port on which the X-Plane Connect plugin is listening.
|
||||
% port: The local port to use when sending and receiving data from XPC.
|
||||
% timeout (optional): Optional parameter for time to UDP timeout (in ms)
|
||||
%Outputs
|
||||
% Socket: UDP Socket
|
||||
% socket: An instance of the XPC client.
|
||||
%
|
||||
% Use
|
||||
% 1. import XPlaneConnect.*;
|
||||
% 2. Socket = openUDP(49005); %Open socket at port 49005 with timeout=0.1 sec
|
||||
% 2. socket = openUDP(); % Open a socket using the default settings
|
||||
% or
|
||||
% 2. Socket = openUDP(49005); %Open socket at port 49005 with timeout=0.2 sec
|
||||
% 2. Socket = openUDP('127.0.0.1', 49008, 49005); % Open a socket to connect to X-Plane on the local machine and receive data on port 49005
|
||||
%
|
||||
% Contributors
|
||||
% [CT] Christopher Teubert (SGT, Inc.)
|
||||
% christopher.a.teubert@nasa.gov
|
||||
%
|
||||
% To Do
|
||||
% 1. Verify Input
|
||||
%
|
||||
% BEGIN CODE
|
||||
% [JW] Jason Watkins
|
||||
% jason.w.watkins@nasa.gov
|
||||
|
||||
import java.net.DatagramSocket
|
||||
%% Handle input
|
||||
p = inputParser;
|
||||
addOptional(p,'xpHost','127.0.0.1',@ischar);
|
||||
addOptional(p,'xpPort',49009,@isnumeric);
|
||||
addOptional(p,'port',0,@isnumeric);
|
||||
parse(p,varargin{:});
|
||||
|
||||
%% create socket
|
||||
socket = DatagramSocket(port);
|
||||
socket.setSoTimeout(100);
|
||||
socket.setReceiveBufferSize(2000);
|
||||
|
||||
%% interpret input
|
||||
if ~isempty(varargin)
|
||||
if isnumeric(varargin(1))
|
||||
socket.setSoTimeout(varargin(1));
|
||||
end
|
||||
%% Create client
|
||||
if ~exist('gov.nasa.xpc.XPlaneConnect', 'class')
|
||||
[folder, ~, ~] = fileparts(which('XPlaneConnect.openUDP'));
|
||||
javaaddpath(fullfile(folder, 'XPlaneConnect.jar'));
|
||||
end
|
||||
socket = gov.nasa.xpc.XPlaneConnect(p.Results.xpHost, p.Results.xpPort, p.Results.port);
|
||||
|
||||
assert(isequal(socket.isClosed(),0),'openUDP: Error- Could not open port');
|
||||
%% Track open clients
|
||||
global clients;
|
||||
clients = [clients, socket];
|
||||
|
||||
end
|
||||
end
|
||||
@@ -1,13 +1,9 @@
|
||||
function status = pauseSim( pause, varargin )
|
||||
%pauseSim pause Simulation
|
||||
function pauseSim( pause, socket )
|
||||
%pauseSim Pauses or unpauses X-Plane.
|
||||
%
|
||||
%Inputs
|
||||
% Pause: binary value 0=run, 1=pause
|
||||
% IP Address (optional): IP Address of the machine that will receive the data as a character array. Default is '127.0.0.1' (local machine)
|
||||
% port (optional): Port on the receiving machine where the data will be sent. Default is 49009 (XPlaneConnect). In general use 49009 to send to the plugin
|
||||
%
|
||||
%Outputs
|
||||
% status: If there was an error. Status<0 means there was an error.
|
||||
% pause: binary value 0=run, 1=pause
|
||||
% socket (optional): The client to use when sending the command.
|
||||
%
|
||||
%Use
|
||||
% 1. import XPlaneConnect.*;
|
||||
@@ -16,29 +12,26 @@ function status = pauseSim( pause, varargin )
|
||||
% Contributors
|
||||
% [CT] Christopher Teubert (SGT, Inc.)
|
||||
% christopher.a.teubert@nasa.gov
|
||||
%
|
||||
% To Do
|
||||
% 1. Verify Input
|
||||
%
|
||||
%BEGIN CODE
|
||||
% [JW] Jason Watkins
|
||||
% jason.w.watkins@nasa.gov
|
||||
|
||||
import XPlaneConnect.*
|
||||
|
||||
%% Handle Input
|
||||
% Optional parameters
|
||||
p = inputParser;
|
||||
addRequired(p,'pause',@isnumeric);
|
||||
addOptional(p,'IP','127.0.0.1',@ischar);
|
||||
addOptional(p,'port',49009,@isnumeric);
|
||||
parse(p,pause,varargin{:});
|
||||
%% Get client
|
||||
global clients;
|
||||
if ~exist('socket', 'var')
|
||||
assert(isequal(length(clients) < 2, 1), '[pauseSim] ERROR: Multiple clients open. You must specify which client to use.');
|
||||
if isempty(clients)
|
||||
socket = openUDP();
|
||||
else
|
||||
socket = clients(1);
|
||||
end
|
||||
end
|
||||
|
||||
% Check format of input-TODO
|
||||
%% Validate input
|
||||
pause = logical(pause);
|
||||
|
||||
%% BODY
|
||||
message = zeros(1,6);
|
||||
|
||||
message(1:4) = 'SIMU'-0;
|
||||
message(6) = uint8(p.Results.pause);
|
||||
%% Send command
|
||||
socket.pauseSim(pause);
|
||||
|
||||
status = sendUDP(message, p.Results.IP, p.Results.port);
|
||||
end
|
||||
@@ -1,9 +1,8 @@
|
||||
function [ sensor ] = readDATA( socket )
|
||||
function [ result ] = readDATA( socket )
|
||||
% readDATA Reads UDP Socket and interprets data
|
||||
%
|
||||
% Inputs
|
||||
% location: Either an opened UDP Socket or integer port number
|
||||
%
|
||||
% socket (optional): The client to read from.
|
||||
% Outputs
|
||||
% If data is X-Plane data format:
|
||||
% data: Matlab X-Plane DATA Structure
|
||||
@@ -30,62 +29,30 @@ function [ sensor ] = readDATA( socket )
|
||||
% NOTE: sending in a port number instead of an opened socket clears the UDP buffer. This only works if the data is being sent at a fast rate. Sending in a UDP Socket reads the first packet in the buffer.
|
||||
%
|
||||
% Contributors
|
||||
% [CT] Christopher Teubert (SGT, Inc.)
|
||||
% christopher.a.teubert@nasa.gov
|
||||
%
|
||||
% To Do
|
||||
% 1. Verify Input
|
||||
%
|
||||
% BEGIN CODE
|
||||
% Christopher Teubert (SGT, Inc.) <christopher.a.teubert@nasa.gov>
|
||||
% Jason Watkins <jason.w.watkins@nasa.gov>
|
||||
|
||||
import XPlaneConnect.*
|
||||
import XPlaneConnect.*
|
||||
|
||||
%% Read UDP Socket
|
||||
[ sensor.raw] = readUDP(socket);
|
||||
|
||||
%% Interpret Input
|
||||
bits = size(sensor.raw);
|
||||
if sensor.raw ~= -998 %If the signal exists
|
||||
header = char(sensor.raw(1:4)');
|
||||
if strcmp(header,'DATA') %DATA signal type
|
||||
Values = floor((bits-5)/36);
|
||||
sensor.d = [];
|
||||
sensor.h = zeros(Values(1),1);
|
||||
for i=1:Values(1)
|
||||
sensor.h(i) = sensor.raw(6+(i-1)*36);
|
||||
sensor.d = [sensor.d; typecast(uint8(sensor.raw(10+(i-1)*36:5+i*36))','single')];
|
||||
end
|
||||
elseif strcmp(header,'STRU') %STRU signal type
|
||||
a = 6;
|
||||
while a<length(sensor.raw)
|
||||
strdim = sensor.raw(a);
|
||||
if strdim == 0
|
||||
break
|
||||
end
|
||||
fieldName = char(sensor.raw(a+1:a+strdim)');
|
||||
a = a+strdim+1;
|
||||
dim1 = sensor.raw(a);
|
||||
dim2 = sensor.raw(a+1);
|
||||
if dim1 == 0 %String
|
||||
value = char(sensor.raw(a+2:a+1+dim2))';
|
||||
a = a + dim2 + 2;
|
||||
else
|
||||
value = [];
|
||||
for i=1:dim1
|
||||
value(i,:) = typecast(uint8(sensor.raw(a+2+(i-1)*dim2*4:a+1+i*dim2*4))','single');
|
||||
end
|
||||
a = a + dim1*dim2*4+2;
|
||||
end
|
||||
sensor.(fieldName) = value;
|
||||
end
|
||||
elseif strcmp(header,'OTHR')
|
||||
sensor.d = sensor.raw(6:end);
|
||||
else %Other signal type
|
||||
sensor.d = sensor.raw;
|
||||
end
|
||||
else %No Signal
|
||||
sensor.d = -998;
|
||||
%% Get client
|
||||
global clients;
|
||||
if ~exist('socket', 'var')
|
||||
assert(istrue(length(clients) < 2), '[readDATA] ERROR: Multiple clients open. You must specify which client to use.');
|
||||
if isempty(clients)
|
||||
socket = openUDP();
|
||||
else
|
||||
socket = clients(1);
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
%% Get data
|
||||
result.raw = socket.readDATA();
|
||||
|
||||
%% Format data
|
||||
rows = (length(result.raw) - 5) / 9;
|
||||
result.h = zeroes(rows);
|
||||
for i=1:rows
|
||||
j = 6 + (i - 1) * 9;
|
||||
result.h(i) = result.rows(j);
|
||||
result.d = [result.d; result.rows((j+1):(j+9))];
|
||||
end
|
||||
@@ -1,83 +0,0 @@
|
||||
function [ data ] = readUDP( varargin )
|
||||
%readUDP Read Array from UDP Socket
|
||||
%
|
||||
% Inputs
|
||||
% input: Either an opened UDP Socket or integer port number
|
||||
%
|
||||
% Outputs
|
||||
% data: UDP uint8 Array. Equal to -998 in the case of an error
|
||||
%
|
||||
% Use
|
||||
% 1. import XPlaneConnect.*;
|
||||
% 2. socket = openUDP(49005);
|
||||
% 3. data = readUDP(socket);
|
||||
% 4. status = closeUDP(socket);
|
||||
%
|
||||
% or
|
||||
%
|
||||
% 1. import XPlaneConnect.*;
|
||||
% 2. data = readUDP(49005);
|
||||
%
|
||||
% NOTE: sending in a port number instead of an opened socket clears the
|
||||
%UDP buffer. This only works if the data is being sent at a fast rate.
|
||||
%Sending in a UDP Socket reads the first packet in the buffer.
|
||||
%
|
||||
% Contributors
|
||||
% [CT] Christopher Teubert (SGT, Inc.)
|
||||
% christopher.a.teubert@nasa.gov
|
||||
%
|
||||
% To Do
|
||||
% 1. Verify Input
|
||||
%
|
||||
% BEGIN CODE
|
||||
|
||||
import XPlaneConnect.*
|
||||
import java.net.DatagramPacket
|
||||
bits = 2000;
|
||||
|
||||
%% Interpret Input
|
||||
global udpReadPort;
|
||||
if isempty(varargin)
|
||||
if isempty(udpReadPort)
|
||||
udpReadPort = 49008;
|
||||
end
|
||||
socket = openUDP(udpReadPort);
|
||||
ownSocket = 1;
|
||||
else
|
||||
socket = varargin{1};
|
||||
ownSocket = 0;
|
||||
if isnumeric(varargin{1})
|
||||
socket=openUDP(varargin{1});
|
||||
ownSocket = 1;
|
||||
end
|
||||
end
|
||||
|
||||
%% Try reading packet
|
||||
try
|
||||
packet = DatagramPacket(zeros(1,bits,'int8'),bits);
|
||||
socket.receive(packet)
|
||||
data = packet.getData;
|
||||
|
||||
data = int16(data);
|
||||
data(data(:)<0) = uint8(data(data(:)<0) + 256); %fix signed issue
|
||||
size = int16(data(5)); %size of data stream
|
||||
|
||||
%% trim trailing data
|
||||
for i=1:floor(length(data)/256)+1
|
||||
if data(size+1:end)==0
|
||||
break
|
||||
end
|
||||
size = size + 256;
|
||||
end
|
||||
data = data(1:size);
|
||||
|
||||
catch err %Read Unsuccessful
|
||||
data = -998;
|
||||
end
|
||||
|
||||
%% Close Port (if opened in code)
|
||||
if ownSocket
|
||||
socket.close()
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,69 +0,0 @@
|
||||
function result = requestDREF( DREFArray, varargin )
|
||||
%requestDREF request the value of a specific DataRef from X-Plane over UDP
|
||||
%
|
||||
%Inputs
|
||||
% DREFArray: Cell Array of DataRefs to be requested
|
||||
% IP Address (optional): IP Address of the machine that will receive the data as a character array. Default is '127.0.0.1' (local machine)
|
||||
% port (optional): Port on the receiving machine where the data will be sent. Default is 49009 (XPlaneConnect). In general use 49009 to send to the plugin
|
||||
%
|
||||
%Outputs
|
||||
% result: cell array of resulting data where
|
||||
%
|
||||
%Use
|
||||
% 1. import XPlaneConnect.*;
|
||||
% 2. DREFArray = {'sim/cockpit2/controls/yoke_heading_ratio','sim/cockpit2/controls/yoke_roll_ratio'};
|
||||
% 3. result = requestDREF( DREFArray, '172.0.100.54' );
|
||||
%
|
||||
% Contributors
|
||||
% [CT] Christopher Teubert (SGT, Inc.)
|
||||
% christopher.a.teubert@nasa.gov
|
||||
%
|
||||
%BEGIN CODE
|
||||
|
||||
import XPlaneConnect.*
|
||||
|
||||
message = zeros(1,6);
|
||||
len = 7;
|
||||
status = -1; %#ok<NASGU> % no data
|
||||
|
||||
%% Handle Input
|
||||
p = inputParser;
|
||||
addRequired(p,'DREFArray');
|
||||
addOptional(p,'IP','127.0.0.1',@ischar);
|
||||
addOptional(p,'port',49009,@isnumeric);
|
||||
parse(p,DREFArray,varargin{:});
|
||||
|
||||
%% BODY
|
||||
% Header
|
||||
message(1:4) = 'GETD'-0;
|
||||
message(6) = length(p.Results.DREFArray);
|
||||
|
||||
% DREFS
|
||||
for i=1:length(p.Results.DREFArray)
|
||||
message(len) = length(p.Results.DREFArray{i});
|
||||
message(len+1:len+message(len)) = p.Results.DREFArray{i};
|
||||
len = len+1+message(len);
|
||||
end
|
||||
|
||||
% Send UDP
|
||||
status = sendUDP(message, p.Results.IP, p.Results.port);
|
||||
|
||||
% Look for response
|
||||
for i=1:40
|
||||
data = readUDP();
|
||||
if length(data) > 1 % Received Data
|
||||
status = 0;
|
||||
counter = 7;
|
||||
nArrays = data(6);
|
||||
result = cell(nArrays,1);
|
||||
for j=1:nArrays
|
||||
sizeArray = data(counter);
|
||||
result{j} = typecast(uint8(data(counter+1:counter+sizeArray*4))','single');
|
||||
counter = counter + 1 + sizeArray * 4;
|
||||
end
|
||||
break;
|
||||
else
|
||||
result = cell(0,1);
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,13 +1,9 @@
|
||||
function [ status ] = selectDATA( index, varargin )
|
||||
function selectDATA( rows, socket )
|
||||
% selectDATA Choose specific X-Plane parameters to be send over UDP
|
||||
%
|
||||
% Inputs
|
||||
% index: An array of the values that to be sent. Corresponds to the numbers on the XPlane Output screen
|
||||
% IP Address (optional): IP Address of the machine that will receive the data as a character array. Default is '127.0.0.1' (local machine)
|
||||
% port (optional): Port on the receiving machine where the data will be sent. Default is 49009 (XPlaneConnect). In general use 49009 to send to the plugin and 49005 to send to the x-plane udp
|
||||
%
|
||||
% Outputs
|
||||
% status: If there was an error. Status<0 means there was an error.
|
||||
% rows: An array of the values that to be sent. Corresponds to the numbers on the XPlane Output screen
|
||||
% socket (optional): The client to use when sending the command.
|
||||
%
|
||||
% Use
|
||||
% 1. import XPlaneConnect.*;
|
||||
@@ -15,29 +11,24 @@ function [ status ] = selectDATA( index, varargin )
|
||||
% 3. status = selectDATA( values, '127.0.0.1', 49005 ); % send to localhose port 49005
|
||||
%
|
||||
% Contributors
|
||||
% [CT] Christopher Teubert (SGT, Inc.)
|
||||
% christopher.a.teubert@nasa.gov
|
||||
%
|
||||
% To Do
|
||||
% 1. Verify Input
|
||||
%
|
||||
% BEGIN CODE
|
||||
% Christopher Teubert (SGT, Inc.) <christopher.a.teubert@nasa.gov>
|
||||
% Jason Watkins <jason.w.watkins@nasa.gov>
|
||||
|
||||
import XPlaneConnect.*
|
||||
|
||||
%% Handle Input
|
||||
p = inputParser;
|
||||
addRequired(p,'index');
|
||||
addOptional(p,'IP','127.0.0.1',@ischar);
|
||||
addOptional(p,'port',49009,@isnumeric);
|
||||
parse(p,index,varargin{:});
|
||||
|
||||
%% BODY
|
||||
dataString = ['DSEL'-0,0];
|
||||
for i=1:length(index)
|
||||
dataString = [dataString, p.Results.index(i), 0, 0, 0];
|
||||
%% Get client
|
||||
global clients;
|
||||
if ~exist('socket', 'var')
|
||||
assert(istrue(length(clients) < 2), '[selectDATA] ERROR: Multiple clients open. You must specify which client to use.');
|
||||
if isempty(clients)
|
||||
socket = openUDP();
|
||||
else
|
||||
socket = clients(1);
|
||||
end
|
||||
status = sendUDP(dataStream, p.Results.IP, p.Results.port);
|
||||
|
||||
end
|
||||
|
||||
%% Validate input
|
||||
rows = int32(rows);
|
||||
|
||||
%% Send command
|
||||
socket.selectDATA(rows);
|
||||
|
||||
@@ -1,64 +1,53 @@
|
||||
function [ status ] = sendCTRL( ctrl, acft, IP, port )
|
||||
% sendCTRL Send X-Plane Aircraft Control Commands over UDP
|
||||
function sendCTRL( values, ac, socket )
|
||||
% sendCTRL Sends command to X-Plane setting control surfaces on the specified aircraft.
|
||||
%
|
||||
% Inputs
|
||||
% ctrl: control array where the elements are as follows:
|
||||
% values: control array where the elements are as follows:
|
||||
% 1. Latitudinal Stick [-1,1]
|
||||
% 2. Longitudinal Stick [-1,1]
|
||||
% 3. Pedal [-1, 1]
|
||||
% 4. Throttle [-1, 1]
|
||||
% 5. Gear (0=up, 1=down)
|
||||
% 6. Flaps [0, 1]
|
||||
% acft (optional): Aircraft # (default is 0; 0 = own aircraft)
|
||||
% IP Address (optional): IP Address of the machine that will receive the data as a character array. Default is '127.0.0.1' (local machine)
|
||||
% port (optional): Port on the receiving machine where the data will be sent. Default is 49009 (XPlaneConnect). In general use 49009 to send to the plugin and 49005 to send to the x-plane udp
|
||||
% ac (optional): The aircraft to set. 0 for the player aircraft.
|
||||
% socket (optional): The client to use when sending the command.
|
||||
%
|
||||
% Outputs
|
||||
% status: If there was an error. Status<0 means there was an error.
|
||||
%
|
||||
% Use
|
||||
% 1. import XPlaneConnect.*;
|
||||
% 2. #Send the data array to port 49009 on the computer at IP address 172.0.100.54.
|
||||
% 3. status = sendCTRL([0, 0, 0, 0.8, 0, 1], 1, '172.0.100.54',49009);
|
||||
% 2. socket = openUDP();
|
||||
% 3. status = sendCTRL([0, 0, 0, 0.8, 0, 1], 0, socket); % Set throttle and flaps on the player aircraft.
|
||||
%
|
||||
% Note: send the value -998 to not overwrite that parameter. That is, if -998 is sent, the parameter will stay at the current X-Plane value
|
||||
% Note: send the value -998 to not overwrite that parameter. That is, if
|
||||
% -998 is sent, the parameter will stay at the current X-Plane value.
|
||||
%
|
||||
% Contributors
|
||||
% [CT] Christopher Teubert (SGT, Inc.)
|
||||
% christopher.a.teubert@nasa.gov
|
||||
%
|
||||
% To Do
|
||||
% 1. Verify Input
|
||||
%
|
||||
% BEGIN CODE
|
||||
% Christopher Teubert (SGT, Inc.) <christopher.a.teubert@nasa.gov>
|
||||
% Jason Watkins <jason.w.watkins@nasa.gov>
|
||||
|
||||
import XPlaneConnect.*
|
||||
|
||||
%% Handle Input
|
||||
% Optional parameters
|
||||
if ~exist('IP','var'), IP = '127.0.0.1'; end
|
||||
if ~exist('port','var'), port = 49009; end
|
||||
if ~exist('acft','var'), acft = 0; end
|
||||
|
||||
% Check format of input-TODO
|
||||
|
||||
%%BODY
|
||||
header = ['CTRL'-0,0];
|
||||
dataStream = header; %TODO-ADD ACFT
|
||||
|
||||
% Deal with position update
|
||||
control = [-998.5, -998.5, -998.5, -998.5, -998.5, -998.5];
|
||||
|
||||
for i=1:min(length(ctrl),length(control))
|
||||
control(i) = ctrl(i);
|
||||
%% Get client
|
||||
global clients;
|
||||
if ~exist('socket', 'var')
|
||||
assert(isequal(length(clients) < 2, 1), '[sendCTRL] ERROR: Multiple clients open. You must specify which client to use.');
|
||||
if isempty(clients)
|
||||
socket = openUDP();
|
||||
else
|
||||
socket = clients(1);
|
||||
end
|
||||
dataStream = [dataStream, typecast(single(control(1:4)),'uint8')];
|
||||
dataStream = [dataStream, uint8(control(5))];
|
||||
dataStream = [dataStream, typecast(single(control(6)),'uint8')];
|
||||
dataStream = [dataStream, uint8(acft)];
|
||||
|
||||
% Send DATA
|
||||
status = sendUDP(dataStream, IP, port);
|
||||
|
||||
end
|
||||
|
||||
%% Validate input
|
||||
values = single(values);
|
||||
if ~exist('ac', 'var')
|
||||
ac = 0;
|
||||
end
|
||||
ac = logical(ac);
|
||||
|
||||
%% Send command
|
||||
socket.sendCTRL(values, ac);
|
||||
|
||||
end
|
||||
@@ -1,15 +1,11 @@
|
||||
function [ status ] = sendDATA(data, varargin)
|
||||
function sendDATA(data, socket)
|
||||
% sendDATA Send X-Plane formatted DATA over UDP
|
||||
%
|
||||
% Inputs
|
||||
% data: X-Plane formatted data. Is a matlab structure with the following fields:
|
||||
% .h: Header array containing header numbers corresponding to values in the X-Plane UDP Data screen.
|
||||
% .d: 2-D Data array. Each row contains eight values corresponding to the header value (.h(1) corresponds to .d(1,:))
|
||||
% IP Address (optional): IP Address of the machine that will receive the data as a character array. Default is '127.0.0.1' (local machine)
|
||||
% port (optional): Port on the receiving machine where the data will be sent . Default is 49009 (XPlaneConnect). In general use 49009 to send to the plugin and 49005 to send to the x-plane udp interface.
|
||||
%
|
||||
% Outputs
|
||||
% status: 0: no error, <0: error
|
||||
% socket (optional): The client to use when sending the command.
|
||||
%
|
||||
% Use
|
||||
% 1. import XPlaneConnect.*;
|
||||
@@ -29,29 +25,23 @@ function [ status ] = sendDATA(data, varargin)
|
||||
|
||||
import XPlaneConnect.*
|
||||
|
||||
%% Handle Input
|
||||
p = inputParser;
|
||||
addRequired(p,'data');
|
||||
addOptional(p,'IP','127.0.0.1',@ischar);
|
||||
addOptional(p,'port',49009,@isnumeric);
|
||||
parse(p,data,varargin{:});
|
||||
|
||||
%% BODY
|
||||
|
||||
header = ['DATA'-0,0];
|
||||
dataStream = header;
|
||||
|
||||
for i=1:length(p.Results.data.h)
|
||||
dataStream = [dataStream, p.Results.data.h(i), 0, 0, 0, typecast(single(p.Results.data.d(i,1:8)),'uint8')]; %#ok<AGROW>
|
||||
end
|
||||
|
||||
% Send DATA
|
||||
if length(dataStream) > 5
|
||||
status = sendUDP(dataStream, p.Results.IP, p.Results.port);
|
||||
%% Get client
|
||||
global clients;
|
||||
if ~exist('socket', 'var')
|
||||
assert(isequal(length(clients) < 2, 1), '[sendDATA] ERROR: Multiple clients open. You must specify which client to use.');
|
||||
if isempty(clients)
|
||||
socket = openUDP();
|
||||
else
|
||||
disp('Warning in sendDATA: Sending empty dataStream')
|
||||
status = -2;
|
||||
socket = clients(1);
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
%% Validate input
|
||||
javaData = [];
|
||||
for i = 1:length(data.h);
|
||||
javaData = [javaData; data.h(i) data.d(i, 1:8)];
|
||||
end
|
||||
|
||||
%% Send command
|
||||
socket.sendDATA(javaData);
|
||||
|
||||
|
||||
@@ -1,58 +1,38 @@
|
||||
function status = sendDREF( dataRef, Value, varargin )
|
||||
% sendDREF Send a command to change any DataRef in X-Plane over UDP. This requires the X-Plane Connect Plugin to be running
|
||||
function sendDREF( dref, value, socket )
|
||||
% sendDREF Sends a command to X-Plane that sets the given DREF.
|
||||
%
|
||||
% Inputs
|
||||
% dataRef: The X-Plane Dataref that will be chaged
|
||||
% Value: The value that the above dataref is set to
|
||||
% IP Address (optional): IP Address of the machine that will receive the data as a character array. Default is '127.0.0.1' (local machine)
|
||||
% port (optional): Port on the receiving machine where the data will be sent. Default is 49009 (XPlaneConnect). In general use 49009 to send to the plugin and 49005 to send to the x-plane udp
|
||||
%
|
||||
% Outputs
|
||||
% status: If there was an error. status<0 means there was an error.
|
||||
% dref: The name of the X-Plane dataref to set.
|
||||
% Value: An array of floating point values whose structure depends on the dref specified.
|
||||
% socket (optional): The client to use when sending the command.
|
||||
%
|
||||
% Use
|
||||
% 1. import XPlaneConnect.*
|
||||
% 2. dataRef = 'sim/aircraft/parts/acf_gear_deploy'; // Landing Gear
|
||||
% 3. Value = 0;
|
||||
% 4. status = sendDREF(dataRef, Value);
|
||||
% 4. status = setDREF(dataRef, Value);
|
||||
%
|
||||
% Contributors
|
||||
% [CT] Christopher Teubert (SGT, Inc.)
|
||||
% christopher.a.teubert@nasa.gov
|
||||
%
|
||||
% To Do
|
||||
% 1. Verify Input
|
||||
%
|
||||
% BEGIN CODE
|
||||
% [JW] Jason Watkins
|
||||
% jason.w.watkins@nasa.gov
|
||||
|
||||
import XPlaneConnect.*
|
||||
|
||||
status = 0;
|
||||
|
||||
%% Handle Input
|
||||
p = inputParser;
|
||||
addRequired(p,'dataRef');
|
||||
addRequired(p,'Value');
|
||||
addOptional(p,'IP','127.0.0.1',@ischar);
|
||||
addOptional(p,'port',49009,@isnumeric);
|
||||
parse(p,dataRef, Value ,varargin{:});
|
||||
%% Get client
|
||||
global clients;
|
||||
if ~exist('socket', 'var')
|
||||
assert(isequal(length(clients) < 2, 1), '[setDREF] ERROR: Multiple clients open. You must specify which client to use.');
|
||||
if isempty(clients)
|
||||
socket = openUDP();
|
||||
else
|
||||
socket = clients(1);
|
||||
end
|
||||
end
|
||||
|
||||
%% BODY
|
||||
dataStream = zeros(1,7+length(p.Results.dataRef)+length(p.Results.Value)*4);
|
||||
% Build Header
|
||||
dataStream(1:4) = 'DREF'-0;
|
||||
|
||||
% Add DREF
|
||||
dataStream(6) = uint8(length(p.Results.dataRef));
|
||||
len = 6+length(p.Results.dataRef);
|
||||
dataStream(7:len)=p.Results.dataRef-0;
|
||||
|
||||
% Add Value
|
||||
dataStream(len+1) =uint8(length(p.Results.Value));
|
||||
dataStream(len+2:end)=typecast(single(p.Results.Value),'uint8');
|
||||
%% Validate input
|
||||
value = single(value);
|
||||
|
||||
% Send DREF
|
||||
if length(dataStream) > 5
|
||||
status = sendUDP(dataStream, p.Results.IP, p.Results.port);
|
||||
end
|
||||
end
|
||||
%%Send command
|
||||
socket.sendDREF(dref, value);
|
||||
@@ -1,5 +1,5 @@
|
||||
function [ status ] = sendPOSI( posi, varargin )
|
||||
% sendPOSI Send X-Plane Aircraft Position over UDP
|
||||
function sendPOSI( posi, ac, socket )
|
||||
% sendPOSI Sets the position of the specified aircraft.
|
||||
%
|
||||
% Inputs
|
||||
% posi: Position array where the elements are as follows:
|
||||
@@ -10,52 +10,43 @@ function [ status ] = sendPOSI( posi, varargin )
|
||||
% 5. Pitch (deg)
|
||||
% 6. True Heading (deg)
|
||||
% 7. Gear (0=up, 1=down)
|
||||
% acft (optional): Aircraft # (default is 0; 0 = own aircraft)
|
||||
% IP Address (optional): IP Address of the machine that will receive the data as a character array. Default is '127.0.0.1' (local machine)
|
||||
% port (optional): Port on the receiving machine where the data will be sent. Default is 49009 (XPlaneConnect). In general use 49009 to send to the plugin and 49005 to send to the x-plane udp
|
||||
%
|
||||
% Outputs
|
||||
% status: If there was an error. Status<0 means there was an error.
|
||||
% acft (optional): The aircraft to set. 0 for the player aircraft.
|
||||
% socket (optional): The client to use when sending the command.
|
||||
%
|
||||
% Use
|
||||
% 1. import XPlaneConnect.*;
|
||||
% 2. #Send the data array to port 49009 on the computer at IP address 172.0.100.54.
|
||||
% 3. status = sendPOSI([37.5242422, -122.06899, 2500, 0, 0, 0, 1], 1, '172.0.100.54');
|
||||
% 1. import XPlaneConnect.*;
|
||||
% 2. sendPOSI([37.5242422, -122.06899, 2500, 0, 0, 0, 1], 1);
|
||||
%
|
||||
% Note: send the value -998 to not overwrite that parameter. That is, if -998 is sent, the parameter will stay at the current X-Plane value
|
||||
% Note: send the value -998 to not overwrite that parameter. That is, if
|
||||
% -998 is sent, the parameter will stay at the current X-Plane value.
|
||||
%
|
||||
% Contributors
|
||||
% [CT] Christopher Teubert (SGT, Inc.)
|
||||
% christopher.a.teubert@nasa.gov
|
||||
%
|
||||
% To Do
|
||||
%
|
||||
% BEGIN CODE
|
||||
% [JW] Jason Watkins
|
||||
% jason.w.watkins@nasa.gov
|
||||
|
||||
import XPlaneConnect.*
|
||||
|
||||
%% Handle Input
|
||||
p = inputParser;
|
||||
addRequired(p,'posi');
|
||||
addOptional(p,'acft',0,@isnumeric);
|
||||
addOptional(p,'IP','127.0.0.1',@ischar);
|
||||
addOptional(p,'port',49009,@isnumeric);
|
||||
parse(p,posi,varargin{:});
|
||||
|
||||
%% BODY
|
||||
header = ['POSI'-0,0];
|
||||
dataStream = [header, p.Results.acft];
|
||||
|
||||
% Deal with position update
|
||||
position = [37.4185718,-121.935565,500,0,0,0, 0];
|
||||
|
||||
for i=1:min(length(position),length(p.Results.posi))
|
||||
position(i) = p.Results.posi(i);
|
||||
%% Get client
|
||||
global clients;
|
||||
if ~exist('socket', 'var')
|
||||
assert(isequal(length(clients) < 2, 1), '[sendPOSI] ERROR: Multiple clients open. You must specify which client to use.');
|
||||
if isempty(clients)
|
||||
socket = openUDP();
|
||||
else
|
||||
socket = clients(1);
|
||||
end
|
||||
dataStream = [dataStream, typecast(single(position),'uint8')];
|
||||
|
||||
% Send POSI
|
||||
status = sendUDP(dataStream, p.Results.IP, p.Results.port);
|
||||
|
||||
end
|
||||
|
||||
%% Validate input
|
||||
posi = single(posi);
|
||||
if ~exist('ac', 'var')
|
||||
ac = 0;
|
||||
end
|
||||
ac = logical(ac);
|
||||
|
||||
%% Send command
|
||||
socket.sendPOSI(posi, ac);
|
||||
|
||||
end
|
||||
@@ -1,57 +0,0 @@
|
||||
function [ status ] = sendSTRU( STRU, varargin )
|
||||
%sendSTRU Send a MATLAB structure over UDP
|
||||
%
|
||||
%Inputs
|
||||
% stru: A MATLAB structure
|
||||
% IP Address (optional): IP Address of the machine that will receive the data as a character array. Default is '127.0.0.1' (local machine)
|
||||
% port (optional): Port on the receiving machine where the data will be sent. Default is 49009 (XPlaneConnect). In general use 49009 to send to the plugin
|
||||
%
|
||||
%Outputs
|
||||
% status: If there was an error. Status<0 means there was an error.
|
||||
%
|
||||
%Use
|
||||
% 1. import XPlaneConnect.*;
|
||||
% 2. data = struct('a',[1:20],'b',1.853,'name','Example Structure');
|
||||
% 3. #Send the data structure to port 49005 on the computer at IP address 172.0.100.54
|
||||
% 4. status = sendUDP( data, '172.0.100.54', 49005 );
|
||||
%
|
||||
% Contributors
|
||||
% [CT] Christopher Teubert (SGT, Inc.)
|
||||
% christopher.a.teubert@nasa.gov
|
||||
%
|
||||
% To Do
|
||||
%
|
||||
%BEGIN CODE
|
||||
|
||||
import XPlaneConnect.*
|
||||
|
||||
%% Handle Input
|
||||
p = inputParser;
|
||||
addRequired(p,'STRU');
|
||||
addOptional(p,'IP','127.0.0.1',@ischar);
|
||||
addOptional(p,'port',49009,@isnumeric);
|
||||
parse(p,STRU,varargin{:});
|
||||
|
||||
%% Form Data Array representing the structure
|
||||
DATA = ['STRU'-0,0]; %array header
|
||||
fieldName = fieldnames(p.Results.STRU); %all Struct fields
|
||||
for i=1:length(fieldName) %for each field
|
||||
field = getfield(p.Results.STRU,fieldName{i}); %get field
|
||||
if ischar(field) %String
|
||||
dim1 = 0; %Indicates string
|
||||
dim2 = length(field); %length
|
||||
data = field-0; %data
|
||||
else %Numeric
|
||||
dim1 = size(field,1); %Array Dim1
|
||||
dim2 = size(field,2); %Array Dim2
|
||||
data = typecast(single(reshape(field',1,dim1*dim2)),'uint8'); %Data
|
||||
end
|
||||
|
||||
DATA = [DATA,length(fieldName{i}),fieldName{i}-0,dim1,dim2,data]; %add to array
|
||||
end
|
||||
|
||||
%% Send Array
|
||||
status = sendUDP(DATA, p.Results.IP, p.Results.port);
|
||||
|
||||
end
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
function [ status ] = sendTEXT( msg, varargin )
|
||||
function sendTEXT( msg, x, y, socket )
|
||||
% sendTEXT Sends a string to be displayed in X-Plane.
|
||||
%
|
||||
% Inputs
|
||||
@@ -13,35 +13,35 @@ function [ status ] = sendTEXT( msg, varargin )
|
||||
%
|
||||
% Use
|
||||
% 1. import XPlaneConnect.*;
|
||||
% 2. #Set a message to be displayed near the top middle of the screen.
|
||||
% 2. % Set a message to be displayed near the top middle of the screen.
|
||||
% 3. status = sendTEXT('Some text', 512, 600);
|
||||
%
|
||||
% Contributors
|
||||
% Jason Watkins
|
||||
% jason.w.watkins@nasa.gov
|
||||
%
|
||||
% To Do
|
||||
%
|
||||
% BEGIN CODE
|
||||
% Jason Watkins (jason.w.watkins@nasa.gov)
|
||||
|
||||
import XPlaneConnect.*
|
||||
%% Handle Input
|
||||
p = inputParser;
|
||||
addRequired(p,'msg');
|
||||
addOptional(p,'x',-1,@isnumeric);
|
||||
addOptional(p,'y',-1,@isnumeric);
|
||||
addOptional(p,'IP','127.0.0.1',@ischar);
|
||||
addOptional(p,'port',49009,@isnumeric);
|
||||
parse(p,msg,varargin{:});
|
||||
|
||||
%% Body
|
||||
header = ['TEXT'-0,0];
|
||||
dataStream = [header,...
|
||||
typecast(uint32(p.Results.x), 'uint8'),...
|
||||
typecast(uint32(p.Results.y), 'uint8'),...
|
||||
uint8(length(msg)), msg-0];
|
||||
|
||||
% Send TEXT
|
||||
status = sendUDP(dataStream, p.Results.IP, p.Results.port);
|
||||
%% Get client
|
||||
global clients;
|
||||
if ~exist('socket', 'var')
|
||||
assert(isequal(length(clients) < 2, 1), '[sendTEXT] ERROR: Multiple clients open. You must specify which client to use.');
|
||||
if isempty(clients)
|
||||
socket = openUDP();
|
||||
else
|
||||
socket = clients(1);
|
||||
end
|
||||
end
|
||||
|
||||
%% Validate input
|
||||
if ~exist('x', 'var')
|
||||
x = -1;
|
||||
end
|
||||
if ~exist('y', 'var')
|
||||
y = -1;
|
||||
end
|
||||
x = int32(x);
|
||||
y = int32(y);
|
||||
|
||||
%% Send command
|
||||
socket.sendTEXT(msg, x, y);
|
||||
end
|
||||
@@ -1,49 +0,0 @@
|
||||
function [ status ] = sendUDP( data, IP, port )
|
||||
%sendUDP Send an one dimensional array of type uint8 data over an UDP connection using a java DatagramSocket
|
||||
%
|
||||
%Inputs
|
||||
% Data: 1-D array of type uint8 data to be sent
|
||||
% IP Address (optional): IP Address of the machine that will receive the data as a character array. Default is '127.0.0.1' (local machine)
|
||||
% port (optional): Port on the receiving machine where the data will be sent. Default is 49009 (XPlaneConnect). In general use 49009 to send to the plugin
|
||||
%
|
||||
%Outputs
|
||||
% status: If there was an error. Status<0 means there was an error.
|
||||
%
|
||||
%Use
|
||||
% 1. import XPlaneConnect.*;
|
||||
% 2. data = uint8([1:20]);
|
||||
% 3. #Send the data array to port 49005 on the computer at IP address 172.0.100.54.
|
||||
% 4. status = sendUDP( data, '172.0.100.54', 49005 );
|
||||
%
|
||||
% Contributors
|
||||
% [CT] Christopher Teubert (SGT, Inc.)
|
||||
% christopher.a.teubert@nasa.gov
|
||||
%
|
||||
% To Do
|
||||
% 1. Verify Input
|
||||
%
|
||||
%BEGIN CODE
|
||||
|
||||
import java.net.DatagramSocket
|
||||
import java.net.DatagramPacket
|
||||
import java.net.InetAddress
|
||||
|
||||
data(5) = length(data);
|
||||
status = 0;
|
||||
|
||||
%% Send array
|
||||
persistent socket
|
||||
if isempty(socket)
|
||||
try
|
||||
socket = DatagramSocket;
|
||||
catch err
|
||||
status = 1;
|
||||
disp(err)
|
||||
end
|
||||
end
|
||||
|
||||
IP = InetAddress.getByName(IP);
|
||||
packet = DatagramPacket(data, length(data), IP, port); %create packet
|
||||
socket.send(packet);
|
||||
end
|
||||
|
||||
@@ -1,53 +1,50 @@
|
||||
function [ status ] = sendWYPT( op, points, varargin )
|
||||
function sendWYPT( op, points, socket )
|
||||
% sendWYPT Adds, removes, or clears a set of waypoints to be rendered in
|
||||
% the simulator.
|
||||
%
|
||||
% Inputs
|
||||
% msg: The string to be displayed
|
||||
% x (optional): The distance from the left edge of the screen to display the message.
|
||||
% y (optional): The distance from the bottom edge of the screen to display the message.
|
||||
% IP Address (optional): IP Address of the machine that will receive the data as a character array. Default is '127.0.0.1' (local machine)
|
||||
% port (optional): Port on the receiving machine where the data will be sent. Default is 49009 (XPlaneConnect). In general use 49009 to send to the plugin and 49005 to send to the x-plane udp
|
||||
%
|
||||
% Outputs
|
||||
% status: 0 if successful, otherwise a negative value.
|
||||
% op: The operation to perform. 1=add, 2=remove, 3=clear.
|
||||
% points: An array of values representing points. Each triplet in the
|
||||
% array will be interpreted as a (Lat, Lon, Alt) point.
|
||||
% socket (optional): The client to use when sending the command.
|
||||
%
|
||||
% Use
|
||||
% 1. import XPlaneConnect.*;
|
||||
% 2. #Set a message to be displayed near the top middle of the screen.
|
||||
% 2. %Set a message to be displayed near the top middle of the screen.
|
||||
% 3. status = sendTEXT('Some text', 512, 600);
|
||||
%
|
||||
% Contributors
|
||||
% Jason Watkins
|
||||
% jason.w.watkins@nasa.gov
|
||||
% Jason Watkins (jason.w.watkins@nasa.gov)
|
||||
%
|
||||
% To Do
|
||||
%
|
||||
% BEGIN CODE
|
||||
|
||||
import XPlaneConnect.*
|
||||
%% Handle Input
|
||||
p = inputParser;
|
||||
addRequired(p,'op');
|
||||
addRequired(p,'points');
|
||||
addOptional(p,'IP','127.0.0.1',@ischar);
|
||||
addOptional(p,'port',49009,@isnumeric);
|
||||
parse(p,op,points,varargin{:});
|
||||
|
||||
%% Validate Input
|
||||
len = uint32(length(points));
|
||||
assert(op > 0 && op < 4);
|
||||
assert(mod(len, 3) == 0);
|
||||
assert(len / 3 < 20);
|
||||
|
||||
%% Body
|
||||
header = ['WYPT'-0,0];
|
||||
dataStream = [header,...
|
||||
uint8(op),...
|
||||
uint8(len / 3),...
|
||||
typecast(single(points), 'uint8')];
|
||||
|
||||
% Send TEXT
|
||||
status = sendUDP(dataStream, p.Results.IP, p.Results.port);
|
||||
%% Get client
|
||||
global clients;
|
||||
if ~exist('socket', 'var')
|
||||
assert(isequal(length(clients) < 2, 1), '[sendWYPT] ERROR: Multiple clients open. You must specify which client to use.');
|
||||
if isempty(clients)
|
||||
socket = openUDP();
|
||||
else
|
||||
socket = clients(1);
|
||||
end
|
||||
end
|
||||
|
||||
%% Validate input
|
||||
len = uint32(length(points));
|
||||
assert(op > 0 && op < 4);
|
||||
wyptOp = gov.nasa.xpc.WaypointOp.Add;
|
||||
if isequal(op, 2)
|
||||
wyptOp = gov.nasa.xpc.WaypointOp.Del;
|
||||
elseif isequal(op, 3)
|
||||
wyptOp = gov.nasa.xpc.WaypointOp.Clr;
|
||||
end
|
||||
assert(mod(len, 3) == 0);
|
||||
|
||||
%% Send command
|
||||
socket.sendWYPT(wyptOp, points);
|
||||
|
||||
end
|
||||
@@ -1,50 +1,36 @@
|
||||
function status = setConn( recvPort, IP, port )
|
||||
function setConn(port, socket)
|
||||
% setConn Send a command to set up the port where you will receive data on
|
||||
% this computer.
|
||||
%
|
||||
% Inputs
|
||||
% Receiving Port: Port that data will be sent to in the future for this connection
|
||||
% IP Address (optional): IP Address of the machine that will receive the data as a character array. Default is '127.0.0.1' (local machine)
|
||||
% port (optional): Port on the receiving machine where the data will be sent. Default is 49009 (XPlaneConnect). In general use 49009 to send to the plugin and 49005 to send to the x-plane udp
|
||||
%
|
||||
% Outputs
|
||||
% status: If there was an error. status<0 means there was an error.
|
||||
% port: Port that data will be sent to in the future for this connection.
|
||||
% socket (optional): The client to use when sending the command.
|
||||
%
|
||||
% Use
|
||||
% 1. import XPlaneConnect.*
|
||||
% 2. status = setConn(49011);
|
||||
%
|
||||
% Contributors
|
||||
% [CT] Christopher Teubert (SGT, Inc.)
|
||||
% christopher.a.teubert@nasa.gov
|
||||
%
|
||||
% To Do
|
||||
% 1. Verify Input
|
||||
%
|
||||
% BEGIN CODE
|
||||
import XPlaneConnect.*
|
||||
% Christopher Teubert (SGT, Inc.) <christopher.a.teubert@nasa.gov>
|
||||
% Jason Watkins <jason.w.watkins@nasa.gov>
|
||||
|
||||
status = 0;
|
||||
message = zeros(1,7);
|
||||
|
||||
%% Handle Input
|
||||
% Optional parameters
|
||||
if ~exist('IP','var'), IP = '127.0.0.1'; end
|
||||
if ~exist('port','var'), port = 49009; end
|
||||
import XPlaneConnect.*
|
||||
|
||||
% Check format of input-TODO
|
||||
%% Get client
|
||||
global clients;
|
||||
if ~exist('socket', 'var')
|
||||
assert(isequal(length(clients) < 2, 1), '[setCONN] ERROR: Multiple clients open. You must specify which client to use.');
|
||||
if isempty(clients)
|
||||
socket = openUDP();
|
||||
else
|
||||
socket = clients(1);
|
||||
end
|
||||
end
|
||||
|
||||
%% BODY
|
||||
% Header
|
||||
message(1:4) = 'CONN'-0;
|
||||
|
||||
% RecvPort
|
||||
message(6:7) = typecast(uint16(recvPort),'uint8');
|
||||
|
||||
% Send
|
||||
sendUDP(message,IP,port);
|
||||
|
||||
global udpReadPort;
|
||||
udpReadPort = recvPort;
|
||||
%% Validate input
|
||||
port = int32(port);
|
||||
|
||||
%% Send command
|
||||
socket.setCONN(port);
|
||||
|
||||
end
|
||||
@@ -1,115 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<meta http-equiv="Content-Style-Type" content="text/css">
|
||||
<title>XPlaneConnect Toolbox</title>
|
||||
<meta name="Generator" content="Cocoa HTML Writer">
|
||||
<meta name="CocoaVersion" content="1138.51">
|
||||
</head>
|
||||
<body>
|
||||
<h1>XPC-MATLAB</h1>
|
||||
Chris Teubert (Christopher.A.Teubert@nasa.gov)<br />
|
||||
|
||||
<h2>Summary</h2>
|
||||
XPC-MATLAB is a series of MATLAB functions that facilitate communication with X-Plane. This toolbox allows for the real-time application of active control to an XPlane simulation, flight visualization, record state during a flight, or interact with a mission using UDP.
|
||||
|
||||
<h2>Table of Contents</h2>
|
||||
<ol>
|
||||
<li><a href="#Func">Functions</a></li>
|
||||
<li><a href="#Setup">Setup</a>
|
||||
<li><a href="#Use">Use</a></li>
|
||||
<li><a href="#Example">Example</a></li>
|
||||
<li><a href="#Future">Future Work</a></li>
|
||||
<li><a href="#Notice">Notices and Disclaimers</a></li>
|
||||
<li><a href="#Changes">Change Log</a></li>
|
||||
</ol>
|
||||
|
||||
<a id="Func"><h2>Functions</h2></a>
|
||||
<h3>Basic Package</h3>
|
||||
|
||||
<table><tr><td width="150px">
|
||||
- <a href="pages/sendDATA.html"><b>sendDATA:</b></a></td><td>
|
||||
Send X-Plane Formatted DATA over UDP</td></tr><tr><td>
|
||||
- <a href="pages/sendPOSI.html"><b>sendPOSI:</b></a></td><td>
|
||||
Send Position and orientation update command to X-Plane over UDP for any aircraft (own or traffic)</td></tr><tr><td>
|
||||
- <a href="pages/sendCTRL.html"><b>sendCTRL:</b></a></td><td>
|
||||
Send control commands to X-Plane over UDP for any aircraft (own or traffic)</td></tr><tr><td>
|
||||
- <a href="pages/sendDREF.html"><b>sendDREF:</b></a></td><td>
|
||||
Set any X-Plane internal variable (dataref) over UDP </td></tr><tr><td>
|
||||
- <a href="pages/selectDATA.html"><b>selectDATA:</b></a></td><td>
|
||||
Choose specific X-Plane DATA parameters to be sent by X-Plane over UDP</td></tr><tr><td>
|
||||
- <a href="pages/setConn.html"><b>setConn:</b></a></td><td>
|
||||
Sets the return port for requested datarefs.</td></tr><tr><td>
|
||||
- <a href="pages/pauseSim.html"><b>pauseSim:</b></a></td><td>
|
||||
Pause simulation</td></tr><tr><td>
|
||||
- <a href="pages/openUDP.html"><b>openUDP:</b></a></td><td>
|
||||
Script that opens an UDP Socket</td></tr><tr><td>
|
||||
- <a href="pages/closeUDP.html"><b> closeUDP:</b></a></td><td>
|
||||
Script that closes an UDP Socket</td></tr>
|
||||
</table>
|
||||
|
||||
<h3>Advanced/Special-Use Functions</h3>
|
||||
<table><tr><td width="150px">
|
||||
- <a href="pages/clearUDPBuffer.html"><b> clearUDPBuffer:</b></a></td><td>
|
||||
Script that clears an UDP Socket Buffer</td></tr><tr><td>
|
||||
- <a href="pages/readDATA.html"><b>readDATA:</b></a></td><td>
|
||||
Read X-Plane Formatted Data from UDP Socket</td></tr><tr><td>
|
||||
- <a href="pages/readUDP.html"><b>readUDP:</b></a></td><td>
|
||||
Read Array from UDP Socket</td></tr><tr><td>
|
||||
- <a href="pages/sendSTRU.html"><b>sendSTRU:</b></a></td><td>
|
||||
Send a MATLAB structure over UDP</td></tr><tr><td>
|
||||
- <a href="pages/sendUDP.html"><b>sendUDP:</b></a></td><td>
|
||||
Send array over UDP</td></tr>
|
||||
</table>
|
||||
|
||||
<h3>Future</h3>
|
||||
<table><tr><td width="150px">
|
||||
- <a href="pages/requestDREF.html"><b>requestDREF:</b></a></td><td>
|
||||
Request the value of a specific data ref</td></tr><tr><td>
|
||||
- <b>drawWaypoint:</b></td><td>
|
||||
NOT FUNCTIONAL</td></tr>
|
||||
</table>
|
||||
|
||||
<a id="Setup"><h2>Setup</h2></a>
|
||||
Before using XPC Functions you must
|
||||
1. Install X-Plane (http://www.x-plane.com)
|
||||
2. Copy the file xpcPlugin.xpl to the "[X-Plane Directory]/Resources/plugins" directory.
|
||||
a. For Mac xpcPlugin can be found in the "[XPlaneConnect]/xpcPlugin/Mac" directory.
|
||||
a. For Windows xpcPlugin can be found in the "[XPlaneConnect]/xpcPlugin/Win" directory.
|
||||
3. Insert X-Plane CD 1 or X-Plane USB Key.
|
||||
4. Start X-Plane.
|
||||
5. import XPlaneConnect.*
|
||||
|
||||
<a id="Example"><h2>Examples</h2></a>
|
||||
<h3>Files</h3>
|
||||
TO BE ADDED
|
||||
<h3>Description</h3>
|
||||
|
||||
<a id="Future"><h2>Future Work</h2></a>
|
||||
<ul>
|
||||
<li> </li>
|
||||
</ul>
|
||||
|
||||
<a id="Notice"><h2>Notices and Disclaimers</h2></a>
|
||||
<b>Notices:</b><br />
|
||||
Copyright ©2013-2014 United States Government as represented by the Administrator of the National Aeronautics and Space Administration. All Rights Reserved.<br />
|
||||
|
||||
<br/><b>Disclaimers:</b>
|
||||
|
||||
<p><b>No Warranty:</b> THE SUBJECT SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY OF ANY KIND, EITHER EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, ANY WARRANTY THAT THE SUBJECT SOFTWARE WILL CONFORM TO SPECIFICATIONS, ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR FREEDOM FROM INFRINGEMENT, ANY WARRANTY THAT THE SUBJECT SOFTWARE WILL BE ERROR FREE, OR ANY WARRANTY THAT DOCUMENTATION, IF PROVIDED, WILL CONFORM TO THE SUBJECT SOFTWARE. THIS AGREEMENT DOES NOT, IN ANY MANNER, CONSTITUTE AN ENDORSEMENT BY GOVERNMENT AGENCY OR ANY PRIOR RECIPIENT OF ANY RESULTS, RESULTING DESIGNS, HARDWARE, SOFTWARE PRODUCTS OR ANY OTHER APPLICATIONS RESULTING FROM USE OF THE SUBJECT SOFTWARE. FURTHER, GOVERNMENT AGENCY DISCLAIMS ALL WARRANTIES AND LIABILITIES REGARDING THIRD-PARTY SOFTWARE, IF PRESENT IN THE ORIGINAL SOFTWARE, AND DISTRIBUTES IT "AS IS."</p>
|
||||
|
||||
<p><b>Waiver and Indemnity:</b> RECIPIENT AGREES TO WAIVE ANY AND ALL CLAIMS AGAINST THE UNITED STATES GOVERNMENT, ITS CONTRACTORS AND SUBCONTRACTORS, AS WELL AS ANY PRIOR RECIPIENT. IF RECIPIENT'S USE OF THE SUBJECT SOFTWARE RESULTS IN ANY LIABILITIES, DEMANDS, DAMAGES, EXPENSES OR LOSSES ARISING FROM SUCH USE, INCLUDING ANY DAMAGES FROM PRODUCTS BASED ON, OR RESULTING FROM, RECIPIENT'S USE OF THE SUBJECT SOFTWARE, RECIPIENT SHALL INDEMNIFY AND HOLD HARMLESS THE UNITED STATES GOVERNMENT, ITS CONTRACTORS AND SUBCONTRACTORS, AS WELL AS ANY PRIOR RECIPIENT, TO THE EXTENT PERMITTED BY LAW. RECIPIENT'S SOLE REMEDY FOR ANY SUCH MATTER SHALL BE THE IMMEDIATE, UNILATERAL TERMINATION OF THIS AGREEMENT.</p>
|
||||
|
||||
<br /><b>X-Plane API</b><br/>
|
||||
Copyright (c) 2008, Sandy Barbour and Ben Supnik All rights reserved.<br/>
|
||||
<p>Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:</p>
|
||||
<ul>
|
||||
<li>Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.</li>
|
||||
<li>Neither the names of the authors nor that of X-Plane or Laminar Research may be used to endorse or promote products derived from this software without specific prior written permission from the authors or Laminar Research, respectively.</li>
|
||||
</ul>
|
||||
|
||||
<p>X-Plane API SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.</p>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,37 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<meta http-equiv="Content-Style-Type" content="text/css">
|
||||
<title>XPlaneConnect Toolbox-ClearUDPBuffer</title>
|
||||
<meta name="Generator" content="Cocoa HTML Writer">
|
||||
<meta name="CocoaVersion" content="1138.51">
|
||||
</head>
|
||||
<body>
|
||||
<a href="../Documentation (MATLAB).html"><-- Back</a><br />
|
||||
<h1>clearUDPBuffer</h1>
|
||||
Script that clears an UDP Socket Buffer
|
||||
|
||||
<h2>Inputs</h2>
|
||||
<ul>
|
||||
<li><b>Socket:</b> UDP Socket to be cleared</li>
|
||||
</ul>
|
||||
|
||||
<h2>Outputs</h2>
|
||||
<ul>
|
||||
<li><b>Socket:</b> UDP Socket</li>
|
||||
</ul>
|
||||
|
||||
<h2>Use</h2>
|
||||
1. import XPlaneConnect.*;<br />
|
||||
2. Socket = openUDP(49005); <br />
|
||||
3. Socket = clearUDPBuffer(Socket);<br />
|
||||
|
||||
<h2>Change Log</h2>
|
||||
10/02/14: [CT] V0.9: Updated to work with updated xpcPlugin<br />
|
||||
09/12/13: [CT] Add optional arguments<br />
|
||||
09/10/13: [CT] Code created<br /><br />
|
||||
<a href="../Documentation (MATLAB).html"><-- Back</a><br />
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,36 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<meta http-equiv="Content-Style-Type" content="text/css">
|
||||
<title>XPlaneConnect Toolbox-closeUDP</title>
|
||||
<meta name="Generator" content="Cocoa HTML Writer">
|
||||
<meta name="CocoaVersion" content="1138.51">
|
||||
</head>
|
||||
<body>
|
||||
<a href="../Documentation (MATLAB).html"><-- Back</a><br />
|
||||
<h1>closeUDP</h1>
|
||||
Script that closes a UDP Socket
|
||||
|
||||
<h2>Inputs</h2>
|
||||
<ul>
|
||||
<li><b>Socket:</b> UDP Socket to be closed</li>
|
||||
</ul>
|
||||
|
||||
<h2>Outputs</h2>
|
||||
<ul>
|
||||
<li><b>Status:</b> Integer indicating the success of socket closing. 1 = Success 0 = Failure</li>
|
||||
</ul>
|
||||
|
||||
<h2>Use</h2>
|
||||
1. import XPlaneConnect.*; <br />
|
||||
2. Socket = openUDP(49005); <br />
|
||||
3. Status = closeUDP(Socket);<br />
|
||||
|
||||
<h2>Change Log</h2>
|
||||
10/02/14: [CT] V0.9: Updated to work with updated xpcPlugin<br />
|
||||
09/10/13: [CT] Code created<br /><br />
|
||||
<a href="../Documentation (MATLAB).html"><-- Back</a><br />
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,39 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<meta http-equiv="Content-Style-Type" content="text/css">
|
||||
<title>XPlaneConnect Toolbox-openUDP</title>
|
||||
<meta name="Generator" content="Cocoa HTML Writer">
|
||||
<meta name="CocoaVersion" content="1138.51">
|
||||
</head>
|
||||
<body>
|
||||
<a href="../Documentation (MATLAB).html"><-- Back</a><br />
|
||||
<h1>openUDP</h1>
|
||||
Script that opens a UDP Socket
|
||||
|
||||
<h2>Inputs</h2>
|
||||
<ul>
|
||||
<li><b>port:</b> UDP Port for socket</li>
|
||||
<li><b>timeout (optional):</b> Optional parameter for time to UDP timeout (in ms)-Default 0.1 seconds</li>
|
||||
</ul>
|
||||
|
||||
<h2>Outputs</h2>
|
||||
<ul>
|
||||
<li><b>Socket:</b> UDP Socket</li>
|
||||
</ul>
|
||||
|
||||
<h2>Use</h2>
|
||||
1. import XPlaneConnect.*;<br />
|
||||
2. Socket = openUDP(49005);%Open socket at port 49005 with timeout of 0.1 seconds <br /><br />
|
||||
or<br/><br/>
|
||||
2. Socket = openUDP(49005,200);%Open socket at port 49005 with timeout of 0.2 seconds<br /><br />
|
||||
|
||||
<h2>Change Log</h2>
|
||||
10/02/14: [CT] V0.9: Updated to work with updated xpcPlugin<br />
|
||||
09/12/13: [CT] Added optional timeout input argument<br />
|
||||
09/10/13: [CT] Code created<br /><br />
|
||||
<a href="../Documentation (MATLAB).html"><-- Back</a><br />
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,36 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<meta http-equiv="Content-Style-Type" content="text/css">
|
||||
<title>XPlaneConnect Toolbox-pauseSim</title>
|
||||
<meta name="Generator" content="Cocoa HTML Writer">
|
||||
<meta name="CocoaVersion" content="1138.51">
|
||||
</head>
|
||||
<body>
|
||||
<a href="../Documentation (MATLAB).html"><-- Back</a><br />
|
||||
<h1>pauseSim</h1>
|
||||
|
||||
<h2>Inputs</h2>
|
||||
<ul>
|
||||
<li><b>Pause:</b> binary value 0=run, 1=pause</li>
|
||||
<li><b>IP Address (optional):</b> IP Address of the machine that will receive the data as a character array. Default is '127.0.0.1' (local machine)</li>
|
||||
<li><b>port (optional):</b> Port on the receiving machine where the data will be sent. Default is 49009 (XPlaneConnect). In general use 49009 to send to the plugin and 49005 to send to the x-plane udp </li>
|
||||
</ul>
|
||||
|
||||
<h2>Outputs</h2>
|
||||
<ul>
|
||||
<li><b>status:</b> If there was an error. status<0 means there was an error.</li>
|
||||
</ul>
|
||||
|
||||
<h2>Use</h2>
|
||||
1. import XPlaneConnect.*;<br />
|
||||
2. status = pauseSim(1);<br />
|
||||
|
||||
<h2>Change Log</h2>
|
||||
10/02/14: [CT] V0.9: Updated to work with updated xpcPlugin<br />
|
||||
06/10/13: [CT] Code created<br /><br />
|
||||
<a href="../Documentation (MATLAB).html"><-- Back</a><br />
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,59 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<meta http-equiv="Content-Style-Type" content="text/css">
|
||||
<title>XPlaneConnect Toolbox-readDATA</title>
|
||||
<meta name="Generator" content="Cocoa HTML Writer">
|
||||
<meta name="CocoaVersion" content="1138.51">
|
||||
</head>
|
||||
<body>
|
||||
<a href="../Documentation (MATLAB).html"><-- Back</a><br />
|
||||
<h1>readDATA</h1>
|
||||
Reads UDP Socket and interprets data
|
||||
|
||||
<h2>Inputs</h2>
|
||||
<ul>
|
||||
<li><b>location:</b> Either an opened UDP Socket or integer port number</li>
|
||||
</ul>
|
||||
|
||||
<h2>Outputs</h2>
|
||||
If data is X-Plane data format:
|
||||
<ul>
|
||||
<li><b>data:</b> Matlab X-Plane DATA Structure<ul>
|
||||
<li>.h: Header array containing header numbers corresponding to values in the X-Plane UDP Data screen. </li>
|
||||
<li>.d: 2-D Data array. Each row contains eight values corresponding to the header value (.h(1) corresponds to .d(1,:))</li>
|
||||
<li>.raw: raw UDP data array received by readUDP</li></ul></li>
|
||||
</ul>
|
||||
If data is matlab structure:
|
||||
<ul>
|
||||
<li><b>data:</b> Matlab Structure. Raw udp data saved to data.raw</li>
|
||||
</ul>
|
||||
If data is any other format:
|
||||
<ul>
|
||||
<li><b>data:</b> Matlab Structure containing one field <ul>
|
||||
<li>.raw & .d: raw UDP data array received by readUDP</li></ul></li>
|
||||
</ul>
|
||||
|
||||
<h2>Use</h2>
|
||||
1. import XPlaneConnect.*;<br />
|
||||
2. socket = openUDP(49005); <br />
|
||||
3. data = readDATA(socket); <br />
|
||||
4. status = closeUDP(socket); <br /><br />
|
||||
|
||||
or <br /> <br />
|
||||
|
||||
1. import XPlaneConnect.*;<br />
|
||||
2. data = readDATA(49005);
|
||||
|
||||
<h2>Note</h2>
|
||||
NOTE: sending in a port number instead of an opened socket clears the UDP buffer. This only works if the data is being sent at a fast rate. Sending in a UDP Socket reads the first packet in the buffer. <br />
|
||||
|
||||
<h2>Change Log</h2>
|
||||
10/02/14: [CT] V0.9: Updated to work with updated xpcPlugin<br />
|
||||
09/10/13: [CT] Updated to receive UDP socket or port number<br />
|
||||
06/10/13: [CT] Code created<br /><br />
|
||||
<a href="../Documentation (MATLAB).html"><-- Back</a><br />
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,43 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<meta http-equiv="Content-Style-Type" content="text/css">
|
||||
<title>XPlaneConnect Toolbox-readUDP</title>
|
||||
<meta name="Generator" content="Cocoa HTML Writer">
|
||||
<meta name="CocoaVersion" content="1138.51">
|
||||
</head>
|
||||
<body>
|
||||
<a href="../Documentation (MATLAB).html"><-- Back</a><br />
|
||||
<h1>readUDP</h1>
|
||||
Read Array from UDP Socket
|
||||
|
||||
<h2>Inputs</h2>
|
||||
<ul>
|
||||
<li><b>location:</b> Either an opened UDP Socket or integer port number</li>
|
||||
</ul>
|
||||
|
||||
<h2>Outputs</h2>
|
||||
<ul>
|
||||
<li><b>data:</b> UDP uint8 Array. Equal to -998 in the case of an error.</li>
|
||||
</ul>
|
||||
|
||||
<h2>Use</h2>
|
||||
1. import XPlaneConnect.*;<br />
|
||||
2. socket = openUDP(49005); <br />
|
||||
3. data = readUDP(socket); <br />
|
||||
4. status = closeUDP(socket); <br /><br />
|
||||
|
||||
or <br /> <br />
|
||||
|
||||
1. import XPlaneConnect.*;<br />
|
||||
2. data = readUDP(49005); <br />
|
||||
|
||||
<h2>Note</h2>
|
||||
NOTE: sending in a port number instead of an opened socket clears the UDP buffer. This only works if the data is being sent at a fast rate. Sending in a UDP Socket reads the first packet in the buffer.
|
||||
|
||||
<h2>Change Log</h2>
|
||||
10/02/14: [CT] V0.9: Updated to work with updated xpcPlugin<br />
|
||||
09/08/13: [CT] Added option for either UDP Socket or port number input <br/>
|
||||
06/10/13: [CT] Code created<br /><br />
|
||||
<a href="../Documentation (MATLAB).html"><-- Back</a><br />
|
||||
@@ -1,37 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<meta http-equiv="Content-Style-Type" content="text/css">
|
||||
<title>XPlaneConnect Toolbox-requestDREF</title>
|
||||
<meta name="Generator" content="Cocoa HTML Writer">
|
||||
<meta name="CocoaVersion" content="1138.51">
|
||||
</head>
|
||||
<body>
|
||||
<a href="../Documentation (MATLAB).html"><-- Back</a><br />
|
||||
<h1>requestDREF</h1>
|
||||
|
||||
<h2>Inputs</h2>
|
||||
<ul>
|
||||
<li><b>DREFArray:</b> Cell Array of DataRefs to be requested</li>
|
||||
<li><b>IP Address (optional):</b> IP Address of the machine that will receive the data as a character array. Default is '127.0.0.1' (local machine)</li>
|
||||
<li><b>port (optional):</b> Port on the receiving machine where the data will be sent. Default is 49009 (XPlaneConnect). In general use 49009 to send to the plugin </li>
|
||||
</ul>
|
||||
|
||||
<h2>Outputs</h2>
|
||||
<ul>
|
||||
<li><b>status:</b> If there was an error. status<0 means there was an error.</li>
|
||||
</ul>
|
||||
|
||||
<h2>Use</h2>
|
||||
1. import XPlaneConnect.*; <br />
|
||||
2. DREFArray = {'sim/cockpit2/controls/yoke_heading_ratio','sim/cockpit2/controls/yoke_roll_ratio'}; <br />
|
||||
3. status = requestDREF( DREFArray, '172.0.100.54' );<br />
|
||||
|
||||
<h2>Change Log</h2>
|
||||
10/02/14: [CT] V0.9: Updated to work with updated xpcPlugin<br />
|
||||
06/10/13: [CT] Code created<br /><br />
|
||||
<a href="../Documentation (MATLAB).html"><-- Back</a><br />
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,39 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<meta http-equiv="Content-Style-Type" content="text/css">
|
||||
<title>XPlaneConnect Toolbox-selectDATA</title>
|
||||
<meta name="Generator" content="Cocoa HTML Writer">
|
||||
<meta name="CocoaVersion" content="1138.51">
|
||||
</head>
|
||||
<body>
|
||||
<a href="../Documentation (MATLAB).html"><-- Back</a><br />
|
||||
<h1>selectDATA</h1>
|
||||
Choose specific X-Plane parameters to be send over UDP
|
||||
|
||||
<h2>Inputs</h2>
|
||||
<ul>
|
||||
<li><b>index:</b> An array of the values that to be sent. Corresponds to the numbers on the XPlane Output screen (ACTUAL NAME?)</li>
|
||||
<li><b>IP Address (optional):</b> IP Address of the machine that will receive the data as a character array. Default is '127.0.0.1' (local machine)</li>
|
||||
<li><b>port (optional):</b> Port on the receiving machine where the data will be sent. Default is 49009 (XPlaneConnect). In general use 49009 to send to the plugin and 49005 to send to the x-plane udp </li>
|
||||
</ul>
|
||||
|
||||
<h2>Outputs</h2>
|
||||
<ul>
|
||||
<li><b>status:</b> If there was an error. Status<0 means there was an error.</li>
|
||||
</ul>
|
||||
|
||||
<h2>Use</h2>
|
||||
1. import XPlaneConnect.*;<br />
|
||||
2. values = [1, 2, 3, 27, 40];
|
||||
3. status = selectDATA(values,'127.0.0.1',49005);<br />
|
||||
|
||||
<h2>Change Log</h2>
|
||||
10/02/14: [CT] V0.9: Updated to work with updated xpcPlugin<br />
|
||||
04/18/14: [CT] V0.2: Added Versioning<br />
|
||||
06/10/13: [CT] Code created<br /><br />
|
||||
<a href="../Documentation (MATLAB).html"><-- Back</a><br />
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,48 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<meta http-equiv="Content-Style-Type" content="text/css">
|
||||
<title>XPlaneConnect Toolbox-sendCTRL</title>
|
||||
<meta name="Generator" content="Cocoa HTML Writer">
|
||||
<meta name="CocoaVersion" content="1138.51">
|
||||
</head>
|
||||
<body>
|
||||
<a href="../Documentation (MATLAB).html"><-- Back</a><br />
|
||||
<h1>sendCTRL</h1>
|
||||
Send position and orientation update command to X-Plane over UDP. This requires the X-Plane Connect Plugin to be running
|
||||
|
||||
<h2>Inputs</h2>
|
||||
<ul>
|
||||
<li><b>ctrl:</b> Array of 6 values where:
|
||||
<ul>
|
||||
<li>ctrl(1) Latitudinal Stick [-1,1] </li>
|
||||
<li>ctrl(2) Longitudinal Stick [-1,1] </li>
|
||||
<li>ctrl(3) Pedal [-1, 1] </li>
|
||||
<li>ctrl(4) Throttle [-1, 1] </li>
|
||||
<li>ctrl(5) Gear (0=up, 1=down) </li>
|
||||
<li>ctrl(6) Flaps [0, 1] </li>
|
||||
</ul>
|
||||
<li><b>aircraft number (optional):</b> 0=own aircraft</li>
|
||||
<li><b>IP Address (optional):</b> IP Address of the machine that will receive the data as a character array. Default is '127.0.0.1' (local machine)</li>
|
||||
<li><b>port (optional):</b> Port on the receiving machine where the data will be sent. Default is 49009 (XPlaneConnect). In general use 49009 to send to the plugin and 49005 to send to the x-plane udp </li>
|
||||
</ul>
|
||||
|
||||
<h2>Outputs</h2>
|
||||
<ul>
|
||||
<li><b>status:</b> If there was an error. status<0 means there was an error.</li>
|
||||
</ul>
|
||||
|
||||
<h2>Use</h2>
|
||||
1. import XPlaneConnect.*;<br />
|
||||
2. ctrl = [0, 0, 0, 0.8, 0, 0];
|
||||
3. status = sendCTRL(ctrl); % Set position of own aircraft<br />
|
||||
4. status2 = sendCTRL(ctrl,1); % Set position of aircraft 1<br />
|
||||
|
||||
<h2>Change Log</h2>
|
||||
10/02/14: [CT] V0.9 Updated to use new xpcPlugin<br />
|
||||
09/26/14: [CT] Code created<br /><br />
|
||||
<a href="../Documentation (MATLAB).html"><-- Back</a><br />
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,46 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<meta http-equiv="Content-Style-Type" content="text/css">
|
||||
<title>XPlaneConnect Toolbox-sendDATA</title>
|
||||
<meta name="Generator" content="Cocoa HTML Writer">
|
||||
<meta name="CocoaVersion" content="1138.51">
|
||||
</head>
|
||||
<body>
|
||||
<a href="../Documentation%20(MATLAB).html"><-- Back</a><br />
|
||||
<h1>sendDATA</h1>
|
||||
Send X-Plane formatted DATA over UDP. This function is used to change one of the parameters listed in the x-plane udp data screen (see http://www.nuclearprojects.com/xplane/images/xp_datainout.jpg)
|
||||
|
||||
<h2>Inputs</h2>
|
||||
<ul>
|
||||
<li><b>data:</b> X-Plane formatted data. Is a matlab structure with the following fields:
|
||||
<ul>
|
||||
<li>.h: Header array containing header numbers corresponding to values in the X-Plane UDP Data screen. </li>
|
||||
<li>.d: 2-D Data array. Each row contains eight values corresponding to the header value (.h(1) corresponds to .d(1,:))</li>
|
||||
</ul></li>
|
||||
<li><b>IP Address (optional):</b> IP Address of the machine that will receive the data as a character array. Default is '127.0.0.1' (local machine)</li>
|
||||
<li><b>port (optional):</b> Port on the receiving machine where the data will be sent. Default is 49009 (XPlaneConnect). In general use 49009 to send to the plugin and 49005 to send to the x-plane udp </li>
|
||||
</ul>
|
||||
|
||||
<h2>Outputs</h2>
|
||||
<ul>
|
||||
<li><b>status:</b> If there was an error. Status=1 means there was an error.</li>
|
||||
</ul>
|
||||
|
||||
<h2>Use</h2>
|
||||
1. import XPlaneConnect.*;<br />
|
||||
2. data = struct('h',14,'d',[1,-998,-998,-998,-998,-998,-998,-998]); %Set Gear<br />
|
||||
3. %Send the data array to port 49005 on the computer at IP address 172.0.100.54.<br />
|
||||
4. status = sendDATA(data, '172.0.100.54', 49005);
|
||||
|
||||
<h2>note</h2>
|
||||
Note: send the value -998 to not overwrite that parameter. That is, if -998 is sent, the parameter will stay at the current X-Plane value<br />
|
||||
|
||||
<h2>Change Log</h2>
|
||||
10/01/14: [CT] V0.9: updated to function with new xpcPlugin<br />
|
||||
06/10/13: [CT] First created<br /><br />
|
||||
<a href="../Documentation%20(MATLAB).html"><-- Back</a><br />
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,48 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<meta http-equiv="Content-Style-Type" content="text/css">
|
||||
<title>XPlaneConnect Toolbox-sendCTRL</title>
|
||||
<meta name="Generator" content="Cocoa HTML Writer">
|
||||
<meta name="CocoaVersion" content="1138.51">
|
||||
</head>
|
||||
<body>
|
||||
<a href="../Documentation (MATLAB).html"><-- Back</a><br />
|
||||
<h1>sendCTRL</h1>
|
||||
Send position and orientation update command to X-Plane over UDP. This requires the X-Plane Connect Plugin to be running
|
||||
|
||||
<h2>Inputs</h2>
|
||||
<ul>
|
||||
<ul>
|
||||
<li>data(1) Latitudinal Stick [-1,1] </li>
|
||||
<li>data(2) Longitudinal Stick [-1,1] </li>
|
||||
<li>data(3) Pedal [-1, 1] </li>
|
||||
<li>data(4) Throttle [-1, 1] </li>
|
||||
<li>data(5) Gear (0=up, 1=down) </li>
|
||||
<li>data(6) Flaps [0, 1] </li>
|
||||
</ul>
|
||||
<li><b>aircraft number (optional):</b> 0=own aircraft</li>
|
||||
<li><b>IP Address (optional):</b> IP Address of the machine that will receive the data as a character array. Default is '127.0.0.1' (local machine)</li>
|
||||
<li><b>port (optional):</b> Port on the receiving machine where the data will be sent. Default is 49009 (XPlaneConnect). In general use 49009 to send to the plugin and 49005 to send to the x-plane udp </li>
|
||||
</ul>
|
||||
|
||||
<h2>Outputs</h2>
|
||||
<ul>
|
||||
<li><b>status:</b> If there was an error. status<0 means there was an error.</li>
|
||||
</ul>
|
||||
|
||||
<h2>Use</h2>
|
||||
1. import XPlaneConnect.* <br />
|
||||
2. dataRef = 'sim/aircraft/parts/acf_gear_deploy'; // Landing Gear <br />
|
||||
3. Value = 0; <br />
|
||||
4. status = sendDREF(dataRef, Value); <br />
|
||||
|
||||
<h2>Change Log</h2>
|
||||
10/02/14: [CT] V0.9: Updated to use new xpcPlugin
|
||||
06/10/13: [CT] Code created<br /><br />
|
||||
|
||||
<a href="../Documentation (MATLAB).html"><-- Back</a><br />
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,50 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<meta http-equiv="Content-Style-Type" content="text/css">
|
||||
<title>XPlaneConnect Toolbox-sendDREF</title>
|
||||
<meta name="Generator" content="Cocoa HTML Writer">
|
||||
<meta name="CocoaVersion" content="1138.51">
|
||||
</head>
|
||||
<body>
|
||||
<a href="../Documentation (MATLAB).html"><-- Back</a><br />
|
||||
<h1>sendPosition</h1>
|
||||
Send position and orientation update command to X-Plane over UDP. This requires the X-Plane Connect Plugin to be running
|
||||
|
||||
<h2>Inputs</h2>
|
||||
<ul>
|
||||
<li><b>data:</b> Array of 6 values where:
|
||||
<ul>
|
||||
<li>data(1) is the aircraft's Latitude (degrees) </li>
|
||||
<li>data(2) is the aircraft's Longitude (degrees) </li>
|
||||
<li>data(3) is the aircraft's altitude (meters above sea level)</li>
|
||||
<li>data(4) is the aircraft's roll angle (degrees)</li>
|
||||
<li>data(5) is the aircraft's pitch angle (degrees)</li>
|
||||
<li>data(6) is the aircraft's heading/yaw angle (degrees)</li>
|
||||
</ul>
|
||||
<li><b>aircraft number (optional):</b> 0=own aircraft</li>
|
||||
<li><b>IP Address (optional):</b> IP Address of the machine that will receive the data as a character array. Default is '127.0.0.1' (local machine)</li>
|
||||
<li><b>port (optional):</b> Port on the receiving machine where the data will be sent. Default is 49009 (XPlaneConnect). In general use 49009 to send to the plugin and 49005 to send to the x-plane udp </li>
|
||||
</ul>
|
||||
|
||||
<h2>Outputs</h2>
|
||||
<ul>
|
||||
<li><b>status:</b> If there was an error. status<0 means there was an error.</li>
|
||||
</ul>
|
||||
|
||||
<h2>Use</h2>
|
||||
1. import XPlaneConnect.*;<br />
|
||||
2. latlon = [37.4185718,-121.935565]; %Lat,lon of NASA Ames Research Center<br />
|
||||
3. alt = 500; %meters above sea level<br />
|
||||
4. orient = [0,20,180]; %Orientation (roll,pitch,yaw/heading). 20 degrees yaw, heading south<br />
|
||||
5. status = sendPOSI([latlon,alt,orient]); % Set position of own aircraft<br />
|
||||
6. status2 = sendPOSI([[latlon(1)+0.005,latlon(2)],alt,orient],1); % Set position of aircraft 1<br />
|
||||
|
||||
<h2>Change Log</h2>
|
||||
10/02/14: [CT] V0.9 Updated to use new xpcPlugin<br />
|
||||
06/10/13: [CT] Code created<br /><br />
|
||||
<a href="../Documentation (MATLAB).html"><-- Back</a><br />
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,39 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<meta http-equiv="Content-Style-Type" content="text/css">
|
||||
<title>XPlaneConnect Toolbox-sendSTRU</title>
|
||||
<meta name="Generator" content="Cocoa HTML Writer">
|
||||
<meta name="CocoaVersion" content="1138.51">
|
||||
</head>
|
||||
<body>
|
||||
<a href="../Documentation (MATLAB).html"><-- Back</a><br />
|
||||
<h1>sendSTRU</h1>
|
||||
Send a MATLAB structure over UDP
|
||||
|
||||
<h2>Inputs</h2>
|
||||
<ul>
|
||||
<li><b>stru:</b> A MATLAB structure</li>
|
||||
<li><b>IP Address (optional):</b> IP Address of the machine that will receive the data as a character array. Default is '127.0.0.1' (local machine)</li>
|
||||
<li><b>port (optional):</b> Port on the receiving machine where the data will be sent. Default is 49009 (XPlaneConnect). In general use 49009 to send to the plugin </li>
|
||||
</ul>
|
||||
|
||||
<h2>Outputs</h2>
|
||||
<ul>
|
||||
<li><b>status:</b> If there was an error. Status<0 means there was an error.</li>
|
||||
</ul>
|
||||
|
||||
<h2>Use</h2>
|
||||
1. import XPlaneConnect.*;<br />
|
||||
2. data = struct('a',[1:20],'b',1.853,'name','Example Structure');<br />
|
||||
3. #Send the data structure to port 49005 on the computer at IP address 172.0.100.54<br />
|
||||
4. status = sendSTRU( data, '172.0.100.54', 49005 ); <br />
|
||||
|
||||
<h2>Change Log</h2>
|
||||
10/02/14: [CT] V0.9: Updated to work with updated xpcPlugin<br />
|
||||
08/01/13: [CT] Code created<br /><br />
|
||||
<a href="../Documentation (MATLAB).html"><-- Back</a><br />
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,39 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<meta http-equiv="Content-Style-Type" content="text/css">
|
||||
<title>XPlaneConnect Toolbox-sendUDP</title>
|
||||
<meta name="Generator" content="Cocoa HTML Writer">
|
||||
<meta name="CocoaVersion" content="1138.51">
|
||||
</head>
|
||||
<body>
|
||||
<a href="../Documentation (MATLAB).html"><-- Back</a><br />
|
||||
<h1>sendUDP</h1>
|
||||
Send an one dimensional array of type uint8 data over an UDP connection
|
||||
|
||||
<h2>Inputs</h2>
|
||||
<ul>
|
||||
<li><b>data:</b> 1-D array of type uint8 data to be sent</li>
|
||||
<li><b>IP Address (optional):</b> IP Address of the machine that will receive the data as a character array. Default is '127.0.0.1' (local machine)</li>
|
||||
<li><b>port (optional):</b> Port on the receiving machine where the data will be sent. Default is 49009 (XPlaneConnect). In general use 49009 to send to the plugin and 49005 to send to the x-plane udp </li>
|
||||
</ul>
|
||||
|
||||
<h2>Outputs</h2>
|
||||
<ul>
|
||||
<li><b>status:</b> If there was an error. Status=1 means there was an error.</li>
|
||||
</ul>
|
||||
|
||||
<h2>Use</h2>
|
||||
1. import XPlaneConnect.*;<br />
|
||||
2. data = uint8([1:20]);<br />
|
||||
3. #Send the data array to port 49005 on the computer at IP address 172.0.100.54.<br />
|
||||
4. status = sendUDP( data, '172.0.100.54', 49005 ); <br />
|
||||
|
||||
<h2>Change Log</h2>
|
||||
10/02/14: [CT] V0.9: Updated to work with updated xpcPlugin<br />
|
||||
06/10/13: [CT] Code created <br /><br />
|
||||
<a href="../Documentation (MATLAB).html"><-- Back</a><br />
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,37 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<meta http-equiv="Content-Style-Type" content="text/css">
|
||||
<title>XPlaneConnect Toolbox-setConn</title>
|
||||
<meta name="Generator" content="Cocoa HTML Writer">
|
||||
<meta name="CocoaVersion" content="1138.51">
|
||||
</head>
|
||||
<body>
|
||||
<a href="../Documentation (MATLAB).html"><-- Back</a><br />
|
||||
<h1>setConn</h1>
|
||||
Send a command to set up the port where you will receive data on this computer.
|
||||
|
||||
<h2>Inputs</h2>
|
||||
<ul>
|
||||
<li><b>Receiving Port:</b> Port that data will be sent to in the future for this connection</li>
|
||||
<li><b>IP Address (optional):</b> IP Address of the machine that will receive the data as a character array. Default is '127.0.0.1' (local machine)</li>
|
||||
<li><b>port (optional):</b> Port on the receiving machine where the data will be sent. Default is 49009 (XPlaneConnect). In general use 49009 to send to the plugin and 49005 to send to the x-plane udp </li>
|
||||
</ul>
|
||||
|
||||
<h2>Outputs</h2>
|
||||
<ul>
|
||||
<li><b>status:</b> If there was an error. status<0 means there was an error.</li>
|
||||
</ul>
|
||||
|
||||
<h2>Use</h2>
|
||||
1. import XPlaneConnect.* <br />
|
||||
2. status = setConn(49011); <br />
|
||||
|
||||
<h2>Change Log</h2>
|
||||
10/02/14: [CT] V0.9: Updated to work with updated xpcPlugin<br />
|
||||
04/21/14: [CT] V0.2: First Version<br /><br />
|
||||
<a href="../Documentation (MATLAB).html"><-- Back</a><br />
|
||||
|
||||
</body>
|
||||
</html>
|
||||
123
README.md
123
README.md
@@ -1,4 +1,121 @@
|
||||
XPlaneConnect
|
||||
=============
|
||||
#X-Plane Connect
|
||||
The X-Plane Connect (XPC) Toolbox is an open source research tool used to
|
||||
interact with the commercial flight simulator software X-Plane. XPC allows users
|
||||
to control aircraft and receive state information from aircraft simulated in
|
||||
X-Plane using functions written in C, C++, Java, or MATLAB in real time over the
|
||||
network. This research tool has been used to visualize flight paths, test control
|
||||
algorithms, simulate an active airspace, or generate out-the-window visuals for
|
||||
in-house flight simulation software. Possible applications include active control
|
||||
of an XPlane simulation, flight visualization, recording states during a flight,
|
||||
or interacting with a mission over UDP.
|
||||
|
||||
The X-Plane Communications Toolbox (XPC) is an open source research tool used to interact with the commercial flight simulator software X-Plane. XPC allows users to control aircraft and receive state information from aircraft simulated in X-Plane using functions written in C, C++, java, or MATLAB in real time over the network. This research tool has been used to visualize flight paths, test control algorithms, simulate an active airspace, or generate out-the-window visuals for in-house flight simulation software.
|
||||
###Migrating to 1.0
|
||||
For existing users, several important breaking changes have been made in version
|
||||
1.0. For detailed information, see the 1.0 release changelog. For client-specific
|
||||
guidlines on migrating to 1.0, refer to the follwing guides:
|
||||
|
||||
####[C](https://github.com/nasa/XPlaneConnect/wiki/Migrating-to-1.0-C)
|
||||
|
||||
####[MATLAB](https://github.com/nasa/XPlaneConnect/wiki/Migrating-to-1.0-MATLAB)
|
||||
|
||||
####[Java](https://github.com/nasa/XPlaneConnect/wiki/Migrating-to-1.0-Java)
|
||||
|
||||
###Architecture
|
||||
XPC includes an X-Plane plugin (xpcPlugin) and clients written in several
|
||||
languages that interact with the plugin.
|
||||
|
||||
####Quick Start
|
||||
To get started using X-Plane Connect, do the following.
|
||||
|
||||
1. Purchase and install X-Plane 9 or 10.
|
||||
2. Copy the X-Plane Plugin folder (xpcPlugin/XPlaneConnect) to the plugin
|
||||
directory ([X-Plane Directory]/Resources/plugins/)
|
||||
3. Write some code using one of the clients to manipulate X-Plane data.
|
||||
|
||||
Each client is located in a top-level directory of the repository named for the
|
||||
client's language. The client directories generally include a 'src' folder
|
||||
containing the client source code, and an 'Examples' folder containing sample
|
||||
code demonstrating how to use the client.
|
||||
|
||||
####Additional Information
|
||||
For detailed information about XPC and how to use the XPC clients, refer to the
|
||||
[XPC Wiki](https://github.com/nasa/XPlaneConnect/wiki).
|
||||
|
||||
####Capabilities
|
||||
The XPC Toolbox allows the user to manipulate the internal state of X-Plane by
|
||||
reading and setting DataRefs, a complete list of which can be found on the
|
||||
[X-Plane SDK wiki](http://www.xsquawkbox.net/xpsdk/docs/DataRefs.html).
|
||||
|
||||
In addition, several convenience functions are provided, which allow the user to
|
||||
efficiently execute common commands. These functions include the ability to set
|
||||
the position and control surfaces of both player and multiplayer aircraft. In
|
||||
addition, the pause function allows users to easily pause and un-pause X-Plane's
|
||||
physics simulation engine.
|
||||
|
||||
###Compatibility
|
||||
XPC has been tested with the following software versions:
|
||||
* Windows: Vista, 7, & 8
|
||||
* Mac OSX: 10.8-10.10
|
||||
* Linux: Tested on Red Hat Enterprise Linux Workstation release 6.6
|
||||
* X-Plane: 9 & 10
|
||||
|
||||
###Contributing
|
||||
All contributions are welcome! If you are having problems with the plugin, please
|
||||
open an issue on GitHub or email [Chris Teubert](mailto:christopher.a.teuber@nasa.gov).
|
||||
If you would like to contribute directly, please feel free to open a pull request
|
||||
against the "develop" branch. Pull requests will be evaluated and integrated into
|
||||
the next official release.
|
||||
|
||||
###Notices
|
||||
Copyright ©2013-2015 United States Government as represented by the Administrator
|
||||
of the National Aeronautics and Space Administration. All Rights Reserved.
|
||||
|
||||
No Warranty: THE SUBJECT SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY OF ANY
|
||||
KIND, EITHER EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, ANY
|
||||
WARRANTY THAT THE SUBJECT SOFTWARE WILL CONFORM TO SPECIFICATIONS, ANY IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR FREEDOM FROM
|
||||
INFRINGEMENT, ANY WARRANTY THAT THE SUBJECT SOFTWARE WILL BE ERROR FREE, OR ANY
|
||||
WARRANTY THAT DOCUMENTATION, IF PROVIDED, WILL CONFORM TO THE SUBJECT SOFTWARE.
|
||||
THIS AGREEMENT DOES NOT, IN ANY MANNER, CONSTITUTE AN ENDORSEMENT BY GOVERNMENT
|
||||
AGENCY OR ANY PRIOR RECIPIENT OF ANY RESULTS, RESULTING DESIGNS, HARDWARE,
|
||||
SOFTWARE PRODUCTS OR ANY OTHER APPLICATIONS RESULTING FROM USE OF THE SUBJECT
|
||||
SOFTWARE. FURTHER, GOVERNMENT AGENCY DISCLAIMS ALL WARRANTIES AND LIABILITIES
|
||||
REGARDING THIRD-PARTY SOFTWARE, IF PRESENT IN THE ORIGINAL SOFTWARE, AND
|
||||
DISTRIBUTES IT "AS IS."
|
||||
|
||||
Waiver and Indemnity: RECIPIENT AGREES TO WAIVE ANY AND ALL CLAIMS AGAINST THE
|
||||
UNITED STATES GOVERNMENT, ITS CONTRACTORS AND SUBCONTRACTORS, AS WELL AS ANY
|
||||
PRIOR RECIPIENT. IF RECIPIENT'S USE OF THE SUBJECT SOFTWARE RESULTS IN ANY
|
||||
LIABILITIES, DEMANDS, DAMAGES, EXPENSES OR LOSSES ARISING FROM SUCH USE,
|
||||
INCLUDING ANY DAMAGES FROM PRODUCTS BASED ON, OR RESULTING FROM, RECIPIENT'S USE
|
||||
OF THE SUBJECT SOFTWARE, RECIPIENT SHALL INDEMNIFY AND HOLD HARMLESS THE UNITED
|
||||
STATES GOVERNMENT, ITS CONTRACTORS AND SUBCONTRACTORS, AS WELL AS ANY PRIOR
|
||||
RECIPIENT, TO THE EXTENT PERMITTED BY LAW. RECIPIENT'S SOLE REMEDY FOR ANY SUCH
|
||||
MATTER SHALL BE THE IMMEDIATE, UNILATERAL TERMINATION OF THIS AGREEMENT.
|
||||
|
||||
####X-Plane API
|
||||
Copyright (c) 2008, Sandy Barbour and Ben Supnik All rights reserved.
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in the
|
||||
Software without restriction, including without limitation the rights to use,
|
||||
copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
* Neither the names of the authors nor that of X-Plane or Laminar Research may
|
||||
be used to endorse or promote products derived from this software without
|
||||
specific prior written permission from the authors or Laminar Research,
|
||||
respectively.
|
||||
|
||||
X-Plane API SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
||||
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
60
Readme.txt
60
Readme.txt
@@ -1,60 +0,0 @@
|
||||
X-Plane Connect (XPC) Toolbox
|
||||
|
||||
Description
|
||||
The X-Plane Connect (XPC) Toolbox facilitates communication with X-Plane. This toolbox allows for the real-time manipulation of X-Plane variables. Possible applications include active control of an XPlane simulation, flight visualization, recording states during a flight, or interacting with a mission over UDP.
|
||||
|
||||
Architecture
|
||||
XPC includes a plugin (xpcPlugin) which is to be copied into the X-Plane Plugin Directory ([X-Plane Directory]/Resources/Plugin/), and the xpcScripts-A series of functions for communication with X-Plane.
|
||||
|
||||
xpcPlugin (Directory: xpcPlugin/)
|
||||
|
||||
xpcScripts
|
||||
C: (Directory: C/src/, Example: C/xpcExample/)
|
||||
MATLAB: (Directory: Matlab/+XPlaneConnect/, Example: MATLAB/xpcExample/)
|
||||
java: (Directory: java/src/, Example: java/xpcExample/)
|
||||
python: (future-Not complete yet): (Directory: python/xpc/, Example: python/xpcExample/)
|
||||
|
||||
Instructions:
|
||||
1. Purchase/Install X-Plane
|
||||
2. Copy the X-Plane Plugin folder (xpcPlugin/XPlaneConnect) to the plugin directory ([X-Plane Directory]/Resources/plugins/)
|
||||
3. Write code using the xpcScrips to manipulate X-Plane
|
||||
|
||||
Capabilities:
|
||||
Set Aircraft Position (own or other aircraft): Use sendPOSI()
|
||||
Control Aircraft (own or other aircraft): Use sendCTRL()
|
||||
Set any internal X-Plane dataref: Use sendDREF()
|
||||
Get the value of any X-Plane dataref: Use requestDREF()
|
||||
Pause Simulation: Use pauseSim()
|
||||
|
||||
Compatability:
|
||||
Windows:
|
||||
Tested on Windows Vista and Windows 7
|
||||
Mac OSX
|
||||
Tested on OS X 10.8-10.10
|
||||
X-Plane
|
||||
Tested with X-Plane 9 & 10
|
||||
|
||||
Notices:
|
||||
|
||||
Copyright ©2013-2014 United States Government as represented by the Administrator of the National Aeronautics and Space Administration. All Rights Reserved.
|
||||
|
||||
Disclaimers
|
||||
|
||||
No Warranty: THE SUBJECT SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY OF ANY KIND, EITHER EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, ANY WARRANTY THAT THE SUBJECT SOFTWARE WILL CONFORM TO SPECIFICATIONS, ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR FREEDOM FROM INFRINGEMENT, ANY WARRANTY THAT THE SUBJECT SOFTWARE WILL BE ERROR FREE, OR ANY WARRANTY THAT DOCUMENTATION, IF PROVIDED, WILL CONFORM TO THE SUBJECT SOFTWARE. THIS AGREEMENT DOES NOT, IN ANY MANNER, CONSTITUTE AN ENDORSEMENT BY GOVERNMENT AGENCY OR ANY PRIOR RECIPIENT OF ANY RESULTS, RESULTING DESIGNS, HARDWARE, SOFTWARE PRODUCTS OR ANY OTHER APPLICATIONS RESULTING FROM USE OF THE SUBJECT SOFTWARE. FURTHER, GOVERNMENT AGENCY DISCLAIMS ALL WARRANTIES AND LIABILITIES REGARDING THIRD-PARTY SOFTWARE, IF PRESENT IN THE ORIGINAL SOFTWARE, AND DISTRIBUTES IT "AS IS."
|
||||
|
||||
Waiver and Indemnity: RECIPIENT AGREES TO WAIVE ANY AND ALL CLAIMS AGAINST THE UNITED STATES GOVERNMENT, ITS CONTRACTORS AND SUBCONTRACTORS, AS WELL AS ANY PRIOR RECIPIENT. IF RECIPIENT'S USE OF THE SUBJECT SOFTWARE RESULTS IN ANY LIABILITIES, DEMANDS, DAMAGES, EXPENSES OR LOSSES ARISING FROM SUCH USE, INCLUDING ANY DAMAGES FROM PRODUCTS BASED ON, OR RESULTING FROM, RECIPIENT'S USE OF THE SUBJECT SOFTWARE, RECIPIENT SHALL INDEMNIFY AND HOLD HARMLESS THE UNITED STATES GOVERNMENT, ITS CONTRACTORS AND SUBCONTRACTORS, AS WELL AS ANY PRIOR RECIPIENT, TO THE EXTENT PERMITTED BY LAW. RECIPIENT'S SOLE REMEDY FOR ANY SUCH MATTER SHALL BE THE IMMEDIATE, UNILATERAL TERMINATION OF THIS AGREEMENT.
|
||||
X-Plane API
|
||||
Copyright (c) 2008, Sandy Barbour and Ben Supnik All rights reserved.
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Neither the names of the authors nor that of X-Plane or Laminar Research
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission from the authors or
|
||||
Laminar Research, respectively.
|
||||
|
||||
X-Plane API SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Contributors:
|
||||
CT: Chris Teubert (christopher.a.teubert@nasa.gov)
|
||||
@@ -22,6 +22,9 @@
|
||||
<ClCompile Include="..\..\C\src\xplaneConnect.c" />
|
||||
<ClCompile Include="..\C Tests\main.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\C\src\xplaneConnect.h" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{BC701AF4-552C-4C9D-82A1-B352542783A4}</ProjectGuid>
|
||||
<RootNamespace>CTests</RootNamespace>
|
||||
|
||||
@@ -22,4 +22,9 @@
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\C\src\xplaneConnect.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,19 +0,0 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 2013
|
||||
VisualStudioVersion = 12.0.31101.0
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CPPTests", "CPPTests.vcxproj", "{9BA85F4F-A75A-4C27-BD85-2FEF881BEA13}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Win32 = Debug|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{9BA85F4F-A75A-4C27-BD85-2FEF881BEA13}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{9BA85F4F-A75A-4C27-BD85-2FEF881BEA13}.Debug|Win32.Build.0 = Debug|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -1,75 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{9BA85F4F-A75A-4C27-BD85-2FEF881BEA13}</ProjectGuid>
|
||||
<RootNamespace>CPPTests</RootNamespace>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v120</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v120</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<IncludePath>../../C/src;$(IncludePath)</IncludePath>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<SDLCheck>false</SDLCheck>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\C\src\xplaneConnect.c" />
|
||||
<ClCompile Include="..\CPP Tests\main.cpp" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
@@ -1,25 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\CPP Tests\main.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\C\src\xplaneConnect.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -1,79 +0,0 @@
|
||||
.\"Modified from man(1) of FreeBSD, the NetBSD mdoc.template, and mdoc.samples.
|
||||
.\"See Also:
|
||||
.\"man mdoc.samples for a complete listing of options
|
||||
.\"man mdoc for the short list of editing options
|
||||
.\"/usr/share/misc/mdoc.template
|
||||
.Dd 11/25/14 \" DATE
|
||||
.Dt XPC Tests 1 \" Program name and manual section number
|
||||
.Os Darwin
|
||||
.Sh NAME \" Section Header - required - don't modify
|
||||
.Nm XPC Tests,
|
||||
.\" The following lines are read in generating the apropos(man -k) database. Use only key
|
||||
.\" words here as the database is built based on the words here and in the .ND line.
|
||||
.Nm Other_name_for_same_program(),
|
||||
.Nm Yet another name for the same program.
|
||||
.\" Use .Nm macro to designate other names for the documented program.
|
||||
.Nd This line parsed for whatis database.
|
||||
.Sh SYNOPSIS \" Section Header - required - don't modify
|
||||
.Nm
|
||||
.Op Fl abcd \" [-abcd]
|
||||
.Op Fl a Ar path \" [-a path]
|
||||
.Op Ar file \" [file]
|
||||
.Op Ar \" [file ...]
|
||||
.Ar arg0 \" Underlined argument - use .Ar anywhere to underline
|
||||
arg2 ... \" Arguments
|
||||
.Sh DESCRIPTION \" Section Header - required - don't modify
|
||||
Use the .Nm macro to refer to your program throughout the man page like such:
|
||||
.Nm
|
||||
Underlining is accomplished with the .Ar macro like this:
|
||||
.Ar underlined text .
|
||||
.Pp \" Inserts a space
|
||||
A list of items with descriptions:
|
||||
.Bl -tag -width -indent \" Begins a tagged list
|
||||
.It item a \" Each item preceded by .It macro
|
||||
Description of item a
|
||||
.It item b
|
||||
Description of item b
|
||||
.El \" Ends the list
|
||||
.Pp
|
||||
A list of flags and their descriptions:
|
||||
.Bl -tag -width -indent \" Differs from above in tag removed
|
||||
.It Fl a \"-a flag as a list item
|
||||
Description of -a flag
|
||||
.It Fl b
|
||||
Description of -b flag
|
||||
.El \" Ends the list
|
||||
.Pp
|
||||
.\" .Sh ENVIRONMENT \" May not be needed
|
||||
.\" .Bl -tag -width "ENV_VAR_1" -indent \" ENV_VAR_1 is width of the string ENV_VAR_1
|
||||
.\" .It Ev ENV_VAR_1
|
||||
.\" Description of ENV_VAR_1
|
||||
.\" .It Ev ENV_VAR_2
|
||||
.\" Description of ENV_VAR_2
|
||||
.\" .El
|
||||
.Sh FILES \" File used or created by the topic of the man page
|
||||
.Bl -tag -width "/Users/joeuser/Library/really_long_file_name" -compact
|
||||
.It Pa /usr/share/file_name
|
||||
FILE_1 description
|
||||
.It Pa /Users/joeuser/Library/really_long_file_name
|
||||
FILE_2 description
|
||||
.El \" Ends the list
|
||||
.\" .Sh DIAGNOSTICS \" May not be needed
|
||||
.\" .Bl -diag
|
||||
.\" .It Diagnostic Tag
|
||||
.\" Diagnostic informtion here.
|
||||
.\" .It Diagnostic Tag
|
||||
.\" Diagnostic informtion here.
|
||||
.\" .El
|
||||
.Sh SEE ALSO
|
||||
.\" List links in ascending order by section, alphabetically within a section.
|
||||
.\" Please do not reference files that do not exist without filing a bug report
|
||||
.Xr a 1 ,
|
||||
.Xr b 1 ,
|
||||
.Xr c 1 ,
|
||||
.Xr a 2 ,
|
||||
.Xr b 2 ,
|
||||
.Xr a 3 ,
|
||||
.Xr b 3
|
||||
.\" .Sh BUGS \" Document known, unremedied bugs
|
||||
.\" .Sh HISTORY \" Document history if command behaves in a unique manner
|
||||
@@ -1,490 +0,0 @@
|
||||
//
|
||||
// main.cpp
|
||||
// XPC Tests
|
||||
//
|
||||
// Created by Chris Teubert on 11/25/14.
|
||||
// Copyright (c) 2014 Chris Teubert. All rights reserved.
|
||||
//
|
||||
|
||||
#include <iostream>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <cmath>
|
||||
#include <time.h>
|
||||
#include <exception>
|
||||
#include "xplaneconnect.h"
|
||||
|
||||
int testFailed = 0;
|
||||
int testPassed = 0;
|
||||
|
||||
void runTest(void (*f)())
|
||||
{
|
||||
try {
|
||||
std::cout << "Test " << testPassed+testFailed+1<<": ";
|
||||
(*f)(); // Run Test
|
||||
std::cout << "PASSED\n";
|
||||
testPassed++;
|
||||
}
|
||||
catch (int i)
|
||||
{
|
||||
std::cerr << "FAILED\n\tError: " << i << std::endl;
|
||||
testFailed++;
|
||||
}
|
||||
catch (char c)
|
||||
{
|
||||
std::cerr << "FAILED\n\tError: " << c << std::endl;
|
||||
testFailed++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void openUDPTest() // openUDP Test
|
||||
{
|
||||
std::cout << "openUDP - ";
|
||||
struct xpcSocket sendPort = openUDP( 49062, "127.0.0.1", 49009 );
|
||||
}
|
||||
|
||||
void closeUDPTest() // closeUDP test
|
||||
{
|
||||
std::cout << "closeUDP - ";
|
||||
struct xpcSocket sendPort = openUDP( 49063, "127.0.0.1", 49009 );
|
||||
closeUDP(sendPort);
|
||||
sendPort = openUDP( 49063, "127.0.0.1", 49009 );
|
||||
closeUDP(sendPort);
|
||||
}
|
||||
|
||||
void sendReadTest() // send/read Test
|
||||
{
|
||||
std::cout << "send/readUDP - ";
|
||||
|
||||
// Initialization
|
||||
int i; // Iterator
|
||||
char test[] = {0, 1, 2, 3, 5};
|
||||
char buf[5] = {0};
|
||||
struct xpcSocket sendPort, recvPort;
|
||||
|
||||
// Setup
|
||||
sendPort = openUDP( 49064, "127.0.0.1", 49063 );
|
||||
recvPort = openUDP( 49063, "127.0.0.1", 49009 );
|
||||
|
||||
// Execution
|
||||
sendUDP( sendPort, test, sizeof(test) );
|
||||
readUDP( recvPort, buf, NULL ); // Test
|
||||
|
||||
// Close
|
||||
closeUDP(sendPort);
|
||||
closeUDP(recvPort);
|
||||
|
||||
// Tests
|
||||
for (i=0; i<4; i++)
|
||||
{
|
||||
if (test[i] != buf[i]) // Not received correctly
|
||||
{
|
||||
throw 1;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void requestDREFTest() // Request DREF Test (Required for next tests)
|
||||
{
|
||||
std::cout << "requestDREF - ";
|
||||
|
||||
// Initialization
|
||||
int i; // Iterator
|
||||
char DREFArray[100][100];
|
||||
float *recDATA[100];
|
||||
short DREFSizes[100];
|
||||
struct xpcSocket sendPort, recvPort;
|
||||
short result = 0;
|
||||
|
||||
// Setup
|
||||
for (i = 0; i < 100; i++) {
|
||||
recDATA[i] = (float *) malloc(40*sizeof(float));
|
||||
memset(DREFArray[i],0,100);
|
||||
}
|
||||
sendPort = openUDP( 49064, "127.0.0.1", 49009 );
|
||||
recvPort = openUDP( 49008, "127.0.0.1", 49009 );
|
||||
strcpy(DREFArray[0],"sim/cockpit/switches/gear_handle_status");
|
||||
strcpy(DREFArray[1],"sim/cockpit2/switches/panel_brightness_ratio");
|
||||
for (i=0;i<2;i++) {
|
||||
DREFSizes[i] = (int) strlen(DREFArray[i]);
|
||||
}
|
||||
|
||||
// Execution
|
||||
result = requestDREF(sendPort, recvPort, DREFArray, DREFSizes, 2, recDATA, DREFSizes);
|
||||
|
||||
// Close
|
||||
closeUDP(sendPort);
|
||||
closeUDP(recvPort);
|
||||
|
||||
// Tests
|
||||
if ( result < 0)// Request 2 values
|
||||
{
|
||||
throw 1;
|
||||
}
|
||||
if (DREFSizes[0] != 1 || DREFSizes[1] != 4)
|
||||
{
|
||||
throw 2;
|
||||
}
|
||||
}
|
||||
|
||||
void sendDREFTest() // sendDREF test
|
||||
{
|
||||
std::cout << "sendDREF - ";
|
||||
|
||||
// Initialization
|
||||
int i; // Iterator
|
||||
char DREFArray[100][100];
|
||||
float *recDATA[100];
|
||||
short DREFSizes[100];
|
||||
float value = 0.0;
|
||||
struct xpcSocket sendPort, recvPort;
|
||||
short result = 0;
|
||||
|
||||
// Setup
|
||||
for (i = 0; i < 100; i++) {
|
||||
recDATA[i] = (float *) malloc(40*sizeof(float));
|
||||
memset(DREFArray[i],0,100);
|
||||
}
|
||||
sendPort = openUDP( 49066, "127.0.0.1", 49009 );
|
||||
recvPort = openUDP( 49008, "127.0.0.1", 49009 );
|
||||
strcpy(DREFArray[0],"sim/cockpit/switches/gear_handle_status");
|
||||
for (i=0;i<1;i++) {
|
||||
DREFSizes[i] = (int) strlen(DREFArray[i]);
|
||||
}
|
||||
|
||||
// Execution
|
||||
sendDREF(sendPort, DREFArray[0], DREFSizes[0], &value, 1);
|
||||
result = requestDREF(sendPort, recvPort, DREFArray, DREFSizes, 1, recDATA, DREFSizes);
|
||||
|
||||
// Close
|
||||
closeUDP(sendPort);
|
||||
closeUDP(recvPort);
|
||||
|
||||
// Tests
|
||||
if (result < 0)// Request 1 value
|
||||
{
|
||||
throw 1;
|
||||
}
|
||||
if (DREFSizes[0] != 1)
|
||||
{
|
||||
throw 2;
|
||||
}
|
||||
if (*recDATA[0] != value)
|
||||
{
|
||||
throw 3;
|
||||
}
|
||||
}
|
||||
|
||||
void sendDATATest() // sendDATA test
|
||||
{
|
||||
std::cout << "sendData - ";
|
||||
|
||||
// Initialize
|
||||
int i,j; // Iterator
|
||||
char DREFArray[100][100];
|
||||
float data[4][9] = {0};
|
||||
float *recDATA[100];
|
||||
short DREFSizes[100];
|
||||
struct xpcSocket sendPort, recvPort;
|
||||
short result = 0;
|
||||
|
||||
// Setup
|
||||
for (i = 0; i < 100; i++) {
|
||||
recDATA[i] = (float *) malloc(40*sizeof(float));
|
||||
memset(DREFArray[i],0,100);
|
||||
}
|
||||
sendPort = openUDP( 49066, "127.0.0.1", 49009 );
|
||||
recvPort = openUDP( 49008, "127.0.0.1", 49009 );
|
||||
strcpy(DREFArray[0],"sim/aircraft/parts/acf_gear_deploy");
|
||||
for (i=0;i<1;i++) {
|
||||
DREFSizes[i] = (int) strlen(DREFArray[i]);
|
||||
}
|
||||
for (i=0;i<4;i++) { // Set array to -999
|
||||
for (j=0;j<9;j++) data[i][j] = -999;
|
||||
}
|
||||
data[0][0] = 14; // Gear
|
||||
data[0][1] = 1;
|
||||
data[0][2] = 0;
|
||||
|
||||
// Execution
|
||||
sendDATA(sendPort, data, 1); // Gear
|
||||
result = requestDREF(sendPort, recvPort, DREFArray, DREFSizes, 1, recDATA, DREFSizes); // Test
|
||||
|
||||
// Close
|
||||
closeUDP(sendPort);
|
||||
closeUDP(recvPort);
|
||||
|
||||
// Tests
|
||||
if ( result < 0 )// Request 1 value
|
||||
{
|
||||
throw 1;
|
||||
}
|
||||
if (DREFSizes[0] != 10)
|
||||
{
|
||||
throw 2;
|
||||
}
|
||||
if (*recDATA[0] != data[0][1])
|
||||
{
|
||||
throw 3;
|
||||
}
|
||||
}
|
||||
|
||||
void sendCTRLTest() // sendCTRL test
|
||||
{
|
||||
std::cout << "sendCTRL - ";
|
||||
|
||||
// Initialize
|
||||
int i; // Iterator
|
||||
char DREFArray[100][100];
|
||||
float CTRL[6] = {0.0};
|
||||
float *recDATA[100];
|
||||
short DREFSizes[100];
|
||||
struct xpcSocket sendPort, recvPort;
|
||||
short result;
|
||||
|
||||
// Setup
|
||||
for (i = 0; i < 100; i++) {
|
||||
recDATA[i] = (float *) malloc(40*sizeof(float));
|
||||
memset(DREFArray[i],0,100);
|
||||
}
|
||||
sendPort = openUDP( 49066, "127.0.0.1", 49009 );
|
||||
recvPort = openUDP( 49008, "127.0.0.1", 49009 );
|
||||
strcpy(DREFArray[0],"sim/cockpit2/controls/yoke_pitch_ratio");
|
||||
strcpy(DREFArray[1],"sim/cockpit2/controls/yoke_roll_ratio");
|
||||
strcpy(DREFArray[2],"sim/cockpit2/controls/yoke_heading_ratio");
|
||||
strcpy(DREFArray[3],"sim/flightmodel/engine/ENGN_thro");
|
||||
strcpy(DREFArray[4],"sim/cockpit/switches/gear_handle_status");
|
||||
strcpy(DREFArray[5],"sim/flightmodel/controls/flaprqst");
|
||||
for (i = 0; i < 100; i++) {
|
||||
DREFSizes[i] = (int)strlen(DREFArray[i]);
|
||||
}
|
||||
CTRL[3] = 0.8; // Throttle
|
||||
CTRL[4] = 1.0; // Gear
|
||||
CTRL[5] = 0.5; // Flaps
|
||||
|
||||
// Execute
|
||||
sendCTRL(sendPort, 6, CTRL);
|
||||
result = requestDREF(sendPort, recvPort, DREFArray, DREFSizes, 6, recDATA, DREFSizes); // Test
|
||||
|
||||
// Close
|
||||
closeUDP(sendPort);
|
||||
closeUDP(recvPort);
|
||||
|
||||
// Tests
|
||||
if ( result < 0 )// Request 1 value
|
||||
{
|
||||
throw -6;
|
||||
}
|
||||
for (i=0;i<6;i++)
|
||||
{
|
||||
if (std::abs( recDATA[i][0]-CTRL[i])>1e-4)
|
||||
{
|
||||
throw -i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void sendPOSITest() // sendPOSI test
|
||||
{
|
||||
std::cout << "sendPOSI - ";
|
||||
|
||||
// Initialization
|
||||
int i; // Iterator
|
||||
char DREFArray[100][100];
|
||||
float POSI[8] = {0.0};
|
||||
float *recDATA[100];
|
||||
short DREFSizes[100];
|
||||
struct xpcSocket sendPort, recvPort;
|
||||
short result;
|
||||
|
||||
// Setup
|
||||
for (i = 0; i < 100; i++) {
|
||||
recDATA[i] = (float *) malloc(40*sizeof(float));
|
||||
memset(DREFArray[i],0,100);
|
||||
}
|
||||
sendPort = openUDP( 49063, "127.0.0.1", 49009 );
|
||||
recvPort = openUDP( 49008, "127.0.0.1", 49009 );
|
||||
strcpy(DREFArray[0],"sim/flightmodel/position/latitude");
|
||||
strcpy(DREFArray[1],"sim/flightmodel/position/longitude");
|
||||
strcpy(DREFArray[2],"sim/flightmodel/position/y_agl");
|
||||
strcpy(DREFArray[3],"sim/flightmodel/position/phi");
|
||||
strcpy(DREFArray[4],"sim/flightmodel/position/theta");
|
||||
strcpy(DREFArray[5],"sim/flightmodel/position/psi");
|
||||
strcpy(DREFArray[6],"sim/cockpit/switches/gear_handle_status");
|
||||
for (i=0;i<7;i++) {
|
||||
DREFSizes[i] = (int) strlen(DREFArray[i]);
|
||||
}
|
||||
POSI[0] = 37.524; // Lat
|
||||
POSI[1] = -122.06899; // Lon
|
||||
POSI[2] = 2500; // Alt
|
||||
POSI[3] = 0; // Pitch
|
||||
POSI[4] = 0; // Roll
|
||||
POSI[5] = 0; // Heading
|
||||
POSI[6] = 1; // Gear
|
||||
|
||||
// Execution
|
||||
sendPOSI( sendPort, 0, 7, POSI );
|
||||
result = requestDREF(sendPort, recvPort, DREFArray, DREFSizes, 7, recDATA, DREFSizes); // Test
|
||||
|
||||
// Close
|
||||
closeUDP(sendPort);
|
||||
closeUDP(recvPort);
|
||||
|
||||
// Tests
|
||||
if ( result < 0 )// Request 1 value
|
||||
{
|
||||
throw -7;
|
||||
}
|
||||
for (i=0;i<7-1;i++)
|
||||
{
|
||||
if (i==2)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (std::abs(recDATA[i][0]-POSI[i])>1e-4)
|
||||
{
|
||||
throw -i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void pauseTest() // pauseSim test
|
||||
{
|
||||
std::cout << "pauseSim - ";
|
||||
|
||||
// Initialize
|
||||
int i; // Iterator
|
||||
char DREFArray[100][100];
|
||||
float *recDATA[100];
|
||||
short DREFSizes[100],RECSizes[100];
|
||||
struct xpcSocket sendPort, recvPort;
|
||||
short result;
|
||||
|
||||
// Setup
|
||||
for (i = 0; i < 100; i++) {
|
||||
recDATA[i] = (float *) malloc(40*sizeof(float));
|
||||
memset(DREFArray[i],0,100);
|
||||
}
|
||||
|
||||
// Setup
|
||||
sendPort = openUDP( 49064, "127.0.0.1", 49009 );
|
||||
recvPort = openUDP( 49008, "127.0.0.1", 49009 );
|
||||
strcpy(DREFArray[0],"sim/operation/override/override_planepath");
|
||||
for (i=0;i<1;i++) {
|
||||
DREFSizes[i] = (int) strlen(DREFArray[i]);
|
||||
}
|
||||
|
||||
// Execute
|
||||
pauseSim(sendPort, 1);
|
||||
result = requestDREF(sendPort, recvPort, DREFArray, DREFSizes, 1, recDATA, RECSizes); // Test
|
||||
|
||||
// Close
|
||||
closeUDP(sendPort);
|
||||
closeUDP(recvPort);
|
||||
|
||||
// Test
|
||||
if (result < 0) {
|
||||
throw -1;
|
||||
}
|
||||
if (recDATA[0][0] != 1)
|
||||
{
|
||||
throw -2;
|
||||
}
|
||||
|
||||
// Reopen
|
||||
sendPort = openUDP( 49064, "127.0.0.1", 49009 );
|
||||
recvPort = openUDP( 49008, "127.0.0.1", 49009 );
|
||||
|
||||
// Execute 2
|
||||
pauseSim(sendPort, 0);
|
||||
result = requestDREF(sendPort, recvPort, DREFArray, DREFSizes, 1, recDATA, RECSizes); // Test
|
||||
|
||||
// Close 2
|
||||
closeUDP(sendPort);
|
||||
closeUDP(recvPort);
|
||||
|
||||
// Test 2
|
||||
if (result < 0)
|
||||
{
|
||||
throw -3;
|
||||
}
|
||||
if (recDATA[0][0] != 0)
|
||||
{
|
||||
throw -4;
|
||||
}
|
||||
}
|
||||
|
||||
void connTest() // setConn test
|
||||
{
|
||||
std::cout << "setConn - ";
|
||||
|
||||
// Initialize
|
||||
int i; // Iterator
|
||||
char DREFArray[100][100];
|
||||
float *recDATA[100];
|
||||
short DREFSizes[100];
|
||||
struct xpcSocket sendPort, recvPort;
|
||||
short result = 0;
|
||||
#if (__APPLE__ || __linux)
|
||||
usleep(0);
|
||||
#endif
|
||||
|
||||
// Setup
|
||||
sendPort = openUDP( 49067, "127.0.0.1", 49009 );
|
||||
recvPort = openUDP( 49055, "127.0.0.1", 49009 );
|
||||
strcpy(DREFArray[0],"sim/cockpit/switches/gear_handle_status");
|
||||
for (i=0;i<1;i++) {
|
||||
DREFSizes[i] = (int) strlen(DREFArray[i]);
|
||||
}
|
||||
|
||||
// Execution
|
||||
setCONN(sendPort, 49055);
|
||||
result = requestDREF(sendPort, recvPort, DREFArray, DREFSizes, 1, recDATA, DREFSizes); // Test
|
||||
|
||||
// Close
|
||||
closeUDP(sendPort);
|
||||
closeUDP(recvPort);
|
||||
|
||||
// Test
|
||||
if ( result < 0 )// No data received
|
||||
{
|
||||
throw 1;
|
||||
}
|
||||
|
||||
|
||||
// Set up for next test
|
||||
sendPort = openUDP( 49067, "127.0.0.1", 49009 );
|
||||
setCONN(sendPort, 49008);
|
||||
closeUDP(sendPort);
|
||||
}
|
||||
|
||||
int main(int argc, const char * argv[])
|
||||
{
|
||||
std::cout << "XPC Tests-cpp ";
|
||||
|
||||
#ifdef _WIN32
|
||||
std::cout << "(Windows)\n";
|
||||
#elif (__APPLE__)
|
||||
std::cout << "(Mac) \n";
|
||||
#elif (__linux)
|
||||
std::cout << "(Linux) \n";
|
||||
#endif
|
||||
|
||||
runTest(openUDPTest);
|
||||
runTest(closeUDPTest);
|
||||
runTest(sendReadTest);
|
||||
runTest(requestDREFTest);
|
||||
runTest(sendDREFTest);
|
||||
runTest(sendDATATest);
|
||||
runTest(sendCTRLTest);
|
||||
runTest(sendPOSITest);
|
||||
runTest(pauseTest);
|
||||
runTest(connTest);
|
||||
|
||||
std::cout << "----------------\nTest Summary\n\tFailed: " << testFailed << "\n\tPassed: " << testPassed << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,240 +0,0 @@
|
||||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 46;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
BE7C5C021A28F72F00F246B9 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BE7C5C001A28F72F00F246B9 /* main.cpp */; };
|
||||
BEB0F4F81A28F7B0001975A6 /* xplaneConnect.c in Sources */ = {isa = PBXBuildFile; fileRef = BEB0F4F61A28F7B0001975A6 /* xplaneConnect.c */; };
|
||||
BEB0F4F91A28F7B0001975A6 /* xplaneConnect.h in Sources */ = {isa = PBXBuildFile; fileRef = BEB0F4F71A28F7B0001975A6 /* xplaneConnect.h */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXCopyFilesBuildPhase section */
|
||||
BE9C6BA91A253FA100EBE08A /* CopyFiles */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
dstPath = /usr/share/man/man1/;
|
||||
dstSubfolderSpec = 0;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 1;
|
||||
};
|
||||
/* End PBXCopyFilesBuildPhase section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
BE7C5C001A28F72F00F246B9 /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = main.cpp; path = "CPP Tests/main.cpp"; sourceTree = SOURCE_ROOT; };
|
||||
BE7C5C011A28F72F00F246B9 /* Cpp_Tests.1 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.man; name = Cpp_Tests.1; path = "CPP Tests/Cpp_Tests.1"; sourceTree = SOURCE_ROOT; };
|
||||
BE9C6BAB1A253FA100EBE08A /* Cpp Tests */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "Cpp Tests"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
BEB0F4F61A28F7B0001975A6 /* xplaneConnect.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = xplaneConnect.c; path = ../C/src/xplaneConnect.c; sourceTree = "<group>"; };
|
||||
BEB0F4F71A28F7B0001975A6 /* xplaneConnect.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = xplaneConnect.h; path = ../C/src/xplaneConnect.h; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
BE9C6BA81A253FA100EBE08A /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
BE9C6BA21A253FA100EBE08A = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
BEB0F4F61A28F7B0001975A6 /* xplaneConnect.c */,
|
||||
BEB0F4F71A28F7B0001975A6 /* xplaneConnect.h */,
|
||||
BE9C6BAD1A253FA100EBE08A /* Cpp Tests */,
|
||||
BE9C6BAC1A253FA100EBE08A /* Products */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
BE9C6BAC1A253FA100EBE08A /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
BE9C6BAB1A253FA100EBE08A /* Cpp Tests */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
BE9C6BAD1A253FA100EBE08A /* Cpp Tests */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
BE7C5C001A28F72F00F246B9 /* main.cpp */,
|
||||
BE7C5C011A28F72F00F246B9 /* Cpp_Tests.1 */,
|
||||
);
|
||||
name = "Cpp Tests";
|
||||
path = "XPC Tests";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
BE9C6BAA1A253FA100EBE08A /* Cpp Tests */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = BE9C6BB41A253FA100EBE08A /* Build configuration list for PBXNativeTarget "Cpp Tests" */;
|
||||
buildPhases = (
|
||||
BE9C6BA71A253FA100EBE08A /* Sources */,
|
||||
BE9C6BA81A253FA100EBE08A /* Frameworks */,
|
||||
BE9C6BA91A253FA100EBE08A /* CopyFiles */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = "Cpp Tests";
|
||||
productName = "XPC Tests";
|
||||
productReference = BE9C6BAB1A253FA100EBE08A /* Cpp Tests */;
|
||||
productType = "com.apple.product-type.tool";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
BE9C6BA31A253FA100EBE08A /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastUpgradeCheck = 0500;
|
||||
ORGANIZATIONNAME = "Chris Teubert";
|
||||
};
|
||||
buildConfigurationList = BE9C6BA61A253FA100EBE08A /* Build configuration list for PBXProject "Cpp Tests" */;
|
||||
compatibilityVersion = "Xcode 3.2";
|
||||
developmentRegion = English;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
);
|
||||
mainGroup = BE9C6BA21A253FA100EBE08A;
|
||||
productRefGroup = BE9C6BAC1A253FA100EBE08A /* Products */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
BE9C6BAA1A253FA100EBE08A /* Cpp Tests */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
BE9C6BA71A253FA100EBE08A /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
BEB0F4F81A28F7B0001975A6 /* xplaneConnect.c in Sources */,
|
||||
BEB0F4F91A28F7B0001975A6 /* xplaneConnect.h in Sources */,
|
||||
BE7C5C021A28F72F00F246B9 /* main.cpp in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
BE9C6BB21A253FA100EBE08A /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.9;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = macosx;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
BE9C6BB31A253FA100EBE08A /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
COPY_PHASE_STRIP = YES;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.9;
|
||||
SDKROOT = macosx;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
BE9C6BB51A253FA100EBE08A /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
PRODUCT_NAME = "Cpp Tests";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
BE9C6BB61A253FA100EBE08A /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
PRODUCT_NAME = "Cpp Tests";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
BE9C6BA61A253FA100EBE08A /* Build configuration list for PBXProject "Cpp Tests" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
BE9C6BB21A253FA100EBE08A /* Debug */,
|
||||
BE9C6BB31A253FA100EBE08A /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
BE9C6BB41A253FA100EBE08A /* Build configuration list for PBXNativeTarget "Cpp Tests" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
BE9C6BB51A253FA100EBE08A /* Debug */,
|
||||
BE9C6BB61A253FA100EBE08A /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = BE9C6BA31A253FA100EBE08A /* Project object */;
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "self:Cpp Tests.xcodeproj">
|
||||
</FileRef>
|
||||
</Workspace>
|
||||
@@ -31,7 +31,7 @@ public class XPlaneConnectTest
|
||||
{
|
||||
fail();
|
||||
}
|
||||
try(XPlaneConnect xpc = new XPlaneConnect(49007, "127.0.0.1", 49009))
|
||||
try(XPlaneConnect xpc = new XPlaneConnect("127.0.0.1", 49009, 49007))
|
||||
{
|
||||
assertNotNull(xpc);
|
||||
}
|
||||
@@ -39,7 +39,7 @@ public class XPlaneConnectTest
|
||||
{
|
||||
fail();
|
||||
}
|
||||
try(XPlaneConnect xpc = new XPlaneConnect(49007, "127.0.0.1", 49009, 200))
|
||||
try(XPlaneConnect xpc = new XPlaneConnect("127.0.0.1", 49009, 49007, 200))
|
||||
{
|
||||
assertNotNull(xpc);
|
||||
}
|
||||
@@ -50,9 +50,9 @@ public class XPlaneConnectTest
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetRecvPort() throws SocketException
|
||||
public void testGetRecvPort() throws Exception
|
||||
{
|
||||
try(XPlaneConnect xpc = new XPlaneConnect())
|
||||
try(XPlaneConnect xpc = new XPlaneConnect("127.0.0.1", 49009, 49008))
|
||||
{
|
||||
assertEquals(49008, xpc.getRecvPort());
|
||||
}
|
||||
@@ -87,11 +87,11 @@ public class XPlaneConnectTest
|
||||
}
|
||||
|
||||
@Test
|
||||
public void constructorTest_SocketAlreadyBound() throws SocketException
|
||||
public void constructorTest_SocketAlreadyBound() throws Exception
|
||||
{
|
||||
try(XPlaneConnect xpc = new XPlaneConnect())
|
||||
try(XPlaneConnect xpc = new XPlaneConnect("127.0.0.1", 49009, 49008))
|
||||
{
|
||||
try(XPlaneConnect xpc2 = new XPlaneConnect())
|
||||
try(XPlaneConnect xpc2 = new XPlaneConnect("127.0.0.1", 49009, 49008))
|
||||
{
|
||||
fail();
|
||||
}
|
||||
@@ -106,7 +106,7 @@ public class XPlaneConnectTest
|
||||
@Test(expected = UnknownHostException.class)
|
||||
public void constructorTest_InvalidHost() throws UnknownHostException
|
||||
{
|
||||
try(XPlaneConnect xpc = new XPlaneConnect(49007, "notarealhost", 49009))
|
||||
try(XPlaneConnect xpc = new XPlaneConnect("notarealhost", 49009, 49007))
|
||||
{
|
||||
|
||||
}
|
||||
@@ -123,7 +123,7 @@ public class XPlaneConnectTest
|
||||
String dref = "sim/cockpit/switches/gear_handle_status";
|
||||
try(XPlaneConnect xpc = new XPlaneConnect())
|
||||
{
|
||||
float[] result = xpc.requestDREF(dref);
|
||||
float[] result = xpc.getDREF(dref);
|
||||
assertEquals(1, result.length);
|
||||
}
|
||||
}
|
||||
@@ -138,7 +138,7 @@ public class XPlaneConnectTest
|
||||
};
|
||||
try(XPlaneConnect xpc = new XPlaneConnect())
|
||||
{
|
||||
float[][] result = xpc.requestDREFs(drefs);
|
||||
float[][] result = xpc.getDREFs(drefs);
|
||||
assertEquals(2, result.length);
|
||||
assertEquals(1, result[0].length);
|
||||
assertEquals(4, result[1].length);
|
||||
@@ -150,7 +150,7 @@ public class XPlaneConnectTest
|
||||
{
|
||||
try(XPlaneConnect xpc = new XPlaneConnect())
|
||||
{
|
||||
xpc.requestDREFs(null);
|
||||
xpc.getDREFs(null);
|
||||
fail();
|
||||
}
|
||||
}
|
||||
@@ -161,7 +161,7 @@ public class XPlaneConnectTest
|
||||
String[] drefs = new String[0];
|
||||
try(XPlaneConnect xpc = new XPlaneConnect())
|
||||
{
|
||||
xpc.requestDREFs(drefs);
|
||||
xpc.getDREFs(drefs);
|
||||
fail();
|
||||
}
|
||||
}
|
||||
@@ -172,7 +172,7 @@ public class XPlaneConnectTest
|
||||
String[] drefs = new String[300];
|
||||
try(XPlaneConnect xpc = new XPlaneConnect())
|
||||
{
|
||||
xpc.requestDREFs(drefs);
|
||||
xpc.getDREFs(drefs);
|
||||
fail();
|
||||
}
|
||||
}
|
||||
@@ -184,7 +184,7 @@ public class XPlaneConnectTest
|
||||
String[] drefs = new String[]{longDREF};
|
||||
try(XPlaneConnect xpc = new XPlaneConnect())
|
||||
{
|
||||
xpc.requestDREFs(drefs);
|
||||
xpc.getDREFs(drefs);
|
||||
fail();
|
||||
}
|
||||
}
|
||||
@@ -195,7 +195,7 @@ public class XPlaneConnectTest
|
||||
String dref = "";
|
||||
try(XPlaneConnect xpc = new XPlaneConnect())
|
||||
{
|
||||
xpc.requestDREF(dref);
|
||||
xpc.getDREF(dref);
|
||||
fail();
|
||||
}
|
||||
}
|
||||
@@ -207,12 +207,12 @@ public class XPlaneConnectTest
|
||||
try(XPlaneConnect xpc = new XPlaneConnect())
|
||||
{
|
||||
xpc.pauseSim(true);
|
||||
float[] result = xpc.requestDREF(dref);
|
||||
float[] result = xpc.getDREF(dref);
|
||||
//assertEquals(1, result.length); //TODO: Why is this result 20 elements long in Java? (It's only one in MATLAB)
|
||||
assertEquals(1, result[0], 1e-4);
|
||||
|
||||
xpc.pauseSim(false);
|
||||
result = xpc.requestDREF(dref);
|
||||
result = xpc.getDREF(dref);
|
||||
//assertEquals(1, result.length);
|
||||
assertEquals(0, result[0], 1e-4);
|
||||
}
|
||||
@@ -305,12 +305,12 @@ public class XPlaneConnectTest
|
||||
String dref = "sim/cockpit/switches/gear_handle_status";
|
||||
try(XPlaneConnect xpc = new XPlaneConnect())
|
||||
{
|
||||
float gearHandle = xpc.requestDREF(dref)[0];
|
||||
float gearHandle = xpc.getDREF(dref)[0];
|
||||
|
||||
float value = gearHandle > 0.5 ? 0 : 1;
|
||||
xpc.sendDREF(dref, value);
|
||||
|
||||
float result = xpc.requestDREF(dref)[0];
|
||||
float result = xpc.getDREF(dref)[0];
|
||||
assertEquals(value, result, 1e-4);
|
||||
}
|
||||
}
|
||||
@@ -348,14 +348,17 @@ public class XPlaneConnectTest
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
@Test
|
||||
public void testSendDREF_MessageTooLong() throws IOException
|
||||
{
|
||||
// NOTE: This test originally ensured that the client restricted messages to 255 bytes in length.
|
||||
// This restriction is no longer necessary, however removing it uncovered a bug that caused
|
||||
// the plugin to do a bad memcpy and crash. This test is left here to ensure that X-Plane
|
||||
// does not crash when given erroneously large value arrays.
|
||||
String dref = "sim/cockpit/switches/gear_handle_status";
|
||||
try(XPlaneConnect xpc = new XPlaneConnect())
|
||||
{
|
||||
xpc.sendDREF(dref, new float[200]);
|
||||
fail();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -396,7 +399,7 @@ public class XPlaneConnectTest
|
||||
try(XPlaneConnect xpc = new XPlaneConnect())
|
||||
{
|
||||
xpc.sendCTRL(ctrl);
|
||||
float[][] result = xpc.requestDREFs(drefs);
|
||||
float[][] result = xpc.getDREFs(drefs);
|
||||
if(result.length < ctrl.length)
|
||||
{
|
||||
fail();
|
||||
@@ -425,8 +428,8 @@ public class XPlaneConnectTest
|
||||
try(XPlaneConnect xpc = new XPlaneConnect())
|
||||
{
|
||||
xpc.sendCTRL(ctrl, 1);
|
||||
float[][] result1 = xpc.requestDREFs(drefs1);
|
||||
float[][] result2 = xpc.requestDREFs(drefs2);
|
||||
float[][] result1 = xpc.getDREFs(drefs1);
|
||||
float[][] result2 = xpc.getDREFs(drefs2);
|
||||
if(result1.length != 4 || result2.length != 2)
|
||||
{
|
||||
fail();
|
||||
@@ -480,7 +483,7 @@ public class XPlaneConnectTest
|
||||
xpc.sendPOSI(posi);
|
||||
//TODO: It seems that these calls are a bit too fast. The dref request often gets stale data, causing the test to fail incorrectly.
|
||||
try {Thread.sleep(100);}catch(InterruptedException ex){}
|
||||
float[][] result = xpc.requestDREFs(drefs);
|
||||
float[][] result = xpc.getDREFs(drefs);
|
||||
xpc.pauseSim(false);
|
||||
if(result.length < posi.length)
|
||||
{
|
||||
@@ -543,7 +546,7 @@ public class XPlaneConnectTest
|
||||
try(XPlaneConnect xpc = new XPlaneConnect())
|
||||
{
|
||||
xpc.sendDATA(data);
|
||||
float[] result = xpc.requestDREF(dref);
|
||||
float[] result = xpc.getDREF(dref);
|
||||
assertEquals(data[0][1], result[0], 1e-4);
|
||||
}
|
||||
}
|
||||
@@ -575,15 +578,9 @@ public class XPlaneConnectTest
|
||||
String dref = "sim/cockpit/switches/gear_handle_status";
|
||||
try(XPlaneConnect xpc = new XPlaneConnect())
|
||||
{
|
||||
int p = xpc.getRecvPort();
|
||||
xpc.setCONN(49055);
|
||||
assertEquals(49055, xpc.getRecvPort());
|
||||
float[] result = xpc.requestDREF(dref);
|
||||
assertEquals(1, result.length);
|
||||
|
||||
xpc.setCONN(p);
|
||||
assertEquals(p, xpc.getRecvPort());
|
||||
result = xpc.requestDREF(dref);
|
||||
float[] result = xpc.getDREF(dref);
|
||||
assertEquals(1, result.length);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
function CTRLTest( )
|
||||
%CTRLTest Summary of this function goes here
|
||||
% Detailed explanation goes here
|
||||
%% Test player aircraft
|
||||
addpath('../../MATLAB')
|
||||
import XPlaneConnect.*
|
||||
|
||||
@@ -14,14 +15,15 @@ THROT = rand();
|
||||
CTRL = [0.0, 0.0, 1.0, THROT, 0.0, 1.0];
|
||||
|
||||
sendCTRL(CTRL);
|
||||
result = requestDREF(DREFS);
|
||||
result = getDREFs(DREFS);
|
||||
|
||||
assert(isequal(length(result),6),'CTRLTest: requestDREF unsucessful-wrong number of elements returned');
|
||||
assert(isequal(length(result{4}),8),'CTRLTest: requestDREF unsucessful- element 1 incorrect size (should be size 8)');
|
||||
assert(isequal(length(result),6),'CTRLTest: getDREFs unsucessful-wrong number of elements returned');
|
||||
assert(isequal(length(result{4}),8),'CTRLTest: getDREFs unsucessful- element 1 incorrect size (should be size 8)');
|
||||
for i=1:length(CTRL)-1
|
||||
assert(abs(result{i}(1)-CTRL(i))<1e-4,['CTRLTest: DATA set unsucessful-',num2str(i)]);
|
||||
end
|
||||
|
||||
%% Test NPC aircraft
|
||||
DREFS = {'sim/multiplayer/position/plane1_yolk_pitch',...
|
||||
'sim/multiplayer/position/plane1_yolk_roll',...
|
||||
'sim/multiplayer/position/plane1_yolk_yaw',...
|
||||
@@ -32,7 +34,7 @@ THROT = rand();
|
||||
CTRL = [0.0, 0.0, 1.0, THROT, 0.0, 1.0];
|
||||
|
||||
sendCTRL(CTRL, 1);
|
||||
result = requestDREF(DREFS);
|
||||
result = getDREFs(DREFS);
|
||||
|
||||
assert(isequal(length(result),6),'CTRLTest: requestDREF unsucessful-wrong number of elements returned');
|
||||
assert(isequal(length(result{4}),8),'CTRLTest: requestDREF unsucessful- element 1 incorrect size (should be size 8)');
|
||||
|
||||
@@ -10,11 +10,10 @@ value = rand();
|
||||
data = struct('h',25,'d',[value,-998,-998,-998,-998,-998,-998,-998]);
|
||||
|
||||
sendDATA(data);
|
||||
result = requestDREF(DREFS);
|
||||
result = getDREFs(DREFS);
|
||||
|
||||
assert(isequal(length(result),1),'DATATest: requestDREF unsucessful-wrong number of elements returned');
|
||||
assert(isequal(length(result{1}),8),'DATATest: requestDREF unsucessful- element 1 incorrect size (should be size 8)');
|
||||
assert(abs(result{1}(1)-value)<1e-4,'DATATest: DATA set unsucessful');
|
||||
assert(isequal(length(result),8),'DATATest: getDREFs unsucessful-wrong number of elements returned');
|
||||
assert(abs(result(1)-value)<1e-4,'DATATest: DATA set unsucessful');
|
||||
|
||||
end
|
||||
|
||||
|
||||
@@ -14,14 +14,14 @@ DREFS = {'sim/flightmodel/position/latitude', ...
|
||||
POSI = [37.524, -122.06899, 2500, 0, 0, 0, 1]; % Gear
|
||||
|
||||
sendPOSI(POSI);
|
||||
result = requestDREF(DREFS);
|
||||
result = getDREFs(DREFS);
|
||||
|
||||
assert(isequal(length(result),7),'POSITest: requestDREF unsucessful-wrong number of elements returned');
|
||||
assert(isequal(length(result),7),'POSITest: getDREFs unsucessful-wrong number of elements returned');
|
||||
for i=1:length(POSI)
|
||||
if i==3
|
||||
continue
|
||||
end
|
||||
assert(abs(result{i}(1)-POSI(i))<1e-4,['POSITest: DATA set unsucessful-',num2str(i)]);
|
||||
assert(abs(result(i)-POSI(i))<1e-4,['POSITest: DATA set unsucessful-',num2str(i)]);
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
function requestDREFTest( )
|
||||
function getDREFsTest( )
|
||||
%SENDREADTEST Summary of this function goes here
|
||||
% Detailed explanation goes here
|
||||
addpath('../../MATLAB')
|
||||
@@ -7,7 +7,7 @@ import XPlaneConnect.*
|
||||
DREFS = {'sim/cockpit/switches/gear_handle_status',...
|
||||
'sim/cockpit2/switches/panel_brightness_ratio'};
|
||||
|
||||
result = requestDREF(DREFS);
|
||||
result = getDREFs(DREFS);
|
||||
|
||||
assert(isequal(length(result),2));
|
||||
assert(isequal(length(result{1}),1));
|
||||
@@ -4,13 +4,10 @@ function openCloseTest()
|
||||
addpath('../../MATLAB')
|
||||
import XPlaneConnect.*
|
||||
|
||||
socket = openUDP( 49007 );
|
||||
|
||||
closeUDP( socket );
|
||||
assert(isequal(socket.isClosed(),1),'openCloseTest: socket is still open');
|
||||
|
||||
socket = openUDP( 49007 );
|
||||
closeUDP( socket );
|
||||
socket = openUDP();
|
||||
closeUDP(socket);
|
||||
socket = openUDP();
|
||||
closeUDP(socket);
|
||||
|
||||
end
|
||||
|
||||
|
||||
@@ -9,17 +9,15 @@ DREFS = {'sim/operation/override/override_planepath'};
|
||||
value = 1; % Pause
|
||||
|
||||
pauseSim(value);
|
||||
result = requestDREF(DREFS);
|
||||
result = getDREFs(DREFS);
|
||||
|
||||
assert(isequal(length(result),1),'pauseTest: requestDREF unsucessful-wrong number of elements returned');
|
||||
assert(abs(result{1}(1)-value)<1e-4,'pauseTest: Pause Unsuccessful');
|
||||
assert(abs(result(1)-value)<1e-4,'pauseTest: Pause Unsuccessful');
|
||||
value = 0; % Resume
|
||||
|
||||
pauseSim(value);
|
||||
result = requestDREF(DREFS);
|
||||
result = getDREFs(DREFS);
|
||||
|
||||
assert(isequal(length(result),1),'pauseTest: requestDREF unsucessful-wrong number of elements returned');
|
||||
assert(abs(result{1}(1)-value)<1e-4,'pauseTest: Pause Unsuccessful');
|
||||
assert(abs(result(1)-value)<1e-4,'pauseTest: Pause Unsuccessful');
|
||||
|
||||
end
|
||||
|
||||
|
||||
@@ -8,12 +8,11 @@ DREFS = {'sim/cockpit/switches/gear_handle_status'};
|
||||
value = randi([0 10]);
|
||||
|
||||
sendDREF(DREFS{1},value);
|
||||
result = requestDREF(DREFS);
|
||||
result = getDREFs(DREFS);
|
||||
|
||||
assert(isequal(length(result),1),'sendDREFTest: requestDREF unsucessful-wrong number of elements returned');
|
||||
assert(isequal(length(result{1}),1),'sendDREFTest: requestDREF unsucessful- element 1 incorrect size (should be size 1)');
|
||||
assert(isequal(length(result),1),'setDREFTest: requestDREF unsucessful-wrong number of elements returned');
|
||||
|
||||
assert(isequal(result{1},value),'sendDREFTest: DREF set unsucessful');
|
||||
assert(isequal(result(1),value),'setDREFTest: DREF set unsucessful');
|
||||
|
||||
end
|
||||
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
function sendReadTest( )
|
||||
%SENDREADTEST Summary of this function goes here
|
||||
% Detailed explanation goes here
|
||||
addpath('../../MATLAB')
|
||||
import XPlaneConnect.*
|
||||
|
||||
recvPortNum = 49074;
|
||||
recvPort = openUDP(49074);
|
||||
|
||||
sendUDP('test2'-0,'127.0.0.1',49074);
|
||||
result = readUDP(recvPort);
|
||||
closeUDP(recvPort);
|
||||
|
||||
assert(~isequal(result,-998), 'no data received');
|
||||
assert(all(result(1:4)'=='test'-0));
|
||||
|
||||
end
|
||||
|
||||
@@ -8,7 +8,7 @@ import XPlaneConnect.*
|
||||
DREFS = {'sim/cockpit/switches/gear_handle_status'};
|
||||
|
||||
setConn(49055);
|
||||
result = requestDREF(DREFS);
|
||||
result = getDREFs(DREFS);
|
||||
|
||||
assert(isequal(length(result),1),'setConnTest: requestDREF unsucessful-wrong number of elements returned');
|
||||
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
function struTest( )
|
||||
%STRUTEST Summary of this function goes here
|
||||
% Detailed explanation goes here
|
||||
addpath('../../MATLAB')
|
||||
import XPlaneConnect.*
|
||||
|
||||
recvNum = 49076;
|
||||
recvPort = openUDP(recvNum);
|
||||
|
||||
testSTRU = struct('h',15,'d',[12, 34, 55, 99, 1, 0],'test','theTest');
|
||||
|
||||
sendSTRU(testSTRU,'127.0.0.1',recvNum);
|
||||
resultSTRU = readDATA(recvPort);
|
||||
closeUDP(recvPort);
|
||||
resultSTRU = rmfield(resultSTRU,'raw');
|
||||
assert(isequal(testSTRU,resultSTRU),'struTest: Error-structs are not equal');
|
||||
|
||||
end
|
||||
|
||||
@@ -11,16 +11,14 @@ end
|
||||
disp(['XPC Tests-MATLAB (', os, ')']);
|
||||
|
||||
theTests = {{@openCloseTest, 'Open/Close Test', 0},...
|
||||
{@sendReadTest,'Send/Read Test', 0},...
|
||||
{@sendTEXTTest,'TEXT Test', 0},...
|
||||
{@requestDREFTest,'Request DREF Test', 0},...
|
||||
{@getDREFsTest,'Request DREF Test', 0},...
|
||||
{@sendDREFTest,'Send DREF Test', 0},...
|
||||
{@DATATest,'DATA Test', 0},...
|
||||
{@CTRLTest,'CTRL Test', 0},...
|
||||
{@POSITest,'POSI Test', 0},...
|
||||
{@sendWYPTTest,'WYPT Test', 0},...
|
||||
{@pauseTest,'Pause Test', 0},...
|
||||
{@struTest,'Struct Test', 0},...
|
||||
{@setConnTest, 'setConn Test', 0}};
|
||||
|
||||
for i=1:length(theTests)
|
||||
|
||||
38
xpcPlugin/CMakeLists.txt
Normal file
38
xpcPlugin/CMakeLists.txt
Normal file
@@ -0,0 +1,38 @@
|
||||
cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
|
||||
|
||||
project(XPlaneConnect)
|
||||
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
|
||||
include_directories(SDK/CHeaders/XPLM)
|
||||
include_directories(../C/src)
|
||||
|
||||
add_definitions(-DXPLM200 -DLIN=1)
|
||||
|
||||
SET(CMAKE_C_COMPILER gcc)
|
||||
SET(CMAKE_CXX_COMPILER g++)
|
||||
|
||||
add_library(xpc64 SHARED XPCPlugin.cpp
|
||||
DataManager.cpp
|
||||
DataMaps.cpp
|
||||
Drawing.cpp
|
||||
Log.cpp
|
||||
Message.cpp
|
||||
MessageHandlers.cpp
|
||||
UDPSocket.cpp)
|
||||
set_target_properties(xpc64 PROPERTIES PREFIX "" SUFFIX ".xpl")
|
||||
set_target_properties(xpc64 PROPERTIES COMPILE_FLAGS "-m64" LINK_FLAGS "-shared -rdynamic -nodefaultlibs -undefined_warning -m64")
|
||||
|
||||
add_library(xpc32 SHARED XPCPlugin.cpp
|
||||
DataManager.cpp
|
||||
DataMaps.cpp
|
||||
Drawing.cpp
|
||||
Log.cpp
|
||||
Message.cpp
|
||||
MessageHandlers.cpp
|
||||
UDPSocket.cpp)
|
||||
set_target_properties(xpc32 PROPERTIES PREFIX "" SUFFIX ".xpl")
|
||||
set_target_properties(xpc32 PROPERTIES COMPILE_FLAGS "-m32" LINK_FLAGS "-shared -rdynamic -nodefaultlibs -undefined_warning -m32")
|
||||
|
||||
# Switch install targets when uncommenting the 32 bit line above.
|
||||
install(TARGETS xpc64 DESTINATION XPlaneConnect/64 RENAME lin.xpl)
|
||||
install(TARGETS xpc32 DESTINATION XPlaneConnect/ RENAME lin.xpl)
|
||||
818
xpcPlugin/DataManager.cpp
Normal file
818
xpcPlugin/DataManager.cpp
Normal file
@@ -0,0 +1,818 @@
|
||||
//Copyright (c) 2013-2015 United States Government as represented by the Administrator of the
|
||||
//National Aeronautics and Space Administration. All Rights Reserved.
|
||||
//
|
||||
//X-Plane API
|
||||
//Copyright(c) 2008, Sandy Barbour and Ben Supnik All rights reserved.
|
||||
//Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
|
||||
//associated documentation files(the "Software"), to deal in the Software without restriction,
|
||||
//including without limitation the rights to use, copy, modify, merge, publish, distribute,
|
||||
//sublicense, and / or sell copies of the Software, and to permit persons to whom the Software is
|
||||
//furnished to do so, subject to the following conditions :
|
||||
// * Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
// * Neither the names of the authors nor that of X - Plane or Laminar Research
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission from the authors or
|
||||
// Laminar Research, respectively.
|
||||
#include "DataManager.h"
|
||||
#include "DataMaps.h"
|
||||
#include "Log.h"
|
||||
|
||||
#include "XPLMDataAccess.h"
|
||||
#include "XPLMGraphics.h"
|
||||
|
||||
#include <cmath>
|
||||
#include <cstdio>
|
||||
#include <map>
|
||||
|
||||
namespace XPC
|
||||
{
|
||||
using namespace std;
|
||||
|
||||
static map<DREF, XPLMDataRef> drefs;
|
||||
static map<DREF, XPLMDataRef> mdrefs[20];
|
||||
static map<string, XPLMDataRef> sdrefs;
|
||||
|
||||
void DataManager::Initialize()
|
||||
{
|
||||
drefs.insert(make_pair(DREF_None, XPLMFindDataRef("sim/test/test_float")));
|
||||
|
||||
drefs.insert(make_pair(DREF_Pause, XPLMFindDataRef("sim/operation/override/override_planepath")));
|
||||
drefs.insert(make_pair(DREF_PauseAI, XPLMFindDataRef("sim/operation/override/override_plane_ai_autopilot")));
|
||||
|
||||
drefs.insert(make_pair(DREF_TotalRuntime, XPLMFindDataRef("sim/time/total_running_time_sec")));
|
||||
drefs.insert(make_pair(DREF_TotalFlighttime, XPLMFindDataRef("sim/time/total_flight_time_sec")));
|
||||
drefs.insert(make_pair(DREF_TimerElapsedtime, XPLMFindDataRef("sim/time/timer_elapsed_time_sec")));
|
||||
|
||||
drefs.insert(make_pair(DREF_IndicatedAirspeed, XPLMFindDataRef("sim/flightmodel/position/indicated_airspeed")));
|
||||
drefs.insert(make_pair(DREF_TrueAirspeed, XPLMFindDataRef("sim/flightmodel/position/true_airspeed")));
|
||||
drefs.insert(make_pair(DREF_GroundSpeed, XPLMFindDataRef("sim/flightmodel/position/groundspeed")));
|
||||
|
||||
drefs.insert(make_pair(DREF_MachNumber, XPLMFindDataRef("sim/flightmodel/misc/machno")));
|
||||
drefs.insert(make_pair(DREF_GForceNormal, XPLMFindDataRef("sim/flightmodel2/misc/gforce_normal")));
|
||||
drefs.insert(make_pair(DREF_GForceAxial, XPLMFindDataRef("sim/flightmodel2/misc/gforce_axial")));
|
||||
drefs.insert(make_pair(DREF_GForceSide, XPLMFindDataRef("sim/flightmodel2/misc/gforce_side")));
|
||||
|
||||
drefs.insert(make_pair(DREF_BarometerSealevelInHg, XPLMFindDataRef("sim/weather/barometer_sealevel_inhg")));
|
||||
drefs.insert(make_pair(DREF_TemperaturSealevelC, XPLMFindDataRef("sim/weather/temperature_sealevel_c")));
|
||||
drefs.insert(make_pair(DREF_WindSpeedKts, XPLMFindDataRef("sim/cockpit2/gauges/indicators/wind_speed_kts")));
|
||||
|
||||
drefs.insert(make_pair(DREF_YokePitch, XPLMFindDataRef("sim/joystick/yoke_pitch_ratio")));
|
||||
drefs.insert(make_pair(DREF_YokeRoll, XPLMFindDataRef("sim/joystick/yoke_roll_ratio")));
|
||||
drefs.insert(make_pair(DREF_YokeHeading, XPLMFindDataRef("sim/joystick/yoke_heading_ratio")));
|
||||
|
||||
drefs.insert(make_pair(DREF_Elevator, XPLMFindDataRef("sim/cockpit2/controls/yoke_pitch_ratio")));
|
||||
drefs.insert(make_pair(DREF_Aileron, XPLMFindDataRef("sim/cockpit2/controls/yoke_roll_ratio")));
|
||||
drefs.insert(make_pair(DREF_Rudder, XPLMFindDataRef("sim/cockpit2/controls/yoke_heading_ratio")));
|
||||
|
||||
drefs.insert(make_pair(DREF_FlapSetting, XPLMFindDataRef("sim/flightmodel/controls/flaprqst")));
|
||||
drefs.insert(make_pair(DREF_FlapActual, XPLMFindDataRef("sim/flightmodel/controls/flaprat")));
|
||||
|
||||
drefs.insert(make_pair(DREF_GearDeploy, XPLMFindDataRef("sim/aircraft/parts/acf_gear_deploy")));
|
||||
drefs.insert(make_pair(DREF_GearHandle, XPLMFindDataRef("sim/cockpit/switches/gear_handle_status")));
|
||||
drefs.insert(make_pair(DREF_BrakeParking, XPLMFindDataRef("sim/flightmodel/controls/parkbrakel")));
|
||||
drefs.insert(make_pair(DREF_BrakeLeft, XPLMFindDataRef("sim/cockpit2/controls/left_brake_ratio")));
|
||||
drefs.insert(make_pair(DREF_BrakeRight, XPLMFindDataRef("sim/cockpit2/controls/right_brake_ratio")));
|
||||
|
||||
drefs.insert(make_pair(DREF_M, XPLMFindDataRef("sim/flightmodel/position/M")));
|
||||
drefs.insert(make_pair(DREF_L, XPLMFindDataRef("sim/flightmodel/position/L")));
|
||||
drefs.insert(make_pair(DREF_N, XPLMFindDataRef("sim/flightmodel/position/N")));
|
||||
|
||||
drefs.insert(make_pair(DREF_QRad, XPLMFindDataRef("sim/flightmodel/position/Qrad")));
|
||||
drefs.insert(make_pair(DREF_PRad, XPLMFindDataRef("sim/flightmodel/position/Prad")));
|
||||
drefs.insert(make_pair(DREF_RRad, XPLMFindDataRef("sim/flightmodel/position/Rrad")));
|
||||
drefs.insert(make_pair(DREF_Q, XPLMFindDataRef("sim/flightmodel/position/Q")));
|
||||
drefs.insert(make_pair(DREF_P, XPLMFindDataRef("sim/flightmodel/position/P")));
|
||||
drefs.insert(make_pair(DREF_R, XPLMFindDataRef("sim/flightmodel/position/R")));
|
||||
|
||||
drefs.insert(make_pair(DREF_Pitch, XPLMFindDataRef("sim/flightmodel/position/theta")));
|
||||
drefs.insert(make_pair(DREF_Roll, XPLMFindDataRef("sim/flightmodel/position/phi")));
|
||||
drefs.insert(make_pair(DREF_HeadingTrue, XPLMFindDataRef("sim/flightmodel/position/psi")));
|
||||
drefs.insert(make_pair(DREF_HeadingMag, XPLMFindDataRef("sim/flightmodel/position/magpsi")));
|
||||
drefs.insert(make_pair(DREF_Quaternion, XPLMFindDataRef("sim/flightmodel/position/q")));
|
||||
|
||||
drefs.insert(make_pair(DREF_AngleOfAttack, XPLMFindDataRef("sim/flightmodel/position/alpha")));
|
||||
drefs.insert(make_pair(DREF_Sideslip, XPLMFindDataRef("sim/cockpit2/gauges/indicators/sideslip_degrees")));
|
||||
drefs.insert(make_pair(DREF_HPath, XPLMFindDataRef("sim/flightmodel/position/hpath")));
|
||||
drefs.insert(make_pair(DREF_VPath, XPLMFindDataRef("sim/flightmodel/position/vpath")));
|
||||
|
||||
drefs.insert(make_pair(DREF_VPath, XPLMFindDataRef("sim/flightmodel/position/magnetic_variation")));
|
||||
|
||||
drefs.insert(make_pair(DREF_Latitude, XPLMFindDataRef("sim/flightmodel/position/latitude")));
|
||||
drefs.insert(make_pair(DREF_Longitude, XPLMFindDataRef("sim/flightmodel/position/longitude")));
|
||||
drefs.insert(make_pair(DREF_AGL, XPLMFindDataRef("sim/flightmodel/position/y_agl")));
|
||||
drefs.insert(make_pair(DREF_Elevation, XPLMFindDataRef("sim/flightmodel/position/elevation")));
|
||||
|
||||
drefs.insert(make_pair(DREF_LocalX, XPLMFindDataRef("sim/flightmodel/position/local_x")));
|
||||
drefs.insert(make_pair(DREF_LocalY, XPLMFindDataRef("sim/flightmodel/position/local_y")));
|
||||
drefs.insert(make_pair(DREF_LocalZ, XPLMFindDataRef("sim/flightmodel/position/local_z")));
|
||||
drefs.insert(make_pair(DREF_LocalVX, XPLMFindDataRef("sim/flightmodel/position/local_vx")));
|
||||
drefs.insert(make_pair(DREF_LocalVY, XPLMFindDataRef("sim/flightmodel/position/local_vy")));
|
||||
drefs.insert(make_pair(DREF_LocalVZ, XPLMFindDataRef("sim/flightmodel/position/local_vz")));
|
||||
|
||||
drefs.insert(make_pair(DREF_ThrottleSet, XPLMFindDataRef("sim/flightmodel/engine/ENGN_thro")));
|
||||
drefs.insert(make_pair(DREF_ThrottleActual, XPLMFindDataRef("sim/flightmodel2/engines/throttle_used_ratio")));
|
||||
|
||||
drefs.insert(make_pair(DREF_MP1Lat, XPLMFindDataRef("sim/multiplayer/position/plane1_lat")));
|
||||
drefs.insert(make_pair(DREF_MP2Lat, XPLMFindDataRef("sim/multiplayer/position/plane2_lat")));
|
||||
drefs.insert(make_pair(DREF_MP3Lat, XPLMFindDataRef("sim/multiplayer/position/plane3_lat")));
|
||||
drefs.insert(make_pair(DREF_MP4Lat, XPLMFindDataRef("sim/multiplayer/position/plane4_lat")));
|
||||
drefs.insert(make_pair(DREF_MP5Lat, XPLMFindDataRef("sim/multiplayer/position/plane5_lat")));
|
||||
drefs.insert(make_pair(DREF_MP6Lat, XPLMFindDataRef("sim/multiplayer/position/plane6_lat")));
|
||||
drefs.insert(make_pair(DREF_MP7Lat, XPLMFindDataRef("sim/multiplayer/position/plane7_lat")));
|
||||
|
||||
drefs.insert(make_pair(DREF_MP1Lon, XPLMFindDataRef("sim/multiplayer/position/plane1_lon")));
|
||||
drefs.insert(make_pair(DREF_MP2Lon, XPLMFindDataRef("sim/multiplayer/position/plane2_lon")));
|
||||
drefs.insert(make_pair(DREF_MP3Lon, XPLMFindDataRef("sim/multiplayer/position/plane3_lon")));
|
||||
drefs.insert(make_pair(DREF_MP4Lon, XPLMFindDataRef("sim/multiplayer/position/plane4_lon")));
|
||||
drefs.insert(make_pair(DREF_MP5Lon, XPLMFindDataRef("sim/multiplayer/position/plane5_lon")));
|
||||
drefs.insert(make_pair(DREF_MP6Lon, XPLMFindDataRef("sim/multiplayer/position/plane6_lon")));
|
||||
drefs.insert(make_pair(DREF_MP7Lon, XPLMFindDataRef("sim/multiplayer/position/plane7_lon")));
|
||||
|
||||
drefs.insert(make_pair(DREF_MP1Alt, XPLMFindDataRef("sim/multiplayer/position/plane1_el")));
|
||||
drefs.insert(make_pair(DREF_MP2Alt, XPLMFindDataRef("sim/multiplayer/position/plane2_el")));
|
||||
drefs.insert(make_pair(DREF_MP3Alt, XPLMFindDataRef("sim/multiplayer/position/plane3_el")));
|
||||
drefs.insert(make_pair(DREF_MP4Alt, XPLMFindDataRef("sim/multiplayer/position/plane4_el")));
|
||||
drefs.insert(make_pair(DREF_MP5Alt, XPLMFindDataRef("sim/multiplayer/position/plane5_el")));
|
||||
drefs.insert(make_pair(DREF_MP6Alt, XPLMFindDataRef("sim/multiplayer/position/plane6_el")));
|
||||
drefs.insert(make_pair(DREF_MP7Alt, XPLMFindDataRef("sim/multiplayer/position/plane7_el")));
|
||||
|
||||
char multi[256];
|
||||
for (int i = 1; i < 20; i++)
|
||||
{
|
||||
sprintf(multi, "sim/multiplayer/position/plane%i_x", i);
|
||||
mdrefs[i][DREF_LocalX] = XPLMFindDataRef(multi);
|
||||
sprintf(multi, "sim/multiplayer/position/plane%i_y", i);
|
||||
mdrefs[i][DREF_LocalY] = XPLMFindDataRef(multi);
|
||||
sprintf(multi, "sim/multiplayer/position/plane%i_z", i);
|
||||
mdrefs[i][DREF_LocalZ] = XPLMFindDataRef(multi);
|
||||
sprintf(multi, "sim/multiplayer/position/plane%i_lat", i);
|
||||
mdrefs[i][DREF_Latitude] = XPLMFindDataRef(multi);
|
||||
sprintf(multi, "sim/multiplayer/position/plane%i_lon", i);
|
||||
mdrefs[i][DREF_Longitude] = XPLMFindDataRef(multi);
|
||||
sprintf(multi, "sim/multiplayer/position/plane%i_el", i);
|
||||
mdrefs[i][DREF_Elevation] = XPLMFindDataRef(multi);
|
||||
sprintf(multi, "sim/multiplayer/position/plane%i_the", i);
|
||||
mdrefs[i][DREF_Pitch] = XPLMFindDataRef(multi);
|
||||
sprintf(multi, "sim/multiplayer/position/plane%i_phi", i);
|
||||
mdrefs[i][DREF_Roll] = XPLMFindDataRef(multi);
|
||||
sprintf(multi, "sim/multiplayer/position/plane%i_psi", i);
|
||||
mdrefs[i][DREF_HeadingTrue] = XPLMFindDataRef(multi);
|
||||
sprintf(multi, "sim/multiplayer/position/plane%i_gear_deploy", i);
|
||||
mdrefs[i][DREF_GearDeploy] = XPLMFindDataRef(multi);
|
||||
sprintf(multi, "sim/multiplayer/position/plane%i_flap_ratio", i);
|
||||
mdrefs[i][DREF_FlapSetting] = XPLMFindDataRef(multi); // Can't set the actual flap setting on npc aircraft
|
||||
mdrefs[i][DREF_FlapActual] = XPLMFindDataRef(multi);
|
||||
sprintf(multi, "sim/multiplayer/position/plane%i_flap_ratio2", i);
|
||||
mdrefs[i][DREF_FlapActual2] = XPLMFindDataRef(multi);
|
||||
sprintf(multi, "sim/multiplayer/position/plane%i_spoiler_ratio", i);
|
||||
mdrefs[i][DREF_Spoiler] = XPLMFindDataRef(multi);
|
||||
sprintf(multi, "sim/multiplayer/position/plane%i_speedbrake_ratio", i);
|
||||
mdrefs[i][DREF_BrakeSpeed] = XPLMFindDataRef(multi);
|
||||
sprintf(multi, "sim/multiplayer/position/plane%i_slat_ratio", i);
|
||||
mdrefs[i][DREF_Slats] = XPLMFindDataRef(multi);
|
||||
sprintf(multi, "sim/multiplayer/position/plane%i_wing_sweep", i);
|
||||
mdrefs[i][DREF_Sweep] = XPLMFindDataRef(multi);
|
||||
sprintf(multi, "sim/multiplayer/position/plane%i_throttle", i);
|
||||
mdrefs[i][DREF_ThrottleActual] = XPLMFindDataRef(multi);
|
||||
sprintf(multi, "sim/multiplayer/position/plane%i_yolk_pitch", i);
|
||||
mdrefs[i][DREF_YokePitch] = XPLMFindDataRef(multi);
|
||||
sprintf(multi, "sim/multiplayer/position/plane%i_yolk_roll", i);
|
||||
mdrefs[i][DREF_YokeRoll] = XPLMFindDataRef(multi);
|
||||
sprintf(multi, "sim/multiplayer/position/plane%i_yolk_yaw", i);
|
||||
mdrefs[i][DREF_YokeHeading] = XPLMFindDataRef(multi);
|
||||
}
|
||||
|
||||
// Row 0: Frame Rates
|
||||
// Row 1: Times
|
||||
XPData[1][1] = DREF_TotalRuntime;
|
||||
XPData[1][2] = DREF_TotalFlighttime;
|
||||
XPData[1][3] = DREF_TimerElapsedtime;
|
||||
// Row 2: Sim stats
|
||||
// Row 3: Velocities
|
||||
XPData[3][0] = DREF_IndicatedAirspeed;
|
||||
XPData[3][2] = DREF_TrueAirspeed;
|
||||
XPData[3][4] = DREF_GroundSpeed;
|
||||
// Row 4: Mach, VVI, G-Loads
|
||||
XPData[4][0] = DREF_MachNumber;
|
||||
XPData[4][4] = DREF_GForceNormal;
|
||||
XPData[4][5] = DREF_GForceAxial;
|
||||
XPData[4][6] = DREF_GForceSide;
|
||||
// Row 5: Atmosphere: Weather
|
||||
XPData[5][0] = DREF_BarometerSealevelInHg;
|
||||
XPData[5][1] = DREF_TemperaturSealevelC;
|
||||
XPData[5][3] = DREF_WindSpeedKts;
|
||||
// Row 6: Atmosphere: Aircraft
|
||||
// Row 7: System Pressures
|
||||
// Row 8: Joystick
|
||||
XPData[8][0] = DREF_YokePitch;
|
||||
XPData[8][1] = DREF_YokeRoll;
|
||||
XPData[8][2] = DREF_YokeHeading;
|
||||
// Row 9: Other Flight Controls
|
||||
// Row 10: Art stab ail/elv/rud
|
||||
// Row 11: Control Surfaces
|
||||
XPData[11][0] = DREF_Elevator;
|
||||
XPData[11][1] = DREF_Aileron;
|
||||
XPData[11][2] = DREF_Rudder;
|
||||
// Row 12: Wing Sweep/Trust Vec
|
||||
// Row 13: trip/flap/slat/s-brakes
|
||||
XPData[13][3] = DREF_FlapSetting;
|
||||
XPData[13][4] = DREF_FlapActual;
|
||||
// Row 14: Gear, Brakes
|
||||
XPData[14][0] = DREF_GearDeploy;
|
||||
XPData[14][1] = DREF_BrakeParking;
|
||||
XPData[14][2] = DREF_BrakeLeft;
|
||||
XPData[14][3] = DREF_BrakeRight;
|
||||
XPData[14][7] = DREF_GearHandle;
|
||||
// Row 15: MNR (Angular Moments)
|
||||
XPData[15][0] = DREF_M;
|
||||
XPData[15][1] = DREF_L;
|
||||
XPData[15][2] = DREF_N;
|
||||
// Row 16: PQR (Angular Velocities)
|
||||
XPData[16][0] = DREF_QRad;
|
||||
XPData[16][1] = DREF_PRad;
|
||||
XPData[16][2] = DREF_RRad;
|
||||
XPData[16][3] = DREF_Q;
|
||||
XPData[16][4] = DREF_P;
|
||||
XPData[16][5] = DREF_R;
|
||||
// Row 17: Orientation: pitch, roll, yaw, heading
|
||||
XPData[17][0] = DREF_Pitch;
|
||||
XPData[17][1] = DREF_Roll;
|
||||
XPData[17][2] = DREF_HeadingTrue;
|
||||
XPData[17][3] = DREF_HeadingMag;
|
||||
XPData[17][4] = DREF_Quaternion;
|
||||
// Row 18: Orientation: alpha beta hpath vpath slip
|
||||
XPData[18][0] = DREF_AngleOfAttack;
|
||||
XPData[18][1] = DREF_Sideslip;
|
||||
XPData[18][2] = DREF_HPath;
|
||||
XPData[18][3] = DREF_VPath;
|
||||
XPData[18][4] = DREF_Sideslip;
|
||||
// Row 19: Mag Compass
|
||||
XPData[19][0] = DREF_HeadingMag;
|
||||
XPData[19][1] = DREF_MagneticVariation;
|
||||
// Row 20: Global Position
|
||||
XPData[20][0] = DREF_Latitude;
|
||||
XPData[20][1] = DREF_Longitude;
|
||||
XPData[20][2] = DREF_Elevation;
|
||||
XPData[20][3] = DREF_AGL;
|
||||
// Row 21: Local Position, Velocity
|
||||
XPData[21][0] = DREF_LocalX;
|
||||
XPData[21][1] = DREF_LocalY;
|
||||
XPData[21][2] = DREF_LocalZ;
|
||||
XPData[21][3] = DREF_LocalVX;
|
||||
XPData[21][4] = DREF_LocalVY;
|
||||
XPData[21][5] = DREF_LocalVZ;
|
||||
// Row 22: All Planes: Lat
|
||||
XPData[22][0] = DREF_Latitude;
|
||||
XPData[22][1] = DREF_MP1Lat;
|
||||
XPData[22][2] = DREF_MP2Lat;
|
||||
XPData[22][3] = DREF_MP3Lat;
|
||||
XPData[22][4] = DREF_MP4Lat;
|
||||
XPData[22][5] = DREF_MP5Lat;
|
||||
XPData[22][6] = DREF_MP6Lat;
|
||||
XPData[22][7] = DREF_MP7Lat;
|
||||
// Row 23: All Planes: Lon
|
||||
XPData[23][0] = DREF_Longitude;
|
||||
XPData[23][1] = DREF_MP1Lon;
|
||||
XPData[23][2] = DREF_MP2Lon;
|
||||
XPData[23][3] = DREF_MP3Lon;
|
||||
XPData[23][4] = DREF_MP4Lon;
|
||||
XPData[23][5] = DREF_MP5Lon;
|
||||
XPData[23][6] = DREF_MP6Lon;
|
||||
XPData[23][7] = DREF_MP7Lon;
|
||||
// Row 22: All Planes: Alt
|
||||
XPData[24][0] = DREF_AGL;
|
||||
XPData[24][1] = DREF_MP1Alt;
|
||||
XPData[24][2] = DREF_MP2Alt;
|
||||
XPData[24][3] = DREF_MP3Alt;
|
||||
XPData[24][4] = DREF_MP4Alt;
|
||||
XPData[24][5] = DREF_MP5Alt;
|
||||
XPData[24][6] = DREF_MP6Alt;
|
||||
XPData[24][7] = DREF_MP7Alt;
|
||||
// Row 25: Throttle Command
|
||||
XPData[25][0] = DREF_ThrottleSet;
|
||||
// Row 26: Throttle Actual
|
||||
XPData[26][0] = DREF_ThrottleActual;
|
||||
}
|
||||
|
||||
int DataManager::Get(string dref, float values[], int size)
|
||||
{
|
||||
XPLMDataRef& xdref = sdrefs[dref];
|
||||
if (xdref == NULL)
|
||||
{
|
||||
xdref = XPLMFindDataRef(dref.c_str());
|
||||
}
|
||||
if (!xdref) // DREF does not exist
|
||||
{
|
||||
#if LOG_VERBOSITY > 0
|
||||
Log::FormatLine("[DMAN] ERROR: invalid DREF %s", dref.c_str());
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
XPLMDataTypeID dataType = XPLMGetDataRefTypes(xdref);
|
||||
#if LOG_VERBOSITY > 4
|
||||
Log::FormatLine("[DMAN] Get DREF %s (x:%X) Type: %i", dref.c_str(), xdref, dataType);
|
||||
#endif
|
||||
// XPLMDataTypeID is a bit flag, so it may contain more than one of the
|
||||
// following types. We prefer types as close to float as possible.
|
||||
if ((dataType & 2) == 2) // Float
|
||||
{
|
||||
values[0] = XPLMGetDataf(xdref);
|
||||
#if LOG_VERBOSITY > 4
|
||||
Log::FormatLine("[DMAN] -- value was %f", values[0]);
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
if ((dataType & 8) == 8) // Float array
|
||||
{
|
||||
int drefSize = XPLMGetDatavf(xdref, NULL, 0, 0);
|
||||
if (drefSize > size)
|
||||
{
|
||||
#if LOG_VERBOSITY > 1
|
||||
Log::WriteLine("[DMAN] WARN: dref size is larger than available space");
|
||||
Log::FormatLine(" Actual dref size: %i, Available size: %i", drefSize, size);
|
||||
#endif
|
||||
drefSize = size;
|
||||
}
|
||||
XPLMGetDatavf(xdref, values, 0, drefSize);
|
||||
#if LOG_VERBOSITY > 4
|
||||
Log::FormatLine("[DMAN] -- value count was %i", drefSize);
|
||||
#endif
|
||||
return drefSize;
|
||||
}
|
||||
if ((dataType & 4) == 4) // Double
|
||||
{
|
||||
values[0] = (float)XPLMGetDatad(xdref);
|
||||
#if LOG_VERBOSITY > 4
|
||||
Log::FormatLine("[DMAN] -- value was %f", values[0]);
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
if ((dataType & 1) == 1) // Integer
|
||||
{
|
||||
values[0] = (float)XPLMGetDatai(xdref);
|
||||
#if LOG_VERBOSITY > 4
|
||||
Log::FormatLine("[DMAN] -- value was %i", (int)values[0]);
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
if ((dataType & 16) == 16) // Integer array
|
||||
{
|
||||
int iValues[200];
|
||||
int drefSize = XPLMGetDatavi(xdref, NULL, 0, 0);
|
||||
if (drefSize > size)
|
||||
{
|
||||
#if LOG_VERBOSITY > 1
|
||||
Log::WriteLine("[DMAN] WARN: dref size is larger than available space");
|
||||
Log::FormatLine(" Actual dref size: %i, Available size: %i", drefSize, size);
|
||||
#endif
|
||||
drefSize = size;
|
||||
}
|
||||
if (drefSize > 200)
|
||||
{
|
||||
#if LOG_VERBOSITY > 1
|
||||
Log::WriteLine("[DMAN] WARN: dref size is larger than temp buffer");
|
||||
Log::FormatLine(" Actual dref size: %i, Temp buffer size: 200", drefSize);
|
||||
#endif
|
||||
drefSize = 200;
|
||||
}
|
||||
XPLMGetDatavi(xdref, iValues, 0, drefSize);
|
||||
for (int i = 0; i < drefSize; ++i)
|
||||
{
|
||||
values[i] = (float)iValues[i];
|
||||
}
|
||||
#if LOG_VERBOSITY > 4
|
||||
Log::FormatLine("[DMAN] -- value count was %i", drefSize);
|
||||
#endif
|
||||
return drefSize;
|
||||
}
|
||||
if ((dataType & 32) == 32) // Byte array
|
||||
{
|
||||
char bValues[1024];
|
||||
int drefSize = XPLMGetDatab(xdref, NULL, 0, 0);
|
||||
if (drefSize > size)
|
||||
{
|
||||
#if LOG_VERBOSITY > 1
|
||||
Log::WriteLine("[DMAN] WARN: dref size is larger than available space");
|
||||
Log::FormatLine(" Actual dref size: %i, Available size: %i", drefSize, size);
|
||||
#endif
|
||||
drefSize = size;
|
||||
}
|
||||
if (drefSize > 1024)
|
||||
{
|
||||
#if LOG_VERBOSITY > 1
|
||||
Log::WriteLine("[DMAN] WARN: dref size is larger than temp buffer");
|
||||
Log::FormatLine(" Actual dref size: %i, Temp buffer size: 1024", drefSize);
|
||||
#endif
|
||||
drefSize = 1024;
|
||||
}
|
||||
XPLMGetDatab(xdref, bValues, 0, drefSize);
|
||||
for (int i = 0; i < drefSize; ++i)
|
||||
{
|
||||
values[i] = (float)bValues[i];
|
||||
}
|
||||
#if LOG_VERBOSITY > 4
|
||||
Log::FormatLine("[DMAN] -- value count was %i", drefSize);
|
||||
#endif
|
||||
return drefSize;
|
||||
}
|
||||
|
||||
// No match
|
||||
#if LOG_VERBOSITY > 0
|
||||
Log::WriteLine("[DMAN] ERROR: Unrecognized data type.");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
double DataManager::GetDouble(DREF dref, char aircraft)
|
||||
{
|
||||
const XPLMDataRef& xdref = aircraft == 0 ? drefs[dref] : mdrefs[aircraft][dref];
|
||||
double value = XPLMGetDatad(xdref);
|
||||
#if LOG_VERBOSITY > 4
|
||||
Log::FormatLine("[DMAN] Get DREF %i (x:%X) result %f for a/c %i", dref, xdref, value, aircraft);
|
||||
#endif
|
||||
return value;
|
||||
}
|
||||
|
||||
float DataManager::GetFloat(DREF dref, char aircraft)
|
||||
{
|
||||
const XPLMDataRef& xdref = aircraft == 0 ? drefs[dref] : mdrefs[aircraft][dref];
|
||||
float value = XPLMGetDataf(xdref);
|
||||
#if LOG_VERBOSITY > 4
|
||||
Log::FormatLine("[DMAN] Get DREF %i (x:%X) result %f for a/c %i", dref, xdref, value, aircraft);
|
||||
#endif
|
||||
return value;
|
||||
}
|
||||
|
||||
int DataManager::GetInt(DREF dref, char aircraft)
|
||||
{
|
||||
const XPLMDataRef& xdref = aircraft == 0 ? drefs[dref] : mdrefs[aircraft][dref];
|
||||
int value = XPLMGetDatai(xdref);
|
||||
#if LOG_VERBOSITY > 4
|
||||
Log::FormatLine("[DMAN] Get DREF %i (x:%X) result %i for a/c %i", dref, xdref, value, aircraft);
|
||||
#endif
|
||||
return value;
|
||||
}
|
||||
|
||||
int DataManager::GetFloatArray(DREF dref, float values[], int size, char aircraft)
|
||||
{
|
||||
const XPLMDataRef& xdref = aircraft == 0 ? drefs[dref] : mdrefs[aircraft][dref];
|
||||
int resultSize = XPLMGetDatavf(xdref, values, 0, size);
|
||||
#if LOG_VERBOSITY > 4
|
||||
Log::FormatLine("[DMAN] Get DREF %i (x:%X) result size %i for a/c %i", dref, xdref, resultSize, aircraft);
|
||||
#endif
|
||||
return resultSize;
|
||||
}
|
||||
|
||||
int DataManager::GetIntArray(DREF dref, int values[], int size, char aircraft)
|
||||
{
|
||||
const XPLMDataRef& xdref = aircraft == 0 ? drefs[dref] : mdrefs[aircraft][dref];
|
||||
int resultSize = XPLMGetDatavi(xdref, values, 0, size);
|
||||
#if LOG_VERBOSITY > 4
|
||||
Log::FormatLine("[DMAN] Get DREF %i (x:%X) result size %i for a/c %i", dref, xdref, resultSize, aircraft);
|
||||
#endif
|
||||
return resultSize;
|
||||
}
|
||||
|
||||
void DataManager::Set(DREF dref, double value, char aircraft)
|
||||
{
|
||||
const XPLMDataRef& xdref = aircraft == 0 ? drefs[dref] : mdrefs[aircraft][dref];
|
||||
#if LOG_VERBOSITY > 4
|
||||
Log::FormatLine("[DMAN] Setting DREF %i (x:%X) to %f for a/c %i", dref, xdref, value, aircraft);
|
||||
#endif
|
||||
XPLMSetDatad(xdref, value);
|
||||
}
|
||||
|
||||
void DataManager::Set(DREF dref, float value, char aircraft)
|
||||
{
|
||||
const XPLMDataRef& xdref = aircraft == 0 ? drefs[dref] : mdrefs[aircraft][dref];
|
||||
#if LOG_VERBOSITY > 4
|
||||
Log::FormatLine("[DMAN] Set DREF %i (x:%X) to %f for a/c %i", dref, xdref, value, aircraft);
|
||||
#endif
|
||||
XPLMSetDataf(xdref, value);
|
||||
}
|
||||
|
||||
void DataManager::Set(DREF dref, int value, char aircraft)
|
||||
{
|
||||
const XPLMDataRef& xdref = aircraft == 0 ? drefs[dref] : mdrefs[aircraft][dref];
|
||||
#if LOG_VERBOSITY > 4
|
||||
Log::FormatLine("[DMAN] Set DREF %i (x:%X) to %i for a/c %i", dref, xdref, value, aircraft);
|
||||
#endif
|
||||
XPLMSetDatai(xdref, value);
|
||||
}
|
||||
|
||||
void DataManager::Set(DREF dref, float values[], int size, char aircraft)
|
||||
{
|
||||
const XPLMDataRef& xdref = aircraft == 0 ? drefs[dref] : mdrefs[aircraft][dref];
|
||||
#if LOG_VERBOSITY > 4
|
||||
Log::FormatLine("[DMAN] Set DREF %i (x:%X) (%i values) for a/c %i", dref, xdref, size, aircraft);
|
||||
#endif
|
||||
int drefSize = XPLMGetDatavf(xdref, NULL, 0, 0);
|
||||
drefSize = min(drefSize, size);
|
||||
XPLMSetDatavf(xdref, values, 0, drefSize);
|
||||
}
|
||||
|
||||
void DataManager::Set(DREF dref, int values[], int size, char aircraft)
|
||||
{
|
||||
const XPLMDataRef& xdref = aircraft == 0 ? drefs[dref] : mdrefs[aircraft][dref];
|
||||
#if LOG_VERBOSITY > 4
|
||||
Log::FormatLine("[DMAN] Setting DREF %i (x:%X) (%i values) for a/c %i", dref, xdref, size, aircraft);
|
||||
#endif
|
||||
int drefSize = XPLMGetDatavi(xdref, NULL, 0, 0);
|
||||
drefSize = min(drefSize, size);
|
||||
XPLMSetDatavi(xdref, values, 0, drefSize);
|
||||
}
|
||||
|
||||
void DataManager::Set(string dref, float values[], int size)
|
||||
{
|
||||
XPLMDataRef& xdref = sdrefs[dref];
|
||||
if (xdref == NULL)
|
||||
{
|
||||
xdref = XPLMFindDataRef(dref.c_str());
|
||||
}
|
||||
if (!xdref)
|
||||
{
|
||||
// DREF does not exist
|
||||
#if LOG_VERBOSITY > 0
|
||||
Log::FormatLine("[DMAN] ERROR: invalid DREF %s", dref.c_str());
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
if (isnan(values[0]))
|
||||
{
|
||||
#if LOG_VERBOSITY > 0
|
||||
Log::WriteLine("[DMAN] ERROR: Value must be a number (NaN received)");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
XPLMDataTypeID dataType = XPLMGetDataRefTypes(xdref);
|
||||
#if LOG_VERBOSITY > 4
|
||||
Log::FormatLine("[DMAN] Setting DREF %s (x:%X) Type: %i", dref.c_str(), xdref, dataType);
|
||||
#endif
|
||||
if ((dataType & 2) == 2) // Float
|
||||
{
|
||||
XPLMSetDataf(xdref, values[0]);
|
||||
#if LOG_VERBOSITY > 4
|
||||
Log::FormatLine("[DMAN] -- value was %f", values[0]);
|
||||
#endif
|
||||
}
|
||||
else if ((dataType & 8) == 8) // Float Array
|
||||
{
|
||||
int drefSize = XPLMGetDatavf(xdref, NULL, 0, 0);
|
||||
#if LOG_VERBOSITY > 1
|
||||
if (size > drefSize)
|
||||
{
|
||||
Log::WriteLine("[DMAN] WARN: Provided size is larger than actual dref size");
|
||||
Log::FormatLine(" Actual dref size: %i, Provided buffer size: %i", drefSize, size);
|
||||
}
|
||||
#endif
|
||||
drefSize = min(drefSize, size);
|
||||
XPLMSetDatavf(xdref, values, 0, drefSize);
|
||||
#if LOG_VERBOSITY > 4
|
||||
Log::FormatLine("[DMAN] -- value count was %i", drefSize);
|
||||
#endif
|
||||
}
|
||||
else if ((dataType & 4) == 4) // Double
|
||||
{
|
||||
XPLMSetDatad(xdref, values[0]);
|
||||
#if LOG_VERBOSITY > 4
|
||||
Log::FormatLine("[DMAN] -- value was %f", values[0]);
|
||||
#endif
|
||||
}
|
||||
else if ((dataType & 1) == 1) // Integer
|
||||
{
|
||||
XPLMSetDatai(xdref, (int)values[0]);
|
||||
#if LOG_VERBOSITY > 4
|
||||
Log::FormatLine("[DMAN] -- value was %i", (int)values[0]);
|
||||
#endif
|
||||
}
|
||||
else if ((dataType & 16) == 16) // Integer Array
|
||||
{
|
||||
int iValues[200];
|
||||
int drefSize = XPLMGetDatavi(xdref, NULL, 0, 0);
|
||||
#if LOG_VERBOSITY > 1
|
||||
if (size > drefSize)
|
||||
{
|
||||
Log::WriteLine("[DMAN] WARN: Provided size is larger than actual dref size");
|
||||
Log::FormatLine(" Actual dref size: %i, Provided buffer size: %i", drefSize, size);
|
||||
}
|
||||
#endif
|
||||
drefSize = min(drefSize, size);
|
||||
if (drefSize > 200)
|
||||
{
|
||||
#if LOG_VERBOSITY > 1
|
||||
Log::WriteLine("[DMAN] WARN: drefSize larger than temp buffer size.");
|
||||
Log::FormatLine(" Actual dref size: %i, Temp buffer size: 200", drefSize);
|
||||
#endif
|
||||
drefSize = 200;
|
||||
}
|
||||
for (int i = 0; i < drefSize; ++i)
|
||||
{
|
||||
iValues[i] = (int)values[i];
|
||||
}
|
||||
XPLMSetDatavi(xdref, iValues, 0, drefSize);
|
||||
#if LOG_VERBOSITY > 4
|
||||
Log::FormatLine("[DMAN] -- value count was %i", drefSize);
|
||||
#endif
|
||||
}
|
||||
else if ((dataType & 32) == 32) // Byte Array
|
||||
{
|
||||
char bValues[1024];
|
||||
int drefSize = XPLMGetDatab(xdref, NULL, 0, 0);
|
||||
#if LOG_VERBOSITY > 1
|
||||
if (size > drefSize)
|
||||
{
|
||||
Log::WriteLine("[DMAN] WARN: Provided size is larger than actual dref size");
|
||||
Log::FormatLine(" Actual dref size: %i, Provided buffer size: %i", drefSize, size);
|
||||
}
|
||||
#endif
|
||||
drefSize = min(drefSize, size);
|
||||
if (drefSize > 1024)
|
||||
{
|
||||
#if LOG_VERBOSITY > 1
|
||||
Log::WriteLine("[DMAN] WARN: drefSize larger than temp buffer size.");
|
||||
Log::FormatLine(" Actual dref size: %i, Temp buffer size: 1024", drefSize);
|
||||
#endif
|
||||
drefSize = 1024;
|
||||
}
|
||||
for (int i = 0; i < drefSize; ++i)
|
||||
{
|
||||
bValues[i] = (char)values[i];
|
||||
}
|
||||
XPLMSetDatab(xdref, bValues, 0, drefSize);
|
||||
#if LOG_VERBOSITY > 4
|
||||
Log::FormatLine("[DMAN] -- value count was %i", drefSize);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#if LOG_VERBOSITY > 0
|
||||
Log::WriteLine("[DMAN] ERROR: Unknown type.");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#if LOG_VERBOSITY > 1
|
||||
if (!XPLMCanWriteDataRef(xdref))
|
||||
{
|
||||
Log::WriteLine("[DMAN] WARN: dref is not writable. The write operation probably failed.");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void DataManager::SetGear(float gear, bool immediate, char aircraft)
|
||||
{
|
||||
#if LOG_VERBOSITY > 3
|
||||
Log::FormatLine("[DMAN] Setting gear (value:%f, immediate:%i) for aircraft %i", gear, immediate, aircraft);
|
||||
#endif
|
||||
if (isnan(gear) || gear < 0 || gear > 1)
|
||||
{
|
||||
#if LOG_VERBOSITY > 0
|
||||
Log::WriteLine("[GEAR] ERROR: Value must be 0 or 1");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
if ((gear < -8.5 && gear > -9.5) || (gear < -997.9 && gear > -999.1))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
float gearArray[10];
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
gearArray[i] = gear;
|
||||
}
|
||||
|
||||
if (aircraft == 0) // Own aircraft
|
||||
{
|
||||
Set(DREF_GearHandle, (int)gear);
|
||||
if (immediate)
|
||||
{
|
||||
Set(DREF_GearDeploy, gearArray, 10);
|
||||
}
|
||||
}
|
||||
else // Multiplayer aircraft
|
||||
{
|
||||
Set(DREF_GearDeploy, gearArray, 10, aircraft);
|
||||
}
|
||||
}
|
||||
|
||||
void DataManager::SetPosition(float pos[3], char aircraft)
|
||||
{
|
||||
#if LOG_VERBOSITY > 3
|
||||
Log::FormatLine("[DMAN] Setting position (%f, %f, %f) for aircraft %i", pos[0], pos[1], pos[2], aircraft);
|
||||
#endif
|
||||
if (isnan(pos[0] + pos[1] + pos[2]))
|
||||
{
|
||||
#if LOG_VERBOSITY > 0
|
||||
Log::WriteLine("[DMAN] ERROR: Position must be a number (NaN received)");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
if (pos[0] < -997.9 && pos[0] > -999.1)
|
||||
{
|
||||
pos[0] = (float)GetDouble(DREF_Latitude, aircraft);
|
||||
}
|
||||
if (pos[1] < -997.9 && pos[1] > -999.1)
|
||||
{
|
||||
pos[1] = (float)GetDouble(DREF_Longitude, aircraft);
|
||||
}
|
||||
if (pos[2] < -997.9 && pos[2] > -999.1)
|
||||
{
|
||||
pos[2] = (float)GetDouble(DREF_Elevation, aircraft);
|
||||
}
|
||||
|
||||
double local[3];
|
||||
XPLMWorldToLocal(pos[0], pos[1], pos[2], &local[0], &local[1], &local[2]);
|
||||
// If the sim is paused, setting global position won't update the
|
||||
// local position, so set them just in case.
|
||||
Set(DREF_LocalX, local[0], aircraft);
|
||||
Set(DREF_LocalY, local[1], aircraft);
|
||||
Set(DREF_LocalZ, local[2], aircraft);
|
||||
// If the sim is unpaused, this will override the above settings.
|
||||
// TODO: Are these setable when paused? Are these necessary?
|
||||
Set(DREF_Latitude, (double)pos[0], aircraft);
|
||||
Set(DREF_Longitude, (double)pos[1], aircraft);
|
||||
Set(DREF_Elevation, (double)pos[2], aircraft);
|
||||
}
|
||||
|
||||
void DataManager::SetOrientation(float orient[3], char aircraft)
|
||||
{
|
||||
#if LOG_VERBOSITY > 3
|
||||
Log::FormatLine("[DMAN] Setting orientation (%f, %f, %f) for aircraft %i",
|
||||
orient[0], orient[1], orient[2], aircraft);
|
||||
#endif
|
||||
if (isnan(orient[0] + orient[1] + orient[2]))
|
||||
{
|
||||
#if LOG_VERBOSITY > 0
|
||||
Log::WriteLine("[DMAN] ERROR: Orientation must be a number (NaN received)");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
if (orient[0] < -997.9 && orient[0] > -999.1)
|
||||
{
|
||||
orient[0] = GetFloat(DREF_Pitch, aircraft);
|
||||
}
|
||||
if (orient[1] < -997.9 && orient[1] > -999.1)
|
||||
{
|
||||
orient[1] = GetFloat(DREF_Roll, aircraft);
|
||||
}
|
||||
if (orient[2] < -997.9 && orient[2] > -999.1)
|
||||
{
|
||||
orient[2] = GetFloat(DREF_HeadingTrue, aircraft);
|
||||
}
|
||||
|
||||
|
||||
// If the sim is paused, setting the quaternion won't update these values,
|
||||
// so we set them here just in case. This also covers multiplayer aircraft,
|
||||
// which we can't set the quaternion on.
|
||||
Set(DREF_Pitch, orient[0], aircraft);
|
||||
Set(DREF_Roll, orient[1], aircraft);
|
||||
Set(DREF_HeadingTrue, orient[2], aircraft);
|
||||
if (aircraft == 0) // Player aircraft
|
||||
{
|
||||
// Convert to Quaternions
|
||||
// from: http://www.xsquawkbox.net/xpsdk/mediawiki/MovingThePlane
|
||||
// http://ntrs.nasa.gov/archive/nasa/casi.ntrs.nasa.gov/19770024290.pdf
|
||||
float q[4];
|
||||
float halfRad = 0.00872664625997F;
|
||||
orient[2] = halfRad * orient[2];
|
||||
orient[0] = halfRad * orient[0];
|
||||
orient[1] = halfRad * orient[1];
|
||||
q[0] = cos(orient[2]) * cos(orient[0]) * cos(orient[1]) + sin(orient[2]) * sin(orient[0]) * sin(orient[1]);
|
||||
q[1] = cos(orient[2]) * cos(orient[0]) * sin(orient[1]) - sin(orient[2]) * sin(orient[0]) * cos(orient[1]);
|
||||
q[2] = cos(orient[2]) * sin(orient[0]) * cos(orient[1]) + sin(orient[2]) * cos(orient[0]) * sin(orient[1]);
|
||||
q[3] = sin(orient[2]) * cos(orient[0]) * cos(orient[1]) - cos(orient[2]) * sin(orient[0]) * sin(orient[1]);
|
||||
|
||||
// If the sim is un-paused, this will overwrite the pitch/roll/yaw
|
||||
// values set above.
|
||||
Set(DREF_Quaternion, q, 4);
|
||||
}
|
||||
}
|
||||
|
||||
void DataManager::SetFlaps(float value)
|
||||
{
|
||||
if (isnan(value))
|
||||
{
|
||||
#if LOG_VERBOSITY > 0
|
||||
Log::WriteLine("[DMAN] ERROR: Flap value must be a number (NaN received)");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
if (value < -997.9 && value > -999.1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
value = (float)fmaxl(value, 0);
|
||||
value = (float)fminl(value, 1);
|
||||
|
||||
Set(DREF_FlapSetting, value);
|
||||
Set(DREF_FlapActual, value);
|
||||
}
|
||||
}
|
||||
411
xpcPlugin/DataManager.h
Normal file
411
xpcPlugin/DataManager.h
Normal file
@@ -0,0 +1,411 @@
|
||||
//Copyright (c) 2013-2015 United States Government as represented by the Administrator of the
|
||||
//National Aeronautics and Space Administration. All Rights Reserved.
|
||||
#ifndef XPC_DATAMANAGER_H
|
||||
#define XPC_DATAMANAGER_H
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace XPC
|
||||
{
|
||||
/// Represents named datarefs used by X-Plane Connect
|
||||
enum DREF
|
||||
{
|
||||
DREF_None = 0,
|
||||
|
||||
DREF_Pause,
|
||||
DREF_PauseAI,
|
||||
|
||||
// Times
|
||||
DREF_TotalRuntime = 100,
|
||||
DREF_TotalFlighttime,
|
||||
DREF_TimerElapsedtime,
|
||||
|
||||
// Velocities
|
||||
DREF_IndicatedAirspeed = 300,
|
||||
DREF_TrueAirspeed,
|
||||
DREF_GroundSpeed,
|
||||
|
||||
// Mach, VVI, G-loads
|
||||
DREF_MachNumber = 400,
|
||||
DREF_GForceNormal,
|
||||
DREF_GForceAxial,
|
||||
DREF_GForceSide,
|
||||
|
||||
// Atmosphere: Weather
|
||||
DREF_BarometerSealevelInHg = 500,
|
||||
DREF_TemperaturSealevelC,
|
||||
DREF_WindSpeedKts,
|
||||
|
||||
// Joystick
|
||||
DREF_YokePitch = 800,
|
||||
DREF_YokeRoll,
|
||||
DREF_YokeHeading,
|
||||
|
||||
// Control Surfaces
|
||||
DREF_Elevator = 1100,
|
||||
DREF_Aileron,
|
||||
DREF_Rudder,
|
||||
|
||||
// Flaps
|
||||
DREF_FlapSetting = 1300,
|
||||
DREF_FlapActual,
|
||||
|
||||
// Gear & Brakes
|
||||
DREF_GearDeploy = 1400,
|
||||
DREF_GearHandle,
|
||||
DREF_BrakeParking,
|
||||
DREF_BrakeLeft,
|
||||
DREF_BrakeRight,
|
||||
|
||||
// MNR (Angular Moments)
|
||||
DREF_M = 1500,
|
||||
DREF_L,
|
||||
DREF_N,
|
||||
|
||||
//PQR (Angular Velocities)
|
||||
DREF_QRad = 1600,
|
||||
DREF_PRad,
|
||||
DREF_RRad,
|
||||
DREF_Q,
|
||||
DREF_P,
|
||||
DREF_R,
|
||||
|
||||
// Orientation: pitch, roll, yaw, heading
|
||||
DREF_Pitch = 1700,
|
||||
DREF_Roll,
|
||||
DREF_HeadingTrue,
|
||||
DREF_HeadingMag,
|
||||
DREF_Quaternion,
|
||||
|
||||
// Orientation: alpha beta hpath vpath slip
|
||||
DREF_AngleOfAttack = 1800,
|
||||
DREF_Sideslip,
|
||||
DREF_HPath,
|
||||
DREF_VPath,
|
||||
|
||||
DREF_MagneticVariation = 1901,
|
||||
|
||||
// Global Position
|
||||
DREF_Latitude = 2000,
|
||||
DREF_Longitude,
|
||||
DREF_Elevation,
|
||||
DREF_AGL,
|
||||
|
||||
// Local Postion & Velocity
|
||||
DREF_LocalX = 2100,
|
||||
DREF_LocalY,
|
||||
DREF_LocalZ,
|
||||
DREF_LocalVX,
|
||||
DREF_LocalVY,
|
||||
DREF_LocalVZ,
|
||||
|
||||
DREF_ThrottleSet = 2200,
|
||||
DREF_ThrottleActual = 2300,
|
||||
|
||||
// Multiplayer Aircraft
|
||||
DREF_FlapActual2,
|
||||
DREF_Spoiler,
|
||||
DREF_BrakeSpeed,
|
||||
DREF_Sweep,
|
||||
DREF_Slats,
|
||||
|
||||
// Mulitplayer positon
|
||||
DREF_MP1Lat,
|
||||
DREF_MP2Lat,
|
||||
DREF_MP3Lat,
|
||||
DREF_MP4Lat,
|
||||
DREF_MP5Lat,
|
||||
DREF_MP6Lat,
|
||||
DREF_MP7Lat,
|
||||
|
||||
DREF_MP1Lon,
|
||||
DREF_MP2Lon,
|
||||
DREF_MP3Lon,
|
||||
DREF_MP4Lon,
|
||||
DREF_MP5Lon,
|
||||
DREF_MP6Lon,
|
||||
DREF_MP7Lon,
|
||||
|
||||
DREF_MP1Alt,
|
||||
DREF_MP2Alt,
|
||||
DREF_MP3Alt,
|
||||
DREF_MP4Alt,
|
||||
DREF_MP5Alt,
|
||||
DREF_MP6Alt,
|
||||
DREF_MP7Alt
|
||||
};
|
||||
|
||||
/// Marshals data between the plugin and X-Plane.
|
||||
///
|
||||
/// \author Jason Watkins
|
||||
/// \version 1.0.1
|
||||
/// \since 1.0.0
|
||||
/// \date Intial Version: 2015-04-13
|
||||
/// \date Last Updated: 2015-04-29
|
||||
class DataManager
|
||||
{
|
||||
public:
|
||||
/// Initializes the internal data used by DataManager to translate DREF values
|
||||
/// into X-Plane internal data.
|
||||
static void Initialize();
|
||||
|
||||
/// Gets a dataref based on its name.
|
||||
///
|
||||
/// \param dref The name of the dref to get.
|
||||
/// \param values An array in which the result of the operation will be stored.
|
||||
/// \param size The size of the values array.
|
||||
/// \returns The number of elements placed in the values array. For scalar
|
||||
/// drefs, this will be one. For array drefs, this will be the
|
||||
/// lesser of the size and the number of elements in the dref.
|
||||
///
|
||||
/// \remarks The first time this method is called for a given dataref, it must
|
||||
/// perform a relatively expensive lookup operation to translate the
|
||||
/// given string into an X-Plane internal pointer. This value is cached,
|
||||
/// so subsequent calls will incure minimal extra overhead compared to
|
||||
/// the other methods in this class.
|
||||
///
|
||||
/// \remarks For simplicity, this method is provided with only one output type.
|
||||
/// For most integer and double drefs, this is unlikely to cause issues.
|
||||
/// However, for drefs where the entire integer range may be used, or
|
||||
/// doubles where high precision is required, using this method may result
|
||||
/// in a loss of precision. In that case, consider using one of the
|
||||
/// strongly typed methods instead.
|
||||
static int Get(std::string dref, float values[], int size);
|
||||
|
||||
/// Gets the value of a double dataref.
|
||||
///
|
||||
/// \param dref The dataref to get.
|
||||
/// \param aircraft The aircraft number for which to get the data.
|
||||
/// \returns The value of the dref specified if that dref has the type
|
||||
/// double; otherwise an undefined value.
|
||||
///
|
||||
/// \remarks This method does not verify the type of the dref requested. It is
|
||||
/// the responsibility of the caller to check the X-Plane documentation
|
||||
/// and call the appropriate overload of this method. If the wrong
|
||||
/// overload is called, the value returned is determined by the X-Plane
|
||||
/// plugin manager, and is considered undefined by the plugin.
|
||||
///
|
||||
/// \remarks Although any combination of dref and aircraft may be passed to this
|
||||
/// method, most drefs are not valid for multiplayer aircraft. All drefs
|
||||
/// that are not prefixed with 'MP' are valid for the player aircraft.
|
||||
/// 'MP' drefs should be called with aircraft 0.
|
||||
static double GetDouble(DREF dref, char aircraft = 0);
|
||||
|
||||
/// Gets the value of a float dataref.
|
||||
///
|
||||
/// \param dref The dataref to get.
|
||||
/// \param aircraft The aircraft number for which to get the data.
|
||||
/// \returns The value of the dref specified if that dref has the type
|
||||
/// float; otherwise an undefined value.
|
||||
///
|
||||
/// \remarks This method does not verify the type of the dref requested. It is
|
||||
/// the responsibility of the caller to check the X-Plane documentation
|
||||
/// and call the appropriate overload of this method. If the wrong
|
||||
/// overload is called, the value returned is determined by the X-Plane
|
||||
/// plugin manager, and is considered undefined by the plugin.
|
||||
///
|
||||
/// \remarks Although any combination of dref and aircraft may be passed to this
|
||||
/// method, most drefs are not valid for multiplayer aircraft. All drefs
|
||||
/// that are not prefixed with 'MP' are valid for the player aircraft.
|
||||
/// 'MP' drefs should be called with aircraft 0.
|
||||
static float GetFloat(DREF dref, char aircraft = 0);
|
||||
|
||||
/// Gets the value of an integer dataref.
|
||||
///
|
||||
/// \param dref The dataref to get.
|
||||
/// \param aircraft The aircraft number for which to get the data.
|
||||
/// \returns The value of the dref specified if that dref has the type
|
||||
/// int; otherwise an undefined value.
|
||||
///
|
||||
/// \remarks This method does not verify the type of the dref requested. It is
|
||||
/// the responsibility of the caller to check the X-Plane documentation
|
||||
/// and call the appropriate overload of this method. If the wrong
|
||||
/// overload is called, the value returned is determined by the X-Plane
|
||||
/// plugin manager, and is considered undefined by the plugin.
|
||||
///
|
||||
/// \remarks Although any combination of dref and aircraft may be passed to this
|
||||
/// method, most drefs are not valid for multiplayer aircraft. All drefs
|
||||
/// that are not prefixed with 'MP' are valid for the player aircraft.
|
||||
/// 'MP' drefs should be called with aircraft 0.
|
||||
static int GetInt(DREF dref, char aircraft = 0);
|
||||
|
||||
/// Gets the value of a float array dataref.
|
||||
///
|
||||
/// \param dref The dataref to get.
|
||||
/// \param values An array in which the result of the operation will be stored.
|
||||
/// \param size The size of the values array.
|
||||
/// \param aircraft The aircraft number for which to get the data.
|
||||
/// \returns The number of elements placed in the values array. This will
|
||||
/// be the lesser of the size and the number of elements in the dref.
|
||||
///
|
||||
/// \remarks This method does not verify the type of the dref requested. It is
|
||||
/// the responsibility of the caller to check the X-Plane documentation
|
||||
/// and call the appropriate overload of this method. If the wrong
|
||||
/// overload is called, the value returned is determined by the X-Plane
|
||||
/// plugin manager, and is considered undefined by the plugin.
|
||||
///
|
||||
/// \remarks Although any combination of dref and aircraft may be passed to this
|
||||
/// method, most drefs are not valid for multiplayer aircraft. All drefs
|
||||
/// that are not prefixed with 'MP' are valid for the player aircraft.
|
||||
/// 'MP' drefs should be called with aircraft 0.
|
||||
static int GetFloatArray(DREF dref, float values[], int size, char aircraft = 0);
|
||||
|
||||
|
||||
/// Gets the value of an int array dataref.
|
||||
///
|
||||
/// \param dref The dataref to get.
|
||||
/// \param values An array in which the result of the operation will be stored.
|
||||
/// \param size The size of the values array.
|
||||
/// \param aircraft The aircraft number for which to get the data.
|
||||
/// \returns The number of elements placed in the values array. This will
|
||||
/// be the lesser of the size and the number of elements in the dref.
|
||||
///
|
||||
/// \remarks This method does not verify the type of the dref requested. It is
|
||||
/// the responsibility of the caller to check the X-Plane documentation
|
||||
/// and call the appropriate overload of this method. If the wrong
|
||||
/// overload is called, the value returned is determined by the X-Plane
|
||||
/// plugin manager, and is considered undefined by the plugin.
|
||||
///
|
||||
/// \remarks Although any combination of dref and aircraft may be passed to this
|
||||
/// method, most drefs are not valid for multiplayer aircraft. All drefs
|
||||
/// that are not prefixed with 'MP' are valid for the player aircraft.
|
||||
/// 'MP' drefs should be called with aircraft 0.
|
||||
static int GetIntArray(DREF dref, int values[], int size, char aircraft = 0);
|
||||
|
||||
/// Sets the value of a dataref
|
||||
///
|
||||
/// \param dref The name of the dref to set.
|
||||
/// \param values The value to set the dref to.
|
||||
/// \param size The number of items stored in values.
|
||||
///
|
||||
/// \remarks The first time this method is called for a given dataref, it must
|
||||
/// perform a relatively expensive lookup operation to translate the
|
||||
/// given string into an X-Plane internal pointer. This value is cached,
|
||||
/// so subsequent calls will incure minimal extra overhead compared to
|
||||
/// the other methods in this class.
|
||||
///
|
||||
/// \remarks For simplicity, this method is provided with only one input type.
|
||||
/// For most integer and double drefs, this is unlikely to cause issues.
|
||||
/// However, for drefs where the entire integer range may be used, or
|
||||
/// doubles where high precision is required, using this method may result
|
||||
/// in a loss of precision. In that case, consider using one of the
|
||||
/// strongly typed methods instead.
|
||||
static void Set(std::string dref, float values[], int size);
|
||||
|
||||
/// Sets the value of a double dataref.
|
||||
///
|
||||
/// \param dref The dataref to set.
|
||||
/// \param value The value to set the dref to.
|
||||
/// \param aircraft The aircraft number for which to get the data.
|
||||
///
|
||||
/// \remarks This method does not verify the type of the dref being set. It is
|
||||
/// the responsibility of the caller to check the X-Plane documentation
|
||||
/// and call the appropriate overload of this method. If the wrong
|
||||
/// overload is called, the operation will fail silently.
|
||||
///
|
||||
/// \remarks Although any combination of dref and aircraft may be passed to this
|
||||
/// method, most drefs are not valid for multiplayer aircraft. All drefs
|
||||
/// that are not prefixed with 'MP' are valid for the player aircraft.
|
||||
/// 'MP' drefs should be called with aircraft 0.
|
||||
static void Set(DREF dref, double value, char aircraft = 0);
|
||||
|
||||
/// Sets the value of a float dataref.
|
||||
///
|
||||
/// \param dref The dataref to set.
|
||||
/// \param value The value to set the dref to.
|
||||
/// \param aircraft The aircraft number for which to get the data.
|
||||
///
|
||||
/// \remarks This method does not verify the type of the dref being set. It is
|
||||
/// the responsibility of the caller to check the X-Plane documentation
|
||||
/// and call the appropriate overload of this method. If the wrong
|
||||
/// overload is called, the operation will fail silently.
|
||||
///
|
||||
/// \remarks Although any combination of dref and aircraft may be passed to this
|
||||
/// method, most drefs are not valid for multiplayer aircraft. All drefs
|
||||
/// that are not prefixed with 'MP' are valid for the player aircraft.
|
||||
/// 'MP' drefs should be called with aircraft 0.
|
||||
static void Set(DREF dref, float value, char aircraft = 0);
|
||||
|
||||
/// Sets the value of an integer dataref.
|
||||
///
|
||||
/// \param dref The dataref to set.
|
||||
/// \param value The value to set the dref to.
|
||||
/// \param aircraft The aircraft number for which to get the data.
|
||||
///
|
||||
/// \remarks This method does not verify the type of the dref being set. It is
|
||||
/// the responsibility of the caller to check the X-Plane documentation
|
||||
/// and call the appropriate overload of this method. If the wrong
|
||||
/// overload is called, the operation will fail silently.
|
||||
///
|
||||
/// \remarks Although any combination of dref and aircraft may be passed to this
|
||||
/// method, most drefs are not valid for multiplayer aircraft. All drefs
|
||||
/// that are not prefixed with 'MP' are valid for the player aircraft.
|
||||
/// 'MP' drefs should be called with aircraft 0.
|
||||
static void Set(DREF dref, int value, char aircraft = 0);
|
||||
|
||||
/// Sets the value of a float array dataref.
|
||||
///
|
||||
/// \param dref The dataref to set.
|
||||
/// \param values The value to set the dref to.
|
||||
/// \param size The number of items stored in values.
|
||||
/// \param aircraft The aircraft number for which to get the data.
|
||||
///
|
||||
/// \remarks This method does not verify the type of the dref being set. It is
|
||||
/// the responsibility of the caller to check the X-Plane documentation
|
||||
/// and call the appropriate overload of this method. If the wrong
|
||||
/// overload is called, the operation will fail silently.
|
||||
///
|
||||
/// \remarks Although any combination of dref and aircraft may be passed to this
|
||||
/// method, most drefs are not valid for multiplayer aircraft. All drefs
|
||||
/// that are not prefixed with 'MP' are valid for the player aircraft.
|
||||
/// 'MP' drefs should be called with aircraft 0.
|
||||
static void Set(DREF dref, float values[], int size, char aircraft = 0);
|
||||
|
||||
/// Sets the value of an integer array dataref.
|
||||
///
|
||||
/// \param dref The dataref to set.
|
||||
/// \param values The value to set the dref to.
|
||||
/// \param size The number of items stored in values.
|
||||
/// \param aircraft The aircraft number for which to get the data.
|
||||
///
|
||||
/// \remarks This method does not verify the type of the dref being set. It is
|
||||
/// the responsibility of the caller to check the X-Plane documentation
|
||||
/// and call the appropriate overload of this method. If the wrong
|
||||
/// overload is called, the operation will fail silently.
|
||||
///
|
||||
/// \remarks Although any combination of dref and aircraft may be passed to this
|
||||
/// method, most drefs are not valid for multiplayer aircraft. All drefs
|
||||
/// that are not prefixed with 'MP' are valid for the player aircraft.
|
||||
/// 'MP' drefs should be called with aircraft 0.
|
||||
static void Set(DREF dref, int values[], int size, char aircraft = 0);
|
||||
|
||||
/// Sets the landing gear for the specified airplane.
|
||||
///
|
||||
/// \param gear The value to set the gear to. 0 for gear down, 1 for gear up.
|
||||
/// \param immediate Whether the gear should be forced to the specified position.
|
||||
/// If immediate is false, only the gear handle dref will be set.
|
||||
/// \param aircraft The aircraft to set the landing gear status on.
|
||||
static void SetGear(float gear, bool immediate, char aircraft = 0);
|
||||
|
||||
/// Sets the position of the specified aircraft on the Earth.
|
||||
///
|
||||
/// \param pos An array containing latitude, longitude and altitude in
|
||||
/// fractional degrees and meters above sea level.
|
||||
/// \param aircraft The aircraft to set the position of.
|
||||
static void SetPosition(float pos[3], char aircraft = 0);
|
||||
|
||||
/// Sets the orientation of the specified aircraft.
|
||||
///
|
||||
/// \param orient An array containing the pitch, roll, and yaw orientations
|
||||
/// to set, all in fractional degrees.
|
||||
/// \param aircraft The aircraft to set the orientation of.
|
||||
static void SetOrientation(float orient[3], char aircraft = 0);
|
||||
|
||||
/// Sets flaps on the the player aircraft.
|
||||
///
|
||||
/// \param value The flaps settings. Should be between 0.0 (no flaps) and 1.0 (full flaps).
|
||||
static void SetFlaps(float value);
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
8
xpcPlugin/DataMaps.cpp
Normal file
8
xpcPlugin/DataMaps.cpp
Normal file
@@ -0,0 +1,8 @@
|
||||
//Copyright (c) 2013-2015 United States Government as represented by the Administrator of the
|
||||
//National Aeronautics and Space Administration. All Rights Reserved.
|
||||
#include "DataManager.h"
|
||||
|
||||
namespace XPC
|
||||
{
|
||||
DREF XPData[134][8] = { DREF_None };
|
||||
}
|
||||
13
xpcPlugin/DataMaps.h
Normal file
13
xpcPlugin/DataMaps.h
Normal file
@@ -0,0 +1,13 @@
|
||||
//Copyright (c) 2013-2015 United States Government as represented by the Administrator of the
|
||||
//National Aeronautics and Space Administration. All Rights Reserved.
|
||||
#ifndef XPC_DATAMAPS_H
|
||||
#define XPC_DATAMAPS_H
|
||||
#include "DataManager.h"
|
||||
|
||||
namespace XPC
|
||||
{
|
||||
/// Maps X-Plane dataref lines to XPC DREF values.
|
||||
extern DREF XPData[134][8];
|
||||
}
|
||||
|
||||
#endif
|
||||
301
xpcPlugin/Drawing.cpp
Normal file
301
xpcPlugin/Drawing.cpp
Normal file
@@ -0,0 +1,301 @@
|
||||
//Copyright (c) 2013-2015 United States Government as represented by the Administrator of the
|
||||
//National Aeronautics and Space Administration. All Rights Reserved.
|
||||
//
|
||||
//X-Plane API
|
||||
//Copyright(c) 2008, Sandy Barbour and Ben Supnik All rights reserved.
|
||||
//Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
|
||||
//associated documentation files(the "Software"), to deal in the Software without restriction,
|
||||
//including without limitation the rights to use, copy, modify, merge, publish, distribute,
|
||||
//sublicense, and / or sell copies of the Software, and to permit persons to whom the Software is
|
||||
//furnished to do so, subject to the following conditions :
|
||||
// * Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
// * Neither the names of the authors nor that of X - Plane or Laminar Research
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission from the authors or
|
||||
// Laminar Research, respectively.
|
||||
#include "Drawing.h"
|
||||
|
||||
#include "XPLMDisplay.h"
|
||||
#include "XPLMGraphics.h"
|
||||
#include "XPLMDataAccess.h"
|
||||
|
||||
#include <cmath>
|
||||
#include <string>
|
||||
#include <cstring>
|
||||
//OpenGL includes
|
||||
#if IBM
|
||||
#include <windows.h>
|
||||
#endif
|
||||
#ifdef __APPLE__
|
||||
# include <OpenGL/gl.h>
|
||||
#else
|
||||
# include <GL/gl.h>
|
||||
#endif/*__APPLE__*/
|
||||
|
||||
namespace XPC
|
||||
{
|
||||
//Internal Structures
|
||||
typedef struct
|
||||
{
|
||||
double x;
|
||||
double y;
|
||||
double z;
|
||||
} LocalPoint;
|
||||
|
||||
//Internal Memory
|
||||
static const size_t MSG_MAX = 1024;
|
||||
static const size_t MSG_LINE_MAX = MSG_MAX / 16;
|
||||
static bool msgEnabled = false;
|
||||
static int msgX = -1;
|
||||
static int msgY = -1;
|
||||
static char msgVal[MSG_MAX] = { 0 };
|
||||
static size_t newLineCount = 0;
|
||||
static size_t newLines[MSG_LINE_MAX] = { 0 };
|
||||
static float rgb[3] = { 0.25F, 1.0F, 0.25F };
|
||||
|
||||
static const size_t WAYPOINT_MAX = 128;
|
||||
static bool routeEnabled = false;
|
||||
static size_t numWaypoints = 0;
|
||||
static Waypoint waypoints[WAYPOINT_MAX];
|
||||
static LocalPoint localPoints[WAYPOINT_MAX];
|
||||
|
||||
XPLMDataRef planeXref;
|
||||
XPLMDataRef planeYref;
|
||||
XPLMDataRef planeZref;
|
||||
|
||||
//Internal Functions
|
||||
static int cmp(const void * a, const void * b)
|
||||
{
|
||||
std::size_t sa = *(size_t*)a;
|
||||
std::size_t sb = *(size_t*)b;
|
||||
if (sa > sb)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
if (sb > sa)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void gl_drawCube(float x, float y, float z, float d)
|
||||
{
|
||||
//tan(0.25) degrees. Should scale all markers to appear about the same size
|
||||
const float TAN = 0.00436335F;
|
||||
float h = d * TAN;
|
||||
|
||||
glBegin(GL_QUAD_STRIP);
|
||||
//Top
|
||||
glVertex3f(x - h, y + h, z - h);
|
||||
glVertex3f(x + h, y + h, z - h);
|
||||
glVertex3f(x - h, y + h, z + h);
|
||||
glVertex3f(x + h, y + h, z + h);
|
||||
//Front
|
||||
glVertex3f(x - h, y - h, z + h);
|
||||
glVertex3f(x + h, y - h, z + h);
|
||||
//Bottom
|
||||
glVertex3f(x - h, y - h, z - h);
|
||||
glVertex3f(x + h, y - h, z - h);
|
||||
//Back
|
||||
glVertex3f(x - h, y + h, z - h);
|
||||
glVertex3f(x + h, y + h, z - h);
|
||||
|
||||
glEnd();
|
||||
glBegin(GL_QUADS);
|
||||
//Left
|
||||
glVertex3f(x - h, y + h, z - h);
|
||||
glVertex3f(x - h, y + h, z + h);
|
||||
glVertex3f(x - h, y - h, z + h);
|
||||
glVertex3f(x - h, y - h, z - h);
|
||||
//Right
|
||||
glVertex3f(x + h, y + h, z + h);
|
||||
glVertex3f(x + h, y + h, z - h);
|
||||
glVertex3f(x + h, y - h, z - h);
|
||||
glVertex3f(x + h, y - h, z + h);
|
||||
|
||||
glEnd();
|
||||
}
|
||||
|
||||
static int MessageDrawCallback(XPLMDrawingPhase inPhase, int inIsBefore, void * inRefcon)
|
||||
{
|
||||
XPLMDrawString(rgb, msgX, msgY, msgVal, NULL, xplmFont_Basic);
|
||||
int y = msgY - 16;
|
||||
for (size_t i = 0; i < newLineCount; ++i)
|
||||
{
|
||||
XPLMDrawString(rgb, msgX, y, msgVal + newLines[i], NULL, xplmFont_Basic);
|
||||
y -= 16;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int RouteDrawCallback(XPLMDrawingPhase inPhase, int inIsBefore, void * inRefcon)
|
||||
{
|
||||
float px = XPLMGetDataf(planeXref);
|
||||
float py = XPLMGetDataf(planeYref);
|
||||
float pz = XPLMGetDataf(planeZref);
|
||||
|
||||
//Convert to local
|
||||
for (size_t i = 0; i < numWaypoints; ++i)
|
||||
{
|
||||
Waypoint* g = &waypoints[i];
|
||||
LocalPoint* l = &localPoints[i];
|
||||
XPLMWorldToLocal(g->latitude, g->longitude, g->altitude,
|
||||
&l->x, &l->y, &l->z);
|
||||
}
|
||||
|
||||
|
||||
//Draw posts
|
||||
glColor3f(1.0F, 1.0F, 1.0F);
|
||||
glBegin(GL_LINES);
|
||||
for (size_t i = 0; i < numWaypoints; ++i)
|
||||
{
|
||||
LocalPoint* l = &localPoints[i];
|
||||
glVertex3f((float)l->x, (float)l->y, (float)l->z);
|
||||
glVertex3f((float)l->x, -1000.0F, (float)l->z);
|
||||
}
|
||||
glEnd();
|
||||
|
||||
//Draw route
|
||||
glColor3f(1.0F, 0.0F, 0.0F);
|
||||
glBegin(GL_LINE_STRIP);
|
||||
for (size_t i = 0; i < numWaypoints; ++i)
|
||||
{
|
||||
LocalPoint* l = &localPoints[i];
|
||||
glVertex3f((float)l->x, (float)l->y, (float)l->z);
|
||||
}
|
||||
glEnd();
|
||||
|
||||
//Draw markers
|
||||
glColor3f(1.0F, 1.0F, 1.0F);
|
||||
for (size_t i = 0; i < numWaypoints; ++i)
|
||||
{
|
||||
LocalPoint* l = &localPoints[i];
|
||||
float xoff = (float)l->x - px;
|
||||
float yoff = (float)l->y - py;
|
||||
float zoff = (float)l->z - pz;
|
||||
float d = sqrtf(xoff*xoff + yoff*yoff + zoff*zoff);
|
||||
gl_drawCube((float)l->x, (float)l->y, (float)l->z, d);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
//Public Functions
|
||||
void Drawing::ClearMessage()
|
||||
{
|
||||
XPLMUnregisterDrawCallback(MessageDrawCallback, xplm_Phase_Window, 0, NULL);
|
||||
msgEnabled = false;
|
||||
}
|
||||
|
||||
void Drawing::SetMessage(int x, int y, char* msg)
|
||||
{
|
||||
//Determine size of message and clear instead if the message string
|
||||
//is empty.
|
||||
size_t len = strnlen(msg, MSG_MAX - 1);
|
||||
if (len == 0)
|
||||
{
|
||||
ClearMessage();
|
||||
return;
|
||||
}
|
||||
|
||||
//Set the message, location, and mark new lines.
|
||||
strncpy(msgVal, msg, len + 1);
|
||||
newLineCount = 0;
|
||||
for (size_t i = 0; i < len && newLineCount < MSG_LINE_MAX; ++i)
|
||||
{
|
||||
if (msgVal[i] == '\n' || msgVal[i] == '\r')
|
||||
{
|
||||
msgVal[i] = 0;
|
||||
newLines[newLineCount++] = i + 1;
|
||||
}
|
||||
}
|
||||
msgX = x < 0 ? 10 : x;
|
||||
msgY = y < 0 ? 600 : y;
|
||||
|
||||
//Enable drawing if necessary
|
||||
if (!msgEnabled)
|
||||
{
|
||||
XPLMRegisterDrawCallback(MessageDrawCallback, xplm_Phase_Window, 0, NULL);
|
||||
msgEnabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
void Drawing::ClearWaypoints()
|
||||
{
|
||||
numWaypoints = 0;
|
||||
if (routeEnabled)
|
||||
{
|
||||
XPLMUnregisterDrawCallback(RouteDrawCallback, xplm_Phase_Objects, 0, NULL);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void Drawing::AddWaypoints(Waypoint points[], size_t numPoints)
|
||||
{
|
||||
if (numWaypoints + numPoints > WAYPOINT_MAX)
|
||||
{
|
||||
numPoints = WAYPOINT_MAX - numWaypoints;
|
||||
}
|
||||
size_t finalNumWaypoints = numPoints + numWaypoints;
|
||||
for (size_t i = 0; i < numPoints; ++i)
|
||||
{
|
||||
waypoints[numWaypoints + i] = points[i];
|
||||
}
|
||||
numWaypoints = finalNumWaypoints;
|
||||
|
||||
if (!routeEnabled)
|
||||
{
|
||||
XPLMRegisterDrawCallback(RouteDrawCallback, xplm_Phase_Objects, 0, NULL);
|
||||
}
|
||||
if (!planeXref)
|
||||
{
|
||||
planeXref = XPLMFindDataRef("sim/flightmodel/position/local_x");
|
||||
planeYref = XPLMFindDataRef("sim/flightmodel/position/local_y");
|
||||
planeZref = XPLMFindDataRef("sim/flightmodel/position/local_z");
|
||||
}
|
||||
}
|
||||
|
||||
void Drawing::RemoveWaypoints(Waypoint points[], size_t numPoints)
|
||||
{
|
||||
//Build a list of indices of waypoints we should delete.
|
||||
size_t delPoints[WAYPOINT_MAX];
|
||||
size_t delPointsCur = 0;
|
||||
for (size_t i = 0; i < numPoints; ++i)
|
||||
{
|
||||
Waypoint p = points[i];
|
||||
for (size_t j = 0; j < numWaypoints; ++j)
|
||||
{
|
||||
Waypoint q = waypoints[j];
|
||||
if (p.latitude == q.latitude &&
|
||||
p.longitude == q.longitude &&
|
||||
p.altitude == q.altitude)
|
||||
{
|
||||
delPoints[delPointsCur++] = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
//Sort the indices so that we only have to iterate them once
|
||||
qsort(delPoints, delPointsCur, sizeof(size_t), cmp);
|
||||
|
||||
//Copy the new array on top of the old array
|
||||
size_t copyCur = 0;
|
||||
size_t count = delPointsCur;
|
||||
delPointsCur = 0;
|
||||
for (size_t i = 0; i < numWaypoints; ++i)
|
||||
{
|
||||
if (i == delPoints[delPointsCur])
|
||||
{
|
||||
++delPointsCur;
|
||||
continue;
|
||||
}
|
||||
waypoints[copyCur++] = waypoints[i];
|
||||
}
|
||||
numWaypoints -= count;
|
||||
if (numWaypoints == 0)
|
||||
{
|
||||
ClearWaypoints();
|
||||
}
|
||||
}
|
||||
}
|
||||
61
xpcPlugin/Drawing.h
Normal file
61
xpcPlugin/Drawing.h
Normal file
@@ -0,0 +1,61 @@
|
||||
//Copyright (c) 2013-2015 United States Government as represented by the Administrator of the
|
||||
//National Aeronautics and Space Administration. All Rights Reserved.
|
||||
#ifndef XPC_DRAWING_H
|
||||
#define XPC_DRAWING_H
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
namespace XPC
|
||||
{
|
||||
typedef struct
|
||||
{
|
||||
double latitude;
|
||||
double longitude;
|
||||
double altitude;
|
||||
} Waypoint;
|
||||
|
||||
/// Handles tasks that involve drawing to the screen in X-Plane.
|
||||
///
|
||||
/// \author Jason Watkins
|
||||
/// \version 1.0
|
||||
/// \since 1.0
|
||||
/// \date Intial Version: 2015-04-10
|
||||
/// \date Last Updated: 2015-04-10
|
||||
class Drawing
|
||||
{
|
||||
public:
|
||||
/// Clears the current message on the screen if any and unregisters the
|
||||
/// draw callback for message drawing.
|
||||
static void ClearMessage();
|
||||
|
||||
/// Sets the message to be drawn on the screen.
|
||||
///
|
||||
/// \param x The x coordinate of the message relative to the left edge
|
||||
/// of the screen.
|
||||
/// \param y The y coordinate of the message relative to the bottom
|
||||
/// edge of the screen
|
||||
/// \param msg A C string containing the message to display. The message
|
||||
/// value is copied into a local buffer.
|
||||
static void SetMessage(int x, int y, char* msg);
|
||||
|
||||
/// Adds the given waypoints to the list of waypoints to draw.
|
||||
///
|
||||
/// \param points A pointer to an array of waypoints.
|
||||
/// \param numPoints The number of points in the array.
|
||||
static void AddWaypoints(Waypoint points[], size_t numPoints);
|
||||
|
||||
/// Removes all waypoints and unregisters the callback for waypoint
|
||||
/// drawing.
|
||||
static void ClearWaypoints();
|
||||
|
||||
/// Removes the given waypoints from the list of waypoints to draw.
|
||||
/// If all waypoints are removed as a result of this action, unregisters
|
||||
/// the callback for waypoint drawing.
|
||||
///
|
||||
/// \param points A pointer to an array of waypoints.
|
||||
/// \param numPoints The number of points in the array.
|
||||
static void RemoveWaypoints(Waypoint points[], size_t numPoints);
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
97
xpcPlugin/Log.cpp
Normal file
97
xpcPlugin/Log.cpp
Normal file
@@ -0,0 +1,97 @@
|
||||
//Copyright (c) 2013-2015 United States Government as represented by the Administrator of the
|
||||
//National Aeronautics and Space Administration. All Rights Reserved.
|
||||
#include "Log.h"
|
||||
#include <cstdarg>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
|
||||
// Implementation note: I initial wrote this class using C++ iostreams, but I couldn't find any
|
||||
// way to implement FormatLine without adding in a call to sprintf. It therefore seems more
|
||||
// efficient to me to just use C-style IO and call fprintf directly.
|
||||
namespace XPC
|
||||
{
|
||||
static void WriteTime(FILE* fd)
|
||||
{
|
||||
time_t rawtime;
|
||||
tm* timeinfo;
|
||||
time(&rawtime);
|
||||
timeinfo = localtime(&rawtime);
|
||||
|
||||
char buffer[16] = { 0 };
|
||||
// Format is equivalent to [%F %T], but neither of those specifiers is
|
||||
// supported on Windows as of Visual Studio 13
|
||||
strftime(buffer, 16, "[%H:%M:%S] ", timeinfo);
|
||||
|
||||
fprintf(fd, buffer);
|
||||
}
|
||||
|
||||
void Log::Initialize(std::string version)
|
||||
{
|
||||
FILE* fd = fopen("XPCLog.txt", "w");
|
||||
if (fd != NULL)
|
||||
{
|
||||
time_t rawtime;
|
||||
tm* timeinfo;
|
||||
time(&rawtime);
|
||||
timeinfo = localtime(&rawtime);
|
||||
|
||||
char timeStr[16] = { 0 };
|
||||
// Format is equivalent to %F, but neither of those specifiers is
|
||||
// supported on Windows as of Visual Studio 13
|
||||
strftime(timeStr, 16, "%Y-%m-%d", timeinfo);
|
||||
|
||||
fprintf(fd, "X-Plane Connect [Version %s]\n", version.c_str());
|
||||
fprintf(fd, "Compiled %s %s\n", __DATE__, __TIME__);
|
||||
fprintf(fd, "Copyright (c) 2013-2015 United States Government as represented by the\n");
|
||||
fprintf(fd, "Administrator of the National Aeronautics and Space Administration.\n");
|
||||
fprintf(fd, "All Rights Reserved.\n\n");
|
||||
|
||||
fprintf(fd, "This file contains debugging information about the X-Plane Connect plugin.\n");
|
||||
fprintf(fd, "If you have technical issues with the plugin, please report them by opening\n");
|
||||
fprintf(fd, "an issue on GitHub (https://github.com/nasa/XPlaneConnect/issues) or by\n");
|
||||
fprintf(fd, "emailing Christopher Teubert (christopher.a.teubert@nasa.gov).\n\n");
|
||||
|
||||
fprintf(fd, "Log file generated on %s.\n", timeStr);
|
||||
fclose(fd);
|
||||
}
|
||||
}
|
||||
|
||||
void Log::WriteLine(const std::string& value)
|
||||
{
|
||||
Log::WriteLine(value.c_str());
|
||||
}
|
||||
|
||||
void Log::WriteLine(const char* value)
|
||||
{
|
||||
FILE* fd = fopen("XPCLog.txt", "a");
|
||||
if (!fd)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
WriteTime(fd);
|
||||
fprintf(fd, "%s\n", value);
|
||||
|
||||
fclose(fd);
|
||||
}
|
||||
|
||||
void Log::FormatLine(const char* format, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
FILE* fd = fopen("XPCLog.txt", "a");
|
||||
if (!fd)
|
||||
{
|
||||
return;
|
||||
}
|
||||
va_start(args, format);
|
||||
|
||||
WriteTime(fd);
|
||||
vfprintf(fd, format, args);
|
||||
fprintf(fd, "\n");
|
||||
|
||||
fclose(fd);
|
||||
|
||||
va_end(args);
|
||||
}
|
||||
}
|
||||
59
xpcPlugin/Log.h
Normal file
59
xpcPlugin/Log.h
Normal file
@@ -0,0 +1,59 @@
|
||||
//Copyright (c) 2013-2015 United States Government as represented by the Administrator of the
|
||||
//National Aeronautics and Space Administration. All Rights Reserved.
|
||||
#ifndef XPC_LOG_H
|
||||
#define XPC_LOG_H
|
||||
#include <string>
|
||||
|
||||
// LOG_VERBOSITY determines the level of logging throughout the plugin.
|
||||
// 0: Minimum logging. Only plugin manager events will be logged.
|
||||
// 1: Critical errors. When an error that prevents correct operation of the
|
||||
// plugin, attempt to write useful information to the log. Note that since
|
||||
// XPC runs inside the X-Plane executable, we try very hard no to crash.
|
||||
// As a result, these log messages may be the only indication of failure.
|
||||
// 2: All errors. Any time something unexpected happens, log it.
|
||||
// 3: Significant actions. Any time something happens outside of normal
|
||||
// command processing, log it.
|
||||
// 5: Everything. Log nearly every single action the plugin takes. This may
|
||||
// have a detrimental impact on X-Plane performance.
|
||||
#define LOG_VERBOSITY 2
|
||||
|
||||
namespace XPC
|
||||
{
|
||||
/// Handles logging for the plugin.
|
||||
///
|
||||
/// \details Provides functions to write lines to the XPC log file.
|
||||
/// \author Jason Watkins
|
||||
/// \version 1.0
|
||||
/// \since 1.0
|
||||
/// \date Intial Version: 2015-04-09
|
||||
/// \date Last Updated: 2015-04-09
|
||||
class Log
|
||||
{
|
||||
public:
|
||||
/// Initializes the logging component by deleting old log files,
|
||||
/// writing header information to the log file.
|
||||
static void Initialize(std::string header);
|
||||
|
||||
/// Writes the C string pointed to by format, followed by a line
|
||||
/// terminator to the XPC log file. If format contains format
|
||||
/// specifiers, additional arguments following format will be formatted
|
||||
/// and inserted in the resulting string, replacing their respective
|
||||
/// specifiers.
|
||||
///
|
||||
/// \param format The format string appropriate for consumption by sprintf.
|
||||
static void FormatLine(const char* format, ...);
|
||||
|
||||
/// Writes the specified string value, followed by a line terminator
|
||||
/// to the XPC log file.
|
||||
///
|
||||
/// \param value The value to write.
|
||||
static void WriteLine(const std::string& value);
|
||||
|
||||
/// Writes the specified C string value, followed by a line terminator
|
||||
/// to the XPC log file.
|
||||
///
|
||||
/// \param value The value to write.
|
||||
static void WriteLine(const char* value);
|
||||
};
|
||||
}
|
||||
#endif
|
||||
184
xpcPlugin/Message.cpp
Normal file
184
xpcPlugin/Message.cpp
Normal file
@@ -0,0 +1,184 @@
|
||||
//Copyright (c) 2013-2015 United States Government as represented by the Administrator of the
|
||||
//National Aeronautics and Space Administration. All Rights Reserved.
|
||||
#include "Message.h"
|
||||
#include "Log.h"
|
||||
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
namespace XPC
|
||||
{
|
||||
Message::Message() {}
|
||||
|
||||
Message Message::ReadFrom(UDPSocket& sock)
|
||||
{
|
||||
Message m;
|
||||
int len = sock.Read(m.buffer, bufferSize, &m.source);
|
||||
m.size = len < 0 ? 0 : len;
|
||||
return m;
|
||||
}
|
||||
|
||||
unsigned long Message::GetMagicNumber()
|
||||
{
|
||||
if (size < 4)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return *((unsigned long*)buffer);
|
||||
}
|
||||
|
||||
std::string Message::GetHead()
|
||||
{
|
||||
if (size < 4)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
return std::string((char*)buffer, 4);
|
||||
}
|
||||
|
||||
const unsigned char* Message::GetBuffer()
|
||||
{
|
||||
if (size == 0)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
std::size_t Message::GetSize()
|
||||
{
|
||||
return size;
|
||||
}
|
||||
|
||||
struct sockaddr Message::GetSource()
|
||||
{
|
||||
return source;
|
||||
}
|
||||
|
||||
void Message::PrintToLog()
|
||||
{
|
||||
#if LOG_VERBOSITY > 4
|
||||
std::stringstream ss;
|
||||
ss << "[DEBUG]";
|
||||
|
||||
// Dump raw bytes to string
|
||||
ss << std::hex << std::setfill('0');
|
||||
for (int i = 0; i < size; ++i)
|
||||
{
|
||||
ss << ' ' << std::setw(2) << static_cast<unsigned>(buffer[i]);
|
||||
}
|
||||
Log::WriteLine(ss.str());
|
||||
|
||||
ss << std::dec;
|
||||
ss.str("");
|
||||
ss << "[" << GetHead() << "-DEBUG] (" << GetSize() << ")";
|
||||
switch (GetMagicNumber()) // Binary version of head
|
||||
{
|
||||
case 0x4E4EF443: // CONN
|
||||
case 0x54505957: // WYPT
|
||||
case 0x54584554: // TEXT
|
||||
{
|
||||
Log::WriteLine(ss.str());
|
||||
break;
|
||||
}
|
||||
case 0x4C525443: // CTRL
|
||||
{
|
||||
// Parse message data
|
||||
float pitch = *((float*)(buffer + 5));
|
||||
float roll = *((float*)(buffer + 9));
|
||||
float yaw = *((float*)(buffer + 13));
|
||||
float thr = *((float*)(buffer + 17));
|
||||
char gear = buffer[21];
|
||||
float flaps = *((float*)(buffer + 22));
|
||||
unsigned char aircraft = 0;
|
||||
if (size == 27)
|
||||
{
|
||||
aircraft = buffer[26];
|
||||
}
|
||||
ss << " Attitude:(" << pitch << " " << roll << " " << yaw << ")";
|
||||
ss << " Thr:" << thr << " Gear:" << (int)gear << " Flaps:" << flaps;
|
||||
Log::WriteLine(ss.str());
|
||||
break;
|
||||
}
|
||||
case 0x41544144: // DATA
|
||||
{
|
||||
std::size_t numCols = (size - 5) / 36;
|
||||
float values[32][9];
|
||||
for (int i = 0; i < numCols; ++i)
|
||||
{
|
||||
values[i][0] = buffer[5 + 36 * i];
|
||||
memcpy(values[i] + 1, buffer + 9 + 36 * i, 9 * sizeof(float));
|
||||
}
|
||||
ss << " (" << numCols << " lines)";
|
||||
Log::WriteLine(ss.str());
|
||||
for (int i = 0; i < numCols; ++i)
|
||||
{
|
||||
ss.str("");
|
||||
ss << "\t#" << values[i][0];
|
||||
for (int j = 1; j < 9; ++j)
|
||||
{
|
||||
ss << " " << values[i][j];
|
||||
}
|
||||
Log::WriteLine(ss.str());
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 0x46455244: // DREF
|
||||
{
|
||||
Log::WriteLine(ss.str());
|
||||
std::string dref((char*)buffer + 6, buffer[5]);
|
||||
Log::FormatLine("-\tDREF (size %i) = %s", dref.length(), dref.c_str());
|
||||
ss.str("");
|
||||
int values = buffer[6 + buffer[5]];
|
||||
ss << "\tValues(size " << values << ") =";
|
||||
for (int i = 0; i < values; ++i)
|
||||
{
|
||||
ss << " " << *((float*)(buffer + values + 1 + sizeof(float) * i));
|
||||
}
|
||||
Log::WriteLine(ss.str());
|
||||
break;
|
||||
}
|
||||
case 0x44544547: // GETD
|
||||
{
|
||||
Log::WriteLine(ss.str());
|
||||
int cur = 6;
|
||||
for (int i = 0; i < buffer[5]; ++i)
|
||||
{
|
||||
std::string dref((char*)buffer + cur + 1, buffer[cur]);
|
||||
Log::FormatLine("\t#%i/%i (size:%i) %s", i + 1, buffer[5], dref.length(), dref.c_str());
|
||||
cur += 1 + buffer[cur];
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 0x49534F50: // POSI
|
||||
{
|
||||
char aircraft = buffer[5];
|
||||
float gear = *((float*)(buffer + 30));
|
||||
float pos[3];
|
||||
float orient[3];
|
||||
memcpy(pos, buffer + 6, 12);
|
||||
memcpy(orient, buffer + 18, 12);
|
||||
ss << " AC:" << (int)aircraft;
|
||||
ss << " Pos:(" << pos[0] << ' ' << pos[1] << ' ' << pos[2] << ") Orient:(";
|
||||
ss << orient[3] << ' ' << orient[4] << ' ' << orient[5] << ") Gear:";
|
||||
ss << gear;
|
||||
Log::WriteLine(ss.str());
|
||||
break;
|
||||
}
|
||||
case 0x554D4953: // SIMU
|
||||
{
|
||||
ss << ' ' << (int)buffer[5];
|
||||
Log::WriteLine(ss.str());
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
ss << " UNKNOWN HEADER ";
|
||||
Log::WriteLine(ss.str());
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
57
xpcPlugin/Message.h
Normal file
57
xpcPlugin/Message.h
Normal file
@@ -0,0 +1,57 @@
|
||||
//Copyright (c) 2013-2015 United States Government as represented by the Administrator of the
|
||||
//National Aeronautics and Space Administration. All Rights Reserved.
|
||||
#ifndef XPC_MESSAGE_H
|
||||
#define XPC_MESSAGE_H
|
||||
|
||||
#include "UDPSocket.h"
|
||||
|
||||
namespace XPC
|
||||
{
|
||||
/// Represents a message received from an XPC client.
|
||||
///
|
||||
/// \author Jason Watkins
|
||||
/// \version 1.0
|
||||
/// \since 1.0
|
||||
/// \date Intial Version: 2015-04-11
|
||||
/// \date Last Updated: 2015-04-11
|
||||
class Message
|
||||
{
|
||||
public:
|
||||
/// Reads a datagram from the specified socket and interprets it as a
|
||||
/// message.
|
||||
///
|
||||
/// \param sock The socket to read from.
|
||||
/// \returns A message parsed from the data read from sock. If no
|
||||
/// data was read or an error occurs, returns a message
|
||||
/// with the size set to 0.
|
||||
static Message ReadFrom(UDPSocket& sock);
|
||||
|
||||
/// Gets the message header in binary form.
|
||||
unsigned long GetMagicNumber();
|
||||
|
||||
/// Gets the message header.
|
||||
std::string GetHead();
|
||||
|
||||
/// Gets the buffer underlying the message.
|
||||
const unsigned char* GetBuffer();
|
||||
|
||||
/// Gets the size of the message in bytes.
|
||||
std::size_t GetSize();
|
||||
|
||||
/// Gets the address this message was read from.
|
||||
struct sockaddr GetSource();
|
||||
|
||||
/// Prints the contents of the message to the XPC log.
|
||||
void PrintToLog();
|
||||
|
||||
private:
|
||||
Message();
|
||||
|
||||
static const std::size_t bufferSize = 4096;
|
||||
unsigned char buffer[bufferSize];
|
||||
std::size_t size;
|
||||
struct sockaddr source;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
622
xpcPlugin/MessageHandlers.cpp
Normal file
622
xpcPlugin/MessageHandlers.cpp
Normal file
@@ -0,0 +1,622 @@
|
||||
//Copyright (c) 2013-2015 United States Government as represented by the Administrator of the
|
||||
//National Aeronautics and Space Administration. All Rights Reserved.
|
||||
#include "MessageHandlers.h"
|
||||
#include "DataManager.h"
|
||||
#include "DataMaps.h"
|
||||
#include "Drawing.h"
|
||||
#include "Log.h"
|
||||
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
|
||||
namespace XPC
|
||||
{
|
||||
std::map<std::string, MessageHandlers::ConnectionInfo> MessageHandlers::connections;
|
||||
std::map<std::string, MessageHandler> MessageHandlers::handlers;
|
||||
|
||||
std::string MessageHandlers::connectionKey;
|
||||
MessageHandlers::ConnectionInfo MessageHandlers::connection;
|
||||
UDPSocket* MessageHandlers::sock;
|
||||
|
||||
void MessageHandlers::SetSocket(UDPSocket* socket)
|
||||
{
|
||||
MessageHandlers::sock = socket;
|
||||
}
|
||||
|
||||
void MessageHandlers::HandleMessage(Message& msg)
|
||||
{
|
||||
if (handlers.size() == 0)
|
||||
{
|
||||
// Common messages
|
||||
handlers.insert(std::make_pair("CONN", MessageHandlers::HandleConn));
|
||||
handlers.insert(std::make_pair("CTRL", MessageHandlers::HandleCtrl));
|
||||
handlers.insert(std::make_pair("DATA", MessageHandlers::HandleData));
|
||||
handlers.insert(std::make_pair("DREF", MessageHandlers::HandleDref));
|
||||
handlers.insert(std::make_pair("GETD", MessageHandlers::HandleGetD));
|
||||
handlers.insert(std::make_pair("POSI", MessageHandlers::HandlePosi));
|
||||
handlers.insert(std::make_pair("SIMU", MessageHandlers::HandleSimu));
|
||||
handlers.insert(std::make_pair("TEXT", MessageHandlers::HandleText));
|
||||
handlers.insert(std::make_pair("WYPT", MessageHandlers::HandleWypt));
|
||||
// Not implemented messages
|
||||
handlers.insert(std::make_pair("VIEW", MessageHandlers::HandleUnknown));
|
||||
// X-Plane data messages
|
||||
handlers.insert(std::make_pair("DSEL", MessageHandlers::HandleXPlaneData));
|
||||
handlers.insert(std::make_pair("USEL", MessageHandlers::HandleXPlaneData));
|
||||
handlers.insert(std::make_pair("DCOC", MessageHandlers::HandleXPlaneData));
|
||||
handlers.insert(std::make_pair("UCOC", MessageHandlers::HandleXPlaneData));
|
||||
handlers.insert(std::make_pair("MOUS", MessageHandlers::HandleXPlaneData));
|
||||
handlers.insert(std::make_pair("CHAR", MessageHandlers::HandleXPlaneData));
|
||||
handlers.insert(std::make_pair("MENU", MessageHandlers::HandleXPlaneData));
|
||||
handlers.insert(std::make_pair("SOUN", MessageHandlers::HandleXPlaneData));
|
||||
handlers.insert(std::make_pair("FAIL", MessageHandlers::HandleXPlaneData));
|
||||
handlers.insert(std::make_pair("RECO", MessageHandlers::HandleXPlaneData));
|
||||
handlers.insert(std::make_pair("PAPT", MessageHandlers::HandleXPlaneData));
|
||||
handlers.insert(std::make_pair("VEHN", MessageHandlers::HandleXPlaneData));
|
||||
handlers.insert(std::make_pair("VEH1", MessageHandlers::HandleXPlaneData));
|
||||
handlers.insert(std::make_pair("VEHA", MessageHandlers::HandleXPlaneData));
|
||||
handlers.insert(std::make_pair("GSET", MessageHandlers::HandleXPlaneData));
|
||||
handlers.insert(std::make_pair("OBJN", MessageHandlers::HandleXPlaneData));
|
||||
handlers.insert(std::make_pair("OBJL", MessageHandlers::HandleXPlaneData));
|
||||
handlers.insert(std::make_pair("GSET", MessageHandlers::HandleXPlaneData));
|
||||
handlers.insert(std::make_pair("ISET", MessageHandlers::HandleXPlaneData));
|
||||
handlers.insert(std::make_pair("BOAT", MessageHandlers::HandleXPlaneData));
|
||||
}
|
||||
|
||||
// Make sure we really have a message to handle.
|
||||
std::string head = msg.GetHead();
|
||||
if (head == "")
|
||||
{
|
||||
return; // No Message to handle
|
||||
}
|
||||
msg.PrintToLog();
|
||||
|
||||
// Set current connection
|
||||
sockaddr sourceaddr = msg.GetSource();
|
||||
connectionKey = UDPSocket::GetHost(&sourceaddr);
|
||||
#if LOG_VERBOSITY > 4
|
||||
Log::FormatLine("[MSGH] Handling message from %s", connectionKey.c_str());
|
||||
#endif
|
||||
std::map<std::string, ConnectionInfo>::iterator conn = connections.find(connectionKey);
|
||||
if (conn == connections.end()) // New connection
|
||||
{
|
||||
connection = MessageHandlers::ConnectionInfo();
|
||||
// If this is a new connection, that means we just added an elment
|
||||
// to connections. As long as we never remove elements, the size of
|
||||
// connections will serve as a unique id.
|
||||
connection.id = static_cast<unsigned char>(connections.size());
|
||||
connection.addr = sourceaddr;
|
||||
connection.getdCount = 0;
|
||||
connections[connectionKey] = connection;
|
||||
#if LOG_VERBOSITY > 2
|
||||
Log::FormatLine("[MSGH] New connection. ID=%u, Remote=%s", connection.id, connectionKey.c_str());
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
connection = (*conn).second;
|
||||
#if LOG_VERBOSITY > 3
|
||||
Log::FormatLine("[MSGH] Existing connection. ID=%u, Remote=%s",
|
||||
connection.id, connectionKey.c_str());
|
||||
#endif
|
||||
}
|
||||
|
||||
// Check if there is a handler for this message type. If so, execute
|
||||
// that handler. Otherwise, execute the unknown message handler.
|
||||
std::map<std::string, MessageHandler>::iterator iter = handlers.find(head);
|
||||
if (iter != handlers.end())
|
||||
{
|
||||
MessageHandler handler = (*iter).second;
|
||||
handler(msg);
|
||||
}
|
||||
else
|
||||
{
|
||||
MessageHandlers::HandleUnknown(msg);
|
||||
}
|
||||
}
|
||||
|
||||
void MessageHandlers::HandleConn(Message& msg)
|
||||
{
|
||||
const unsigned char* buffer = msg.GetBuffer();
|
||||
|
||||
// Store new port
|
||||
unsigned short port = *((unsigned short*)(buffer + 5));
|
||||
sockaddr* sa = &connection.addr;
|
||||
switch (sa->sa_family)
|
||||
{
|
||||
case AF_INET:
|
||||
{
|
||||
sockaddr_in* sin = reinterpret_cast<sockaddr_in*>(sa);
|
||||
(*sin).sin_port = htons(port);
|
||||
break;
|
||||
}
|
||||
case AF_INET6:
|
||||
{
|
||||
sockaddr_in6* sin = reinterpret_cast<sockaddr_in6*>(sa);
|
||||
(*sin).sin6_port = htons(port);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
#if LOG_VERBOSITY > 0
|
||||
Log::WriteLine("[CONN] ERROR: Unknown address type.");
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
connections.erase(connectionKey);
|
||||
connectionKey = UDPSocket::GetHost(&connection.addr);
|
||||
connections[connectionKey] = connection;
|
||||
|
||||
// Create response
|
||||
unsigned char response[6] = "CONF";
|
||||
response[5] = connection.id;
|
||||
|
||||
// Update log
|
||||
#if LOG_VERBOSITY > 1
|
||||
Log::FormatLine("[CONN] ID: %u New destination port: %u",
|
||||
connection.id, port);
|
||||
#endif
|
||||
|
||||
// Send response
|
||||
sock->SendTo(response, 6, &connection.addr);
|
||||
}
|
||||
|
||||
void MessageHandlers::HandleCtrl(Message& msg)
|
||||
{
|
||||
// Update Log
|
||||
#if LOG_VERBOSITY > 2
|
||||
Log::FormatLine("[CTRL] Message Received (Conn %i)", connection.id);
|
||||
#endif
|
||||
|
||||
const unsigned char* buffer = msg.GetBuffer();
|
||||
std::size_t size = msg.GetSize();
|
||||
//Legacy packets that don't specify an aircraft number should be 26 bytes long.
|
||||
//Packets specifying an A/C num should be 27 bytes.
|
||||
if (size != 26 && size != 27)
|
||||
{
|
||||
#if LOG_VERBOSITY > 0
|
||||
Log::FormatLine("[CTRL] ERROR: Unexpected message length (%i)", size);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
// Parse message data
|
||||
float pitch = *((float*)(buffer + 5));
|
||||
float roll = *((float*)(buffer + 9));
|
||||
float yaw = *((float*)(buffer + 13));
|
||||
float thr = *((float*)(buffer + 17));
|
||||
char gear = buffer[21];
|
||||
float flaps = *((float*)(buffer + 22));
|
||||
unsigned char aircraft = 0;
|
||||
if (size == 27)
|
||||
{
|
||||
aircraft = buffer[26];
|
||||
}
|
||||
|
||||
float thrArray[8];
|
||||
for (int i = 0; i < 8; ++i)
|
||||
{
|
||||
thrArray[i] = thr;
|
||||
}
|
||||
|
||||
DataManager::Set(DREF_YokePitch, pitch, aircraft);
|
||||
DataManager::Set(DREF_YokeRoll, roll, aircraft);
|
||||
DataManager::Set(DREF_YokeHeading, yaw, aircraft);
|
||||
DataManager::Set(DREF_ThrottleSet, thrArray, 8, aircraft);
|
||||
DataManager::Set(DREF_ThrottleActual, thrArray, 8, aircraft);
|
||||
if (aircraft == 0)
|
||||
{
|
||||
DataManager::Set("sim/flightmodel/engine/ENGN_thro_override", thrArray, 1);
|
||||
}
|
||||
if (gear != -1)
|
||||
{
|
||||
DataManager::SetGear(gear, false, aircraft);
|
||||
}
|
||||
if (flaps < -999.5 || flaps > -997.5)
|
||||
{
|
||||
DataManager::Set(DREF_FlapSetting, flaps, aircraft);
|
||||
}
|
||||
}
|
||||
|
||||
void MessageHandlers::HandleData(Message& msg)
|
||||
{
|
||||
// Parse data
|
||||
const unsigned char* buffer = msg.GetBuffer();
|
||||
std::size_t size = msg.GetSize();
|
||||
std::size_t numCols = (size - 5) / 36;
|
||||
if (numCols > 0)
|
||||
{
|
||||
#if LOG_VERBOSITY > 1
|
||||
Log::FormatLine("[DATA] Message Received (Conn %i)", connection.id);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#if LOG_VERBOSITY > 0
|
||||
Log::FormatLine("[DATA] WARNING: Empty data packet received (Conn %i)", connection.id);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
if (numCols > 134) // Error. Will overflow values
|
||||
{
|
||||
#if LOG_VERBOSITY > 0
|
||||
Log::FormatLine("[DATA] ERROR: numCols to large.");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
float values[134][9];
|
||||
for (int i = 0; i < numCols; ++i)
|
||||
{
|
||||
values[i][0] = buffer[5 + 36 * i];
|
||||
memcpy(values[i] + 1, buffer + 9 + 36 * i, 9 * sizeof(float));
|
||||
}
|
||||
|
||||
// Update log
|
||||
|
||||
float savedAlpha = -998;
|
||||
float savedHPath = -998;
|
||||
for (int i = 0; i < numCols; ++i)
|
||||
{
|
||||
unsigned char dataRef = (unsigned char)values[i][0];
|
||||
if (dataRef >= 134)
|
||||
{
|
||||
#if LOG_VERBOSITY > 0
|
||||
Log::FormatLine("[DATA] ERROR: DataRef # must be between 0 - 134 (Received: %hi)", (int)dataRef);
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (dataRef)
|
||||
{
|
||||
case 3: // Velocity
|
||||
{
|
||||
float theta = DataManager::GetFloat(DREF_Pitch);
|
||||
float alpha = savedAlpha != -998 ? savedAlpha : DataManager::GetFloat(DREF_AngleOfAttack);
|
||||
float hpath = savedHPath != -998 ? savedHPath : DataManager::GetFloat(DREF_HPath);
|
||||
if (alpha != alpha || hpath != hpath)
|
||||
{
|
||||
#if LOG_VERBOSITY > 0
|
||||
Log::WriteLine("[DATA] ERROR: Value must be a number (NaN received)");
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
const float deg2rad = 0.0174532925F;
|
||||
int ind[3] = { 1, 3, 4 };
|
||||
for (int j = 0; j < 3; ++j)
|
||||
{
|
||||
float v = values[i][ind[j]];
|
||||
if (v != -998)
|
||||
{
|
||||
DataManager::Set(DREF_LocalVX, v*cos((theta - alpha)*deg2rad)*sin(hpath*deg2rad));
|
||||
DataManager::Set(DREF_LocalVY, v*sin((theta - alpha)*deg2rad));
|
||||
DataManager::Set(DREF_LocalVZ, -v*cos((theta - alpha)*deg2rad)*cos(hpath*deg2rad));
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 17: // Orientation
|
||||
{
|
||||
float orient[3];
|
||||
orient[0] = values[i][1];
|
||||
orient[1] = values[i][2];
|
||||
orient[2] = values[i][3];
|
||||
DataManager::SetOrientation(orient);
|
||||
break;
|
||||
}
|
||||
case 18: // Alpha, hpath etc.
|
||||
{
|
||||
if (values[i][1] != values[i][1] || values[i][3] != values[i][3])
|
||||
{
|
||||
#if LOG_VERBOSITY > 0
|
||||
Log::WriteLine("[DATA] ERROR: Value must be a number (NaN received)");
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
if (values[i][1] != -998)
|
||||
{
|
||||
savedAlpha = values[i][1];
|
||||
}
|
||||
if (values[i][3] != -998)
|
||||
{
|
||||
savedHPath = values[i][3];
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 20: // Position
|
||||
{
|
||||
float pos[3];
|
||||
pos[0] = values[i][2];
|
||||
pos[1] = values[i][3];
|
||||
pos[2] = values[i][4];
|
||||
DataManager::SetPosition(pos);
|
||||
break;
|
||||
}
|
||||
case 25: // Throttle
|
||||
{
|
||||
if (values[i][1] != values[i][1])
|
||||
{
|
||||
#if LOG_VERBOSITY > 0
|
||||
Log::WriteLine("[DATA] ERROR: Value must be a number (NaN received)");
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
float thr[8];
|
||||
for (int j = 0; j < 8; ++j)
|
||||
{
|
||||
thr[j] = values[i][1];
|
||||
}
|
||||
DataManager::Set(DREF_ThrottleSet, thr, 8);
|
||||
break;
|
||||
}
|
||||
default: // Non-Special dataRefs
|
||||
{
|
||||
float line[8];
|
||||
memcpy(line, values[i] + 1, 8 * sizeof(float));
|
||||
for (int j = 0; j < 8; ++j)
|
||||
{
|
||||
#if LOG_VERBOSITY > 1
|
||||
Log::FormatLine("[DATA] Setting Dataref %i.%i to %f", dataRef, j, line[j]);
|
||||
#endif
|
||||
|
||||
if (dataRef == 14 && j == 0)
|
||||
{
|
||||
DataManager::SetGear(line[0], true);
|
||||
continue;
|
||||
}
|
||||
|
||||
DREF dref = XPData[dataRef][j];
|
||||
if (dref == DREF_None)
|
||||
{
|
||||
// TODO: Send single line instead!
|
||||
HandleXPlaneData(msg);
|
||||
}
|
||||
else
|
||||
{
|
||||
DataManager::Set(dref, line, 8);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MessageHandlers::HandleDref(Message& msg)
|
||||
{
|
||||
const unsigned char* buffer = msg.GetBuffer();
|
||||
unsigned char len = buffer[5];
|
||||
std::string dref = std::string((char*)buffer + 6, len);
|
||||
|
||||
unsigned char valueCount = buffer[6 + len];
|
||||
float* values = (float*)(buffer + 7 + len);
|
||||
|
||||
#if LOG_VERBOSITY > 1
|
||||
Log::FormatLine("[DREF] Request to set DREF value received (Conn %i): %s", connection.id, dref.c_str());
|
||||
#endif
|
||||
|
||||
DataManager::Set(dref, values, valueCount);
|
||||
}
|
||||
|
||||
void MessageHandlers::HandleGetD(Message& msg)
|
||||
{
|
||||
const unsigned char* buffer = msg.GetBuffer();
|
||||
unsigned char drefCount = buffer[5];
|
||||
if (drefCount == 0) // Use last request
|
||||
{
|
||||
#if LOG_VERBOSITY > 0
|
||||
Log::FormatLine("[GETD] DATA Requested: Repeat last request from connection %i (%i data refs)",
|
||||
connection.id, connection.getdCount);
|
||||
#endif
|
||||
if (connection.getdCount == 0) // No previous request to use
|
||||
{
|
||||
#if LOG_VERBOSITY > 1
|
||||
Log::FormatLine("[GETD] ERROR: No previous requests from connection %i.", connection.id);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
}
|
||||
else // New request
|
||||
{
|
||||
#if LOG_VERBOSITY > 0
|
||||
Log::FormatLine("[GETD] DATA Requested: New Request for connection %i (%i data refs)",
|
||||
connection.id, drefCount);
|
||||
#endif
|
||||
std::size_t ptr = 6;
|
||||
for (int i = 0; i < drefCount; ++i)
|
||||
{
|
||||
unsigned char len = buffer[ptr];
|
||||
connection.getdRequest[i] = std::string((char*)buffer + 1 + ptr, len);
|
||||
ptr += 1 + len;
|
||||
}
|
||||
connection.getdCount = drefCount;
|
||||
connections[connectionKey] = connection;
|
||||
}
|
||||
|
||||
unsigned char response[4096] = "RESP";
|
||||
response[5] = drefCount;
|
||||
std::size_t cur = 6;
|
||||
for (int i = 0; i < drefCount; ++i)
|
||||
{
|
||||
float values[255];
|
||||
int count = DataManager::Get(connection.getdRequest[i], values, 255);
|
||||
response[cur++] = count;
|
||||
memcpy(response + cur, values, count * sizeof(float));
|
||||
cur += count * sizeof(float);
|
||||
}
|
||||
|
||||
sock->SendTo(response, cur, &connection.addr);
|
||||
}
|
||||
|
||||
void MessageHandlers::HandlePosi(Message& msg)
|
||||
{
|
||||
// Update log
|
||||
#if LOG_VERBOSITY > 0
|
||||
Log::FormatLine("[POSI] Message Received (Conn %i)", connection.id);
|
||||
#endif
|
||||
|
||||
const unsigned char* buffer = msg.GetBuffer();
|
||||
const std::size_t size = msg.GetSize();
|
||||
if (size < 34)
|
||||
{
|
||||
#if LOG_VERBOSITY > 1
|
||||
Log::FormatLine("[POSI] ERROR: Unexpected size: %i (Expected at least 34)", size);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
char aircraft = buffer[5];
|
||||
float gear = *((float*)(buffer + 30));
|
||||
float pos[3];
|
||||
float orient[3];
|
||||
memcpy(pos, buffer + 6, 12);
|
||||
memcpy(orient, buffer + 18, 12);
|
||||
|
||||
if (aircraft > 0)
|
||||
{
|
||||
// Enable AI for the aircraft we are setting
|
||||
float ai[20];
|
||||
std::size_t result = DataManager::GetFloatArray(DREF_PauseAI, ai, 20);
|
||||
if (result == 20) // Only set values if they were retrieved successfully.
|
||||
{
|
||||
ai[aircraft] = 1;
|
||||
DataManager::Set(DREF_PauseAI, ai, 0, 20);
|
||||
}
|
||||
}
|
||||
|
||||
DataManager::SetPosition(pos, aircraft);
|
||||
DataManager::SetOrientation(orient, aircraft);
|
||||
if (gear != -1)
|
||||
{
|
||||
DataManager::SetGear(gear, true, aircraft);
|
||||
}
|
||||
}
|
||||
|
||||
void MessageHandlers::HandleSimu(Message& msg)
|
||||
{
|
||||
// Update log
|
||||
#if LOG_VERBOSITY > 0
|
||||
Log::FormatLine("[SIMU] Message Received (Conn %i)", connection.id);
|
||||
#endif
|
||||
|
||||
const unsigned char* buffer = msg.GetBuffer();
|
||||
|
||||
// Set DREF
|
||||
int value[20];
|
||||
for (int i = 0; i < 20; ++i)
|
||||
{
|
||||
value[i] = buffer[5];
|
||||
}
|
||||
DataManager::Set(DREF_Pause, value, 20);
|
||||
|
||||
#if LOG_VERBOSITY > 2
|
||||
if (buffer[5] == 0)
|
||||
{
|
||||
Log::FormatLine("[SIMU] Simulation Resumed (Conn %i)", connection.id);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log::FormatLine("[SIMU] Simulation Paused (Conn %i)", connection.id);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void MessageHandlers::HandleText(Message& msg)
|
||||
{
|
||||
// Update Log
|
||||
#if LOG_VERBOSITY > 0
|
||||
Log::FormatLine("[TEXT] Message Received (Conn %i)", connection.id);
|
||||
#endif
|
||||
|
||||
std::size_t len = msg.GetSize();
|
||||
const unsigned char* buffer = msg.GetBuffer();
|
||||
|
||||
char text[256] = { 0 };
|
||||
if (len < 14)
|
||||
{
|
||||
#if LOG_VERBOSITY > 1
|
||||
Log::WriteLine("[TEXT] ERROR: Length less than 14 bytes");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
size_t msgLen = (unsigned char)buffer[13];
|
||||
if (msgLen == 0)
|
||||
{
|
||||
Drawing::ClearMessage();
|
||||
#if LOG_VERBOSITY > 2
|
||||
Log::WriteLine("[TEXT] Text cleared");
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
int x = *((int*)(buffer + 5));
|
||||
int y = *((int*)(buffer + 9));
|
||||
strncpy(text, (char*)buffer + 14, msgLen);
|
||||
Drawing::SetMessage(x, y, text);
|
||||
#if LOG_VERBOSITY > 2
|
||||
Log::WriteLine("[TEXT] Text set");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void MessageHandlers::HandleWypt(Message& msg)
|
||||
{
|
||||
// Update Log
|
||||
#if LOG_VERBOSITY > 0
|
||||
Log::FormatLine("[WYPT] Message Received (Conn %i)", connection.id);
|
||||
#endif
|
||||
|
||||
// Parse data
|
||||
const unsigned char* buffer = msg.GetBuffer();
|
||||
unsigned char op = buffer[5];
|
||||
unsigned char count = buffer[6];
|
||||
Waypoint points[255];
|
||||
const unsigned char* ptr = buffer + 7;
|
||||
for (size_t i = 0; i < count; ++i)
|
||||
{
|
||||
points[i].latitude = *((float*)ptr);
|
||||
points[i].longitude = *((float*)(ptr + 4));
|
||||
points[i].altitude = *((float*)(ptr + 8));
|
||||
ptr += 12;
|
||||
}
|
||||
|
||||
// Perform operation
|
||||
#if LOG_VERBOSITY > 2
|
||||
Log::FormatLine("[WYPT] Performing operation %i", op);
|
||||
#endif
|
||||
switch (op)
|
||||
{
|
||||
case 1:
|
||||
Drawing::AddWaypoints(points, count);
|
||||
break;
|
||||
case 2:
|
||||
Drawing::RemoveWaypoints(points, count);
|
||||
break;
|
||||
case 3:
|
||||
Drawing::ClearWaypoints();
|
||||
break;
|
||||
default:
|
||||
#if LOG_VERBOSITY > 1
|
||||
Log::FormatLine("[WYPT] ERROR: %i is not a valid operation.", op);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void MessageHandlers::HandleXPlaneData(Message& msg)
|
||||
{
|
||||
#if LOG_VERBOSITY > 1
|
||||
Log::WriteLine("[MSGH] Sending raw data to X-Plane");
|
||||
#endif
|
||||
sockaddr_in loopback;
|
||||
loopback.sin_family = AF_INET;
|
||||
loopback.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
||||
loopback.sin_port = htons(49000);
|
||||
sock->SendTo(msg.GetBuffer(), msg.GetSize(), (sockaddr*)&loopback);
|
||||
}
|
||||
|
||||
void MessageHandlers::HandleUnknown(Message& msg)
|
||||
{
|
||||
// UPDATE LOG
|
||||
#if LOG_VERBOSITY > 0
|
||||
Log::FormatLine("[EXEC] ERROR: Unknown packet type %s", msg.GetHead().c_str());
|
||||
#endif
|
||||
}
|
||||
}
|
||||
68
xpcPlugin/MessageHandlers.h
Normal file
68
xpcPlugin/MessageHandlers.h
Normal file
@@ -0,0 +1,68 @@
|
||||
//Copyright (c) 2013-2015 United States Government as represented by the Administrator of the
|
||||
//National Aeronautics and Space Administration. All Rights Reserved.
|
||||
#ifndef XPC_MESSAGEHANDLERS_H
|
||||
#define XPC_MESSAGEHANDLERS_H
|
||||
#include "Message.h"
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
namespace XPC
|
||||
{
|
||||
/// A function that handles a message.
|
||||
typedef void(*MessageHandler)(Message&);
|
||||
|
||||
/// Handles incommming messages and manages connections.
|
||||
///
|
||||
/// \author Jason Watkins
|
||||
/// \version 1.0
|
||||
/// \since 1.0
|
||||
/// \date Intial Version: 2015-04-12
|
||||
/// \date Last Updated: 2015-04-12
|
||||
class MessageHandlers
|
||||
{
|
||||
public:
|
||||
/// The first stop for all messages to the plugin after they are read from the
|
||||
/// socket.
|
||||
///
|
||||
/// \details After a message is read, HandleMessage analyzes the sender's network address
|
||||
/// to determine whether the sender is a new client. It then either loads
|
||||
/// connection details for an existing client, or creates a new connection record
|
||||
/// for new clients. Finally, the message handler checks the message type and
|
||||
/// dispatches the message to the appropriate handler.
|
||||
/// \param msg The message to be processed.
|
||||
static void HandleMessage(Message& msg);
|
||||
|
||||
/// Sets the socke that message handlers use to send responses.
|
||||
static void SetSocket(UDPSocket* socket);
|
||||
|
||||
private:
|
||||
static void HandleConn(Message& msg);
|
||||
static void HandleCtrl(Message& msg);
|
||||
static void HandleData(Message& msg);
|
||||
static void HandleDref(Message& msg);
|
||||
static void HandleGetD(Message& msg);
|
||||
static void HandlePosi(Message& msg);
|
||||
static void HandleSimu(Message& msg);
|
||||
static void HandleText(Message& msg);
|
||||
static void HandleWypt(Message& msg);
|
||||
static void HandleXPlaneData(Message& msg);
|
||||
static void HandleUnknown(Message& msg);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned char id;
|
||||
sockaddr addr;
|
||||
unsigned char getdCount;
|
||||
std::string getdRequest[255];
|
||||
} ConnectionInfo;
|
||||
|
||||
static std::map<std::string, ConnectionInfo> connections;
|
||||
static std::map<std::string, MessageHandler> handlers;
|
||||
static std::string connectionKey; // The current connection ip:port string
|
||||
static ConnectionInfo connection; // The current connection record
|
||||
static UDPSocket* sock; // Outgoing network socket
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
184
xpcPlugin/UDPSocket.cpp
Normal file
184
xpcPlugin/UDPSocket.cpp
Normal file
@@ -0,0 +1,184 @@
|
||||
//Copyright (c) 2013-2015 United States Government as represented by the Administrator of the
|
||||
//National Aeronautics and Space Administration. All Rights Reserved.
|
||||
#include "Log.h"
|
||||
#include "UDPSocket.h"
|
||||
|
||||
#include <cstring>
|
||||
#include <cstdio>
|
||||
|
||||
namespace XPC
|
||||
{
|
||||
UDPSocket::UDPSocket(unsigned short recvPort)
|
||||
{
|
||||
#if LOG_VERBOSITY > 1
|
||||
Log::FormatLine("[SOCK] Opening socket (port:%d)", recvPort);
|
||||
#endif
|
||||
// Setup Port
|
||||
struct sockaddr_in localAddr;
|
||||
localAddr.sin_family = AF_INET;
|
||||
localAddr.sin_addr.s_addr = INADDR_ANY;
|
||||
localAddr.sin_port = htons(recvPort);
|
||||
|
||||
//Create and bind the socket
|
||||
#ifdef _WIN32
|
||||
WSADATA wsa;
|
||||
int startResult = WSAStartup(MAKEWORD(2, 2), &wsa);
|
||||
if (startResult != 0)
|
||||
{
|
||||
#if LOG_VERBOSITY > 0
|
||||
Log::FormatLine("[SOCK] ERROR: WSAStartup failed with error code %i.", startResult);
|
||||
#endif
|
||||
this->sock = ~0;
|
||||
return;
|
||||
}
|
||||
if ((this->sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET)
|
||||
{
|
||||
#if LOG_VERBOSITY > 0
|
||||
int err = WSAGetLastError();
|
||||
Log::FormatLine("[SOCK] ERROR: Failed to open socket. (Error code %i)", err);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
#elif (__APPLE__ || __linux)
|
||||
if ((this->sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
|
||||
{
|
||||
Log::WriteLine("[SOCK] ERROR: Failed to open socket");
|
||||
return;
|
||||
}
|
||||
int optval = 1;
|
||||
setsockopt(this->sock, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
|
||||
setsockopt(this->sock, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof(optval));
|
||||
#endif
|
||||
if (bind(this->sock, (struct sockaddr*)&localAddr, sizeof(localAddr)) != 0)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
#if LOG_VERBOSITY > 0
|
||||
int err = WSAGetLastError();
|
||||
Log::FormatLine("[SOCK] ERROR: Failed to bind socket. (Error code %i)", err);
|
||||
#endif
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
//Set Timout
|
||||
int usTimeOut = 500;
|
||||
|
||||
#ifdef _WIN32
|
||||
DWORD msTimeOutWin = 1; // Minimum socket timeout in Windows is 1ms
|
||||
if(setsockopt(this->sock, SOL_SOCKET, SO_RCVTIMEO, (char *)&msTimeOutWin, sizeof(msTimeOutWin)) != 0)
|
||||
{
|
||||
#if LOG_VERBOSITY > 1
|
||||
int err = WSAGetLastError();
|
||||
Log::FormatLine("[SOCK] ERROR: Failed to set timeout. (Error code %i)", err);
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
struct timeval tv;
|
||||
tv.tv_sec = 0; /* Sec Timeout */
|
||||
tv.tv_usec = usTimeOut; // Microsec Timeout
|
||||
setsockopt(this->sock, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(struct timeval));
|
||||
#endif
|
||||
}
|
||||
|
||||
UDPSocket::~UDPSocket()
|
||||
{
|
||||
#if LOG_VERBOSITY > 1
|
||||
Log::FormatLine("[SOCK] Closing socket (%d)", this->sock);
|
||||
#endif
|
||||
#ifdef _WIN32
|
||||
closesocket(this->sock);
|
||||
#elif (__APPLE__ || __linux)
|
||||
close(this->sock);
|
||||
#endif
|
||||
}
|
||||
|
||||
int UDPSocket::Read(unsigned char* dst, int maxLen, sockaddr* recvAddr)
|
||||
{
|
||||
socklen_t recvaddrlen = sizeof(*recvAddr);
|
||||
int status = 0;
|
||||
|
||||
#ifdef _WIN32
|
||||
// Windows readUDP needs the select command- minimum timeout is 1ms.
|
||||
// Without this playback becomes choppy
|
||||
|
||||
// Definitions
|
||||
FD_SET stReadFDS;
|
||||
FD_SET stExceptFDS;
|
||||
timeval tv;
|
||||
|
||||
// Setup for Select
|
||||
FD_ZERO(&stReadFDS);
|
||||
FD_SET(sock, &stReadFDS);
|
||||
FD_ZERO(&stExceptFDS);
|
||||
FD_SET(sock, &stExceptFDS);
|
||||
tv.tv_sec = 0; /* Sec Timeout */
|
||||
tv.tv_usec = 250; // Microsec Timeout
|
||||
|
||||
// Select Command
|
||||
int result = select(-1, &stReadFDS, (FD_SET *)0, &stExceptFDS, &tv);
|
||||
#if LOG_VERBOSITY > 1
|
||||
if (result == SOCKET_ERROR)
|
||||
{
|
||||
int err = WSAGetLastError();
|
||||
Log::FormatLine("[SOCK] ERROR: Select failed. (Error code %i)", err);
|
||||
}
|
||||
#endif
|
||||
if (result <= 0) // No Data or error
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
// If no error: Read Data
|
||||
status = recvfrom(sock, (char*)dst, maxLen, 0, recvAddr, &recvaddrlen);
|
||||
#else
|
||||
// For apple or linux-just read - will timeout in 0.5 ms
|
||||
status = (int)recvfrom(sock, dst, 5000, 0, recvAddr, &recvaddrlen);
|
||||
#endif
|
||||
return status;
|
||||
}
|
||||
|
||||
void UDPSocket::SendTo(const unsigned char* buffer, std::size_t len, sockaddr* remote)
|
||||
{
|
||||
if (sendto(sock, (char*)buffer, (int)len, 0, remote, sizeof(*remote)) < 0)
|
||||
{
|
||||
#if LOG_VERBOSITY > 0
|
||||
Log::FormatLine("[SOCK] Send failed. (remote: %s)", GetHost(remote).c_str());
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#if LOG_VERBOSITY > 3
|
||||
Log::FormatLine("[SOCK] Datagram sent. (remote: %s)", GetHost(remote).c_str());
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
std::string UDPSocket::GetHost(sockaddr* sa)
|
||||
{
|
||||
char ip[INET6_ADDRSTRLEN + 6] = { 0 };
|
||||
switch (sa->sa_family)
|
||||
{
|
||||
case AF_INET:
|
||||
{
|
||||
sockaddr_in* sin = reinterpret_cast<sockaddr_in*>(sa);
|
||||
inet_ntop(AF_INET, &sin->sin_addr, ip, INET6_ADDRSTRLEN);
|
||||
int len = strnlen(ip, INET6_ADDRSTRLEN);
|
||||
ip[len++] = ':';
|
||||
std::sprintf(ip + len, "%u", ntohs((*sin).sin_port));
|
||||
break;
|
||||
}
|
||||
case AF_INET6:
|
||||
{
|
||||
sockaddr_in6* sin = reinterpret_cast<sockaddr_in6*>(sa);
|
||||
inet_ntop(AF_INET6, &sin->sin6_addr, ip, INET6_ADDRSTRLEN);
|
||||
int len = strnlen(ip, INET6_ADDRSTRLEN);
|
||||
ip[len++] = ':';
|
||||
std::sprintf(ip + len, "%u", ntohs((*sin).sin6_port));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return "UNKNOWN";
|
||||
}
|
||||
return std::string(ip);
|
||||
}
|
||||
}
|
||||
74
xpcPlugin/UDPSocket.h
Normal file
74
xpcPlugin/UDPSocket.h
Normal file
@@ -0,0 +1,74 @@
|
||||
//Copyright (c) 2013-2015 United States Government as represented by the Administrator of the
|
||||
//National Aeronautics and Space Administration. All Rights Reserved.
|
||||
#ifndef XPC_SOCKET_H
|
||||
#define XPC_SOCKET_H
|
||||
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
#ifdef _WIN32
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#pragma comment(lib,"ws2_32.lib") //Winsock Library
|
||||
#elif (__APPLE__ || __linux)
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
|
||||
namespace XPC
|
||||
{
|
||||
/// Represents a UDP datagram socket used for reading data from and sending
|
||||
/// data to XPC clients.
|
||||
///
|
||||
/// \author Jason Watkins
|
||||
/// \version 1.0
|
||||
/// \since 1.0
|
||||
/// \date Intial Version: 2015-04-10
|
||||
/// \date Last Updated: 2015-04-11
|
||||
class UDPSocket
|
||||
{
|
||||
public:
|
||||
/// Initializes a new instance of the XPCSocket class bound to the
|
||||
/// specified receive port.
|
||||
///
|
||||
/// \param recvPort The port on which this instance will receive data.
|
||||
UDPSocket(unsigned short recvPort);
|
||||
|
||||
/// Closes the underlying socket for this instance.
|
||||
~UDPSocket();
|
||||
|
||||
/// Reads the specified number of bytes into the data buffer and stores
|
||||
/// the remote endpoint.
|
||||
///
|
||||
/// \param buffer The array to copy the data into.
|
||||
/// \param size The number of bytes to read.
|
||||
/// \param remoteAddr When at least one byte is read, contains the address
|
||||
/// of the remote host.
|
||||
/// \returns The number of bytes read, or a negative number if
|
||||
/// an error occurs.
|
||||
int Read(unsigned char* buffer, int size, sockaddr* remoteAddr);
|
||||
|
||||
/// Sends data to the specified remote endpoint.
|
||||
///
|
||||
/// \param data The data to be sent.
|
||||
/// \param len The number of bytes to send.
|
||||
/// \param remote The destination socket.
|
||||
void SendTo(const unsigned char* buffer, std::size_t len, sockaddr* remote);
|
||||
|
||||
/// Gets a string containing the IP address and port contained in the given sockaddr.
|
||||
///
|
||||
/// \param addr The socket address to parse.
|
||||
/// \returns A string representation of the socket address.
|
||||
static std::string GetHost(sockaddr* addr);
|
||||
private:
|
||||
#ifdef _WIN32
|
||||
SOCKET sock;
|
||||
#else
|
||||
int sock;
|
||||
#endif
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
BIN
xpcPlugin/XPlaneConnect/64/lin.xpl
Executable file
BIN
xpcPlugin/XPlaneConnect/64/lin.xpl
Executable file
Binary file not shown.
Binary file not shown.
BIN
xpcPlugin/XPlaneConnect/lin.xpl
Executable file
BIN
xpcPlugin/XPlaneConnect/lin.xpl
Executable file
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,268 +0,0 @@
|
||||
#include "xpcDrawing.h"
|
||||
#include "XPLMDisplay.h"
|
||||
#include "XPLMGraphics.h"
|
||||
#include "XPLMDataAccess.h"
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
//OpenGL includes
|
||||
#if IBM
|
||||
#include <windows.h>
|
||||
#endif
|
||||
#if __GNUC__
|
||||
#include <OpenGL/gl.h>
|
||||
#else
|
||||
#include <GL/gl.h>
|
||||
#endif
|
||||
|
||||
//Internal Structures
|
||||
typedef struct
|
||||
{
|
||||
double x;
|
||||
double y;
|
||||
double z;
|
||||
} LocalPoint;
|
||||
|
||||
//Internal Memory
|
||||
static const size_t MSG_MAX = 1024;
|
||||
static const size_t MSG_LINE_MAX = MSG_MAX / 16;
|
||||
static bool msgEnabled = false;
|
||||
static int msgX = -1;
|
||||
static int msgY = -1;
|
||||
static char msgVal[MSG_MAX] = { 0 };
|
||||
static size_t newLineCount = 0;
|
||||
static size_t newLines[MSG_LINE_MAX] = { 0 };
|
||||
static float rgb[3] = { 0.25F, 1.0F, 0.25F };
|
||||
|
||||
static const size_t WAYPOINT_MAX = 128;
|
||||
static bool routeEnabled = false;
|
||||
static size_t numWaypoints = 0;
|
||||
static Waypoint waypoints[WAYPOINT_MAX];
|
||||
static LocalPoint localPoints[WAYPOINT_MAX];
|
||||
|
||||
XPLMDataRef planeXref;
|
||||
XPLMDataRef planeYref;
|
||||
XPLMDataRef planeZref;
|
||||
|
||||
//Internal Functions
|
||||
int cmp(const void * a, const void * b)
|
||||
{
|
||||
return (*(size_t*)a - *(size_t*)b);
|
||||
}
|
||||
|
||||
static void gl_drawCube(float x, float y, float z, float d)
|
||||
{
|
||||
//tan(0.25) degrees. Should scale all markers to appear about the same size
|
||||
const float TAN = 0.00436335082070156648652885284203;
|
||||
float h = d * TAN;
|
||||
|
||||
glBegin(GL_QUAD_STRIP);
|
||||
//Top
|
||||
glVertex3f(x - h, y + h, z - h);
|
||||
glVertex3f(x + h, y + h, z - h);
|
||||
glVertex3f(x - h, y + h, z + h);
|
||||
glVertex3f(x + h, y + h, z + h);
|
||||
//Front
|
||||
glVertex3f(x - h, y - h, z + h);
|
||||
glVertex3f(x + h, y - h, z + h);
|
||||
//Bottom
|
||||
glVertex3f(x - h, y - h, z - h);
|
||||
glVertex3f(x + h, y - h, z - h);
|
||||
//Back
|
||||
glVertex3f(x - h, y + h, z - h);
|
||||
glVertex3f(x + h, y + h, z - h);
|
||||
|
||||
glEnd();
|
||||
glBegin(GL_QUADS);
|
||||
//Left
|
||||
glVertex3f(x - h, y + h, z - h);
|
||||
glVertex3f(x - h, y + h, z + h);
|
||||
glVertex3f(x - h, y - h, z + h);
|
||||
glVertex3f(x - h, y - h, z - h);
|
||||
//Right
|
||||
glVertex3f(x + h, y + h, z + h);
|
||||
glVertex3f(x + h, y + h, z - h);
|
||||
glVertex3f(x + h, y - h, z - h);
|
||||
glVertex3f(x + h, y - h, z + h);
|
||||
|
||||
glEnd();
|
||||
}
|
||||
|
||||
static int MessageDrawCallback(XPLMDrawingPhase inPhase, int inIsBefore, void * inRefcon)
|
||||
{
|
||||
XPLMDrawString(rgb, msgX, msgY, msgVal, NULL, xplmFont_Basic);
|
||||
int y = msgY - 16;
|
||||
for (size_t i = 0; i < newLineCount; ++i)
|
||||
{
|
||||
XPLMDrawString(rgb, msgX, y, msgVal + newLines[i], NULL, xplmFont_Basic);
|
||||
y -= 16;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int RouteDrawCallback(XPLMDrawingPhase inPhase, int inIsBefore, void * inRefcon)
|
||||
{
|
||||
float px = XPLMGetDataf(planeXref);
|
||||
float py = XPLMGetDataf(planeYref);
|
||||
float pz = XPLMGetDataf(planeZref);
|
||||
|
||||
Waypoint* g;
|
||||
LocalPoint* l;
|
||||
//Convert to local
|
||||
for (size_t i = 0; i < numWaypoints; ++i)
|
||||
{
|
||||
g = &waypoints[i];
|
||||
l = &localPoints[i];
|
||||
XPLMWorldToLocal(g->latitude, g->longitude, g->altitude,
|
||||
&l->x, &l->y, &l->z);
|
||||
}
|
||||
|
||||
|
||||
//Draw posts
|
||||
glColor3f(1.0F, 1.0F, 1.0F);
|
||||
glBegin(GL_LINES);
|
||||
for (size_t i = 0; i < numWaypoints; ++i)
|
||||
{
|
||||
l = &localPoints[i];
|
||||
glVertex3f((float)l->x, (float)l->y, (float)l->z);
|
||||
glVertex3f((float)l->x, -1000.0F, (float)l->z);
|
||||
}
|
||||
glEnd();
|
||||
|
||||
//Draw route
|
||||
glColor3f(1.0F, 0.0F, 0.0F);
|
||||
glBegin(GL_LINE_STRIP);
|
||||
for (size_t i = 0; i < numWaypoints; ++i)
|
||||
{
|
||||
l = &localPoints[i];
|
||||
glVertex3f((float)l->x, (float)l->y, (float)l->z);
|
||||
}
|
||||
glEnd();
|
||||
|
||||
//Draw markers
|
||||
glColor3f(1.0F, 1.0F, 1.0F);
|
||||
for (size_t i = 0; i < numWaypoints; ++i)
|
||||
{
|
||||
l = &localPoints[i];
|
||||
float xoff = (float)l->x - px;
|
||||
float yoff = (float)l->y - py;
|
||||
float zoff = (float)l->z - pz;
|
||||
float d = sqrtf(xoff*xoff + yoff*yoff + zoff*zoff);
|
||||
gl_drawCube((float)l->x, (float)l->y, (float)l->z, d);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
//Public Functions
|
||||
void XPCClearMessage()
|
||||
{
|
||||
XPLMUnregisterDrawCallback(MessageDrawCallback, xplm_Phase_Window, 0, NULL);
|
||||
msgEnabled = false;
|
||||
}
|
||||
|
||||
void XPCSetMessage(int x, int y, char* msg)
|
||||
{
|
||||
//Determine size of message and clear instead if the message string
|
||||
//is empty.
|
||||
size_t len = strnlen(msg, MSG_MAX);
|
||||
if (len == 0)
|
||||
{
|
||||
XPCClearMessage();
|
||||
return;
|
||||
}
|
||||
|
||||
//Set the message, location, and mark new lines.
|
||||
strncpy(msgVal, msg, len);
|
||||
newLineCount = 0;
|
||||
for (size_t i = 0; i < len && newLineCount < MSG_LINE_MAX; ++i)
|
||||
{
|
||||
if (msgVal[i] == '\n' || msgVal[i] == '\r')
|
||||
{
|
||||
msgVal[i] = 0;
|
||||
newLines[newLineCount++] = i + 1;
|
||||
}
|
||||
}
|
||||
msgX = x < 0 ? 10 : x;
|
||||
msgY = y < 0 ? 600 : y;
|
||||
|
||||
//Enable drawing if necessary
|
||||
if (!msgEnabled)
|
||||
{
|
||||
XPLMRegisterDrawCallback(MessageDrawCallback, xplm_Phase_LastCockpit, 0, NULL);
|
||||
msgEnabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
void XPCClearWaypoints()
|
||||
{
|
||||
numWaypoints = 0;
|
||||
if (routeEnabled)
|
||||
{
|
||||
XPLMUnregisterDrawCallback(RouteDrawCallback, xplm_Phase_Objects, 0, NULL);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void XPCAddWaypoints(Waypoint points[], size_t numPoints)
|
||||
{
|
||||
if (numWaypoints + numPoints > WAYPOINT_MAX)
|
||||
{
|
||||
numPoints = WAYPOINT_MAX - numWaypoints;
|
||||
}
|
||||
size_t finalNumWaypoints = numPoints + numWaypoints;
|
||||
for (size_t i = 0; i < numPoints; ++i)
|
||||
{
|
||||
waypoints[numWaypoints + i] = points[i];
|
||||
}
|
||||
numWaypoints = finalNumWaypoints;
|
||||
|
||||
if (!routeEnabled)
|
||||
{
|
||||
XPLMRegisterDrawCallback(RouteDrawCallback, xplm_Phase_Objects, 0, NULL);
|
||||
}
|
||||
if (!planeXref)
|
||||
{
|
||||
planeXref = XPLMFindDataRef("sim/flightmodel/position/local_x");
|
||||
planeYref = XPLMFindDataRef("sim/flightmodel/position/local_y");
|
||||
planeZref = XPLMFindDataRef("sim/flightmodel/position/local_z");
|
||||
}
|
||||
}
|
||||
|
||||
void XPCRemoveWaypoints(Waypoint points[], size_t numPoints)
|
||||
{
|
||||
//Build a list of indices of waypoints we should delete.
|
||||
size_t delPoints[WAYPOINT_MAX];
|
||||
size_t delPointsCur = 0;
|
||||
for (size_t i = 0; i < numPoints; ++i)
|
||||
{
|
||||
Waypoint p = points[i];
|
||||
for (size_t j = 0; j < numWaypoints; ++j)
|
||||
{
|
||||
Waypoint q = waypoints[j];
|
||||
if (p.latitude == q.latitude &&
|
||||
p.longitude == q.longitude &&
|
||||
p.altitude == q.altitude)
|
||||
{
|
||||
delPoints[delPointsCur++] = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
//Sort the indices so that we only have to iterate them once
|
||||
qsort(delPoints, delPointsCur, sizeof(size_t), cmp);
|
||||
|
||||
//Copy the new array on top of the old array
|
||||
size_t copyCur = 0;
|
||||
size_t count = delPointsCur;
|
||||
delPointsCur = 0;
|
||||
for (size_t i = 0; i < numWaypoints; ++i)
|
||||
{
|
||||
if (i == delPoints[delPointsCur])
|
||||
{
|
||||
++delPointsCur;
|
||||
continue;
|
||||
}
|
||||
waypoints[copyCur++] = waypoints[i];
|
||||
}
|
||||
numWaypoints -= count;
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
#ifndef xpcDrawing_h
|
||||
#define xpcDrawing_h
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "xplaneConnect.h"
|
||||
|
||||
void XPCClearMessage();
|
||||
|
||||
void XPCSetMessage(int x, int y, char* msg);
|
||||
|
||||
void XPCClearWaypoints();
|
||||
|
||||
void XPCAddWaypoints(Waypoint points[], size_t numPoints);
|
||||
|
||||
void XPCRemoveWaypoints(Waypoint points[], size_t numPoints);
|
||||
|
||||
#endif
|
||||
@@ -8,10 +8,15 @@
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
BE37D960187C8B0F0033B082 /* XPCPlugin.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BE37D95E187C8B0F0033B082 /* XPCPlugin.cpp */; };
|
||||
BE5F2FF118FCA1D500AFCD17 /* xpcPluginTools.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BE5F2FF018FCA1D500AFCD17 /* xpcPluginTools.cpp */; };
|
||||
BE8361EF18C5591C00E9C923 /* mac.xpl in CopyFiles */ = {isa = PBXBuildFile; fileRef = D607B19909A556E400699BC3 /* mac.xpl */; };
|
||||
BEABAD371AE041A3007BA7DA /* DataManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BEABAD2B1AE041A3007BA7DA /* DataManager.cpp */; };
|
||||
BEABAD381AE041A3007BA7DA /* DataMaps.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BEABAD2D1AE041A3007BA7DA /* DataMaps.cpp */; };
|
||||
BEABAD391AE041A3007BA7DA /* Drawing.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BEABAD2F1AE041A3007BA7DA /* Drawing.cpp */; };
|
||||
BEABAD3A1AE041A3007BA7DA /* Log.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BEABAD311AE041A3007BA7DA /* Log.cpp */; };
|
||||
BEABAD3B1AE041A3007BA7DA /* Message.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BEABAD331AE041A3007BA7DA /* Message.cpp */; };
|
||||
BEABAD3C1AE041A3007BA7DA /* MessageHandlers.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BEABAD351AE041A3007BA7DA /* MessageHandlers.cpp */; };
|
||||
BEABAD3F1AE0498D007BA7DA /* UDPSocket.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BEABAD3D1AE0498D007BA7DA /* UDPSocket.cpp */; };
|
||||
BEDC620418EDF1A7005DB364 /* xplaneConnect.c in Sources */ = {isa = PBXBuildFile; fileRef = BEDC620218EDF1A7005DB364 /* xplaneConnect.c */; };
|
||||
BEFBC0CB1AD4A0290025705B /* xpcDrawing.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BEFBC0C91AD4A0290025705B /* xpcDrawing.cpp */; };
|
||||
D6A7BDAA16A1DEA200D1426A /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D6A7BDA916A1DEA200D1426A /* OpenGL.framework */; };
|
||||
D6A7BDC116A1DEC000D1426A /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D6A7BDC016A1DEC000D1426A /* CoreFoundation.framework */; };
|
||||
D6A7BDF116A1DED200D1426A /* XPLM.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D6A7BDF016A1DED200D1426A /* XPLM.framework */; };
|
||||
@@ -33,13 +38,22 @@
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
BE37D95E187C8B0F0033B082 /* XPCPlugin.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = XPCPlugin.cpp; sourceTree = SOURCE_ROOT; usesTabs = 1; };
|
||||
BE3C039719DF043D0063D8DD /* Readme.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = Readme.txt; path = ../Readme.txt; sourceTree = "<group>"; };
|
||||
BE5F2FEF18FCA13700AFCD17 /* xpcPluginTools.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = xpcPluginTools.h; sourceTree = "<group>"; };
|
||||
BE5F2FF018FCA1D500AFCD17 /* xpcPluginTools.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = xpcPluginTools.cpp; sourceTree = "<group>"; };
|
||||
BEABAD2B1AE041A3007BA7DA /* DataManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DataManager.cpp; sourceTree = "<group>"; };
|
||||
BEABAD2C1AE041A3007BA7DA /* DataManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DataManager.h; sourceTree = "<group>"; };
|
||||
BEABAD2D1AE041A3007BA7DA /* DataMaps.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DataMaps.cpp; sourceTree = "<group>"; };
|
||||
BEABAD2E1AE041A3007BA7DA /* DataMaps.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DataMaps.h; sourceTree = "<group>"; };
|
||||
BEABAD2F1AE041A3007BA7DA /* Drawing.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Drawing.cpp; sourceTree = "<group>"; };
|
||||
BEABAD301AE041A3007BA7DA /* Drawing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Drawing.h; sourceTree = "<group>"; };
|
||||
BEABAD311AE041A3007BA7DA /* Log.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Log.cpp; sourceTree = "<group>"; };
|
||||
BEABAD321AE041A3007BA7DA /* Log.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Log.h; sourceTree = "<group>"; };
|
||||
BEABAD331AE041A3007BA7DA /* Message.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Message.cpp; sourceTree = "<group>"; };
|
||||
BEABAD341AE041A3007BA7DA /* Message.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Message.h; sourceTree = "<group>"; };
|
||||
BEABAD351AE041A3007BA7DA /* MessageHandlers.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MessageHandlers.cpp; sourceTree = "<group>"; };
|
||||
BEABAD361AE041A3007BA7DA /* MessageHandlers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MessageHandlers.h; sourceTree = "<group>"; };
|
||||
BEABAD3D1AE0498D007BA7DA /* UDPSocket.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = UDPSocket.cpp; sourceTree = "<group>"; };
|
||||
BEABAD3E1AE0498D007BA7DA /* UDPSocket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UDPSocket.h; sourceTree = "<group>"; };
|
||||
BEDC620218EDF1A7005DB364 /* xplaneConnect.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = xplaneConnect.c; path = ../C/src/xplaneConnect.c; sourceTree = "<group>"; };
|
||||
BEDC620318EDF1A7005DB364 /* xplaneConnect.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = xplaneConnect.h; path = ../C/src/xplaneConnect.h; sourceTree = "<group>"; };
|
||||
BEFBC0C91AD4A0290025705B /* xpcDrawing.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = xpcDrawing.cpp; sourceTree = "<group>"; };
|
||||
BEFBC0CA1AD4A0290025705B /* xpcDrawing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = xpcDrawing.h; sourceTree = "<group>"; };
|
||||
D607B19909A556E400699BC3 /* mac.xpl */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = mac.xpl; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
D6A7BDA916A1DEA200D1426A /* OpenGL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGL.framework; path = System/Library/Frameworks/OpenGL.framework; sourceTree = SDKROOT; };
|
||||
D6A7BDC016A1DEC000D1426A /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = System/Library/Frameworks/CoreFoundation.framework; sourceTree = SDKROOT; };
|
||||
@@ -62,26 +76,43 @@
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
AC4E46B809C2E0B3006B7E1B /* C Source */ = {
|
||||
AC4E46B809C2E0B3006B7E1B /* src */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
BE37D95E187C8B0F0033B082 /* XPCPlugin.cpp */,
|
||||
BEDC620218EDF1A7005DB364 /* xplaneConnect.c */,
|
||||
BEDC620318EDF1A7005DB364 /* xplaneConnect.h */,
|
||||
BE5F2FF018FCA1D500AFCD17 /* xpcPluginTools.cpp */,
|
||||
BE5F2FEF18FCA13700AFCD17 /* xpcPluginTools.h */,
|
||||
BEFBC0C91AD4A0290025705B /* xpcDrawing.cpp */,
|
||||
BEFBC0CA1AD4A0290025705B /* xpcDrawing.h */,
|
||||
BEABAD2B1AE041A3007BA7DA /* DataManager.cpp */,
|
||||
BEABAD2D1AE041A3007BA7DA /* DataMaps.cpp */,
|
||||
BEABAD2F1AE041A3007BA7DA /* Drawing.cpp */,
|
||||
BEABAD311AE041A3007BA7DA /* Log.cpp */,
|
||||
BEABAD331AE041A3007BA7DA /* Message.cpp */,
|
||||
BEABAD351AE041A3007BA7DA /* MessageHandlers.cpp */,
|
||||
BEABAD3D1AE0498D007BA7DA /* UDPSocket.cpp */,
|
||||
);
|
||||
name = "C Source";
|
||||
name = src;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
BE953E0B1AEB183400CE4A8C /* inc */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
BEDC620318EDF1A7005DB364 /* xplaneConnect.h */,
|
||||
BEABAD2C1AE041A3007BA7DA /* DataManager.h */,
|
||||
BEABAD2E1AE041A3007BA7DA /* DataMaps.h */,
|
||||
BEABAD301AE041A3007BA7DA /* Drawing.h */,
|
||||
BEABAD321AE041A3007BA7DA /* Log.h */,
|
||||
BEABAD341AE041A3007BA7DA /* Message.h */,
|
||||
BEABAD361AE041A3007BA7DA /* MessageHandlers.h */,
|
||||
BEABAD3E1AE0498D007BA7DA /* UDPSocket.h */,
|
||||
);
|
||||
name = inc;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D607B15F09A5563000699BC3 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
BE3C039719DF043D0063D8DD /* Readme.txt */,
|
||||
D6A7BDAD16A1DEA700D1426A /* Frameworks */,
|
||||
AC4E46B809C2E0B3006B7E1B /* C Source */,
|
||||
AC4E46B809C2E0B3006B7E1B /* src */,
|
||||
BE953E0B1AEB183400CE4A8C /* inc */,
|
||||
D607B19A09A556E400699BC3 /* Products */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
@@ -158,10 +189,15 @@
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
BEABAD3A1AE041A3007BA7DA /* Log.cpp in Sources */,
|
||||
BEABAD3B1AE041A3007BA7DA /* Message.cpp in Sources */,
|
||||
BEABAD3C1AE041A3007BA7DA /* MessageHandlers.cpp in Sources */,
|
||||
BEABAD381AE041A3007BA7DA /* DataMaps.cpp in Sources */,
|
||||
BEDC620418EDF1A7005DB364 /* xplaneConnect.c in Sources */,
|
||||
BEABAD371AE041A3007BA7DA /* DataManager.cpp in Sources */,
|
||||
BEABAD391AE041A3007BA7DA /* Drawing.cpp in Sources */,
|
||||
BE37D960187C8B0F0033B082 /* XPCPlugin.cpp in Sources */,
|
||||
BEFBC0CB1AD4A0290025705B /* xpcDrawing.cpp in Sources */,
|
||||
BE5F2FF118FCA1D500AFCD17 /* xpcPluginTools.cpp in Sources */,
|
||||
BEABAD3F1AE0498D007BA7DA /* UDPSocket.cpp in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -171,6 +207,9 @@
|
||||
D607B16309A5563100699BC3 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "c++98";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CONFIGURATION_BUILD_DIR = ./XPlaneConnect;
|
||||
DYLIB_COMPATIBILITY_VERSION = "";
|
||||
DYLIB_CURRENT_VERSION = "";
|
||||
@@ -189,7 +228,7 @@
|
||||
"$(HEADER_SEARCH_PATHS)",
|
||||
);
|
||||
MACH_O_TYPE = mh_bundle;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.6;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.7;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
OTHER_LDFLAGS = (
|
||||
"$(OTHER_LDFLAGS)",
|
||||
@@ -208,7 +247,7 @@
|
||||
PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = YES;
|
||||
PRODUCT_NAME = "${TARGET_NAME}";
|
||||
SCAN_ALL_SOURCE_FILES_FOR_INCLUDES = NO;
|
||||
SDKROOT = macosx10.8;
|
||||
SDKROOT = macosx;
|
||||
SYMROOT = build;
|
||||
XPSDK_ROOT = SDK;
|
||||
};
|
||||
@@ -217,7 +256,10 @@
|
||||
D607B16409A5563100699BC3 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CONFIGURATION_BUILD_DIR = ./Mac;
|
||||
ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "c++98";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CONFIGURATION_BUILD_DIR = ./XPlaneConnect;
|
||||
DYLIB_COMPATIBILITY_VERSION = "";
|
||||
DYLIB_CURRENT_VERSION = "";
|
||||
EXECUTABLE_EXTENSION = xpl;
|
||||
@@ -235,7 +277,7 @@
|
||||
"$(HEADER_SEARCH_PATHS)",
|
||||
);
|
||||
MACH_O_TYPE = mh_bundle;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.6;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.7;
|
||||
OTHER_LDFLAGS = (
|
||||
"$(OTHER_LDFLAGS)",
|
||||
"-Wl,-exported_symbol",
|
||||
@@ -253,7 +295,7 @@
|
||||
PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = YES;
|
||||
PRODUCT_NAME = "${TARGET_NAME}";
|
||||
SCAN_ALL_SOURCE_FILES_FOR_INCLUDES = NO;
|
||||
SDKROOT = macosx10.8;
|
||||
SDKROOT = macosx;
|
||||
SYMROOT = build;
|
||||
XPSDK_ROOT = SDK;
|
||||
};
|
||||
@@ -291,6 +333,7 @@
|
||||
);
|
||||
MACH_O_TYPE = mh_bundle;
|
||||
PRODUCT_NAME = mac;
|
||||
SDKROOT = macosx;
|
||||
STRIP_INSTALLED_PRODUCT = YES;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
VERSION_INFO_PREFIX = XPC;
|
||||
@@ -328,7 +371,9 @@
|
||||
"$(USER_LIBRARY_DIR)/Developer/Xcode/DerivedData/xplaneConnect-asdjuezcjkhojuewbyxhyhabxfwc/Build/Products/Debug",
|
||||
);
|
||||
MACH_O_TYPE = mh_bundle;
|
||||
ONLY_ACTIVE_ARCH = NO;
|
||||
PRODUCT_NAME = mac;
|
||||
SDKROOT = macosx;
|
||||
STRIP_INSTALLED_PRODUCT = YES;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
VERSION_INFO_PREFIX = XPC;
|
||||
|
||||
@@ -9,12 +9,18 @@ Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Win32 = Debug|Win32
|
||||
Debug|x64 = Debug|x64
|
||||
Release|Win32 = Release|Win32
|
||||
Release|x64 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{6AEF5D28-2701-44FF-AE10-1DEF07C5CAEA}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{6AEF5D28-2701-44FF-AE10-1DEF07C5CAEA}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{6AEF5D28-2701-44FF-AE10-1DEF07C5CAEA}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{6AEF5D28-2701-44FF-AE10-1DEF07C5CAEA}.Debug|x64.Build.0 = Debug|x64
|
||||
{6AEF5D28-2701-44FF-AE10-1DEF07C5CAEA}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{6AEF5D28-2701-44FF-AE10-1DEF07C5CAEA}.Release|Win32.Build.0 = Release|Win32
|
||||
{6AEF5D28-2701-44FF-AE10-1DEF07C5CAEA}.Release|x64.ActiveCfg = Release|x64
|
||||
{6AEF5D28-2701-44FF-AE10-1DEF07C5CAEA}.Release|x64.Build.0 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
||||
@@ -9,6 +9,14 @@
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{6AEF5D28-2701-44FF-AE10-1DEF07C5CAEA}</ProjectGuid>
|
||||
@@ -22,27 +30,53 @@
|
||||
<PlatformToolset>v120</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v120</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v120</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v120</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<OutDir>..\XPlaneConnect\</OutDir>
|
||||
<TargetExt>.xpl</TargetExt>
|
||||
<IncludePath>..\xpcPlugin\SDK\CHeaders\XPLM;..\SDK\CHeaders\XPLM;..\..\C\src;$(IncludePath)</IncludePath>
|
||||
<IncludePath>..\SDK\CHeaders\XPLM;$(IncludePath)</IncludePath>
|
||||
<LibraryPath>..\xpcPlugin\SDK\Libraries\Win;$(LibraryPath)</LibraryPath>
|
||||
<TargetName>win</TargetName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<OutDir>..\XPlaneConnect\</OutDir>
|
||||
<TargetExt>.xpl</TargetExt>
|
||||
<IncludePath>..\SDK\CHeaders\XPLM;$(IncludePath)</IncludePath>
|
||||
<LibraryPath>..\xpcPlugin\SDK\Libraries\Win;$(LibraryPath)</LibraryPath>
|
||||
<TargetName>win</TargetName>
|
||||
</PropertyGroup>
|
||||
@@ -54,19 +88,28 @@
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<OutDir>..\XPlaneConnect\64\</OutDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<TargetExt>.xpl</TargetExt>
|
||||
<IncludePath>..\xpcPlugin\SDK\CHeaders\XPLM;..\SDK\CHeaders\XPLM;..\..\C\src;$(IncludePath)</IncludePath>
|
||||
<LibraryPath>..\xpcPlugin\SDK\Libraries\Win;$(LibraryPath)</LibraryPath>
|
||||
<TargetName>win</TargetName>
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<OutDir>..\XPlaneConnect\64\</OutDir>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>IBM=1;XPLM200;_DEBUG;_WINDOWS;_USRDLL;XPCPLUGIN_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>IBM=1;XPLM200;_DEBUG;_WINDOWS;_USRDLL;XPCPLUGIN_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<DebugInformationFormat>OldStyle</DebugInformationFormat>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<OmitFramePointers />
|
||||
<FunctionLevelLinking>false</FunctionLevelLinking>
|
||||
<DisableSpecificWarnings>4996</DisableSpecificWarnings>
|
||||
<DisableSpecificWarnings>
|
||||
</DisableSpecificWarnings>
|
||||
<MinimalRebuild>false</MinimalRebuild>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
@@ -74,12 +117,39 @@
|
||||
<AdditionalDependencies>Opengl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<WarningLevel>EnableAllWarnings</WarningLevel>
|
||||
<Optimization>Full</Optimization>
|
||||
<PreprocessorDefinitions>IBM=1;XPLM200;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<DebugInformationFormat>OldStyle</DebugInformationFormat>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<OmitFramePointers>
|
||||
</OmitFramePointers>
|
||||
<FunctionLevelLinking>false</FunctionLevelLinking>
|
||||
<DisableSpecificWarnings>
|
||||
</DisableSpecificWarnings>
|
||||
<MinimalRebuild>false</MinimalRebuild>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<BasicRuntimeChecks>Default</BasicRuntimeChecks>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<ExceptionHandling>false</ExceptionHandling>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>false</GenerateDebugInformation>
|
||||
<AdditionalDependencies>Opengl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>IBM=1;XPLM200;_DEBUG;_WINDOWS;_USRDLL;XPCPLUGIN_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>IBM=1;XPLM200;_DEBUG;_WINDOWS;_USRDLL;XPCPLUGIN_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<SDLCheck>
|
||||
</SDLCheck>
|
||||
<DebugInformationFormat>OldStyle</DebugInformationFormat>
|
||||
@@ -89,7 +159,7 @@
|
||||
<FunctionLevelLinking>false</FunctionLevelLinking>
|
||||
<DisableSpecificWarnings>4996</DisableSpecificWarnings>
|
||||
<MinimalRebuild>false</MinimalRebuild>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
@@ -97,16 +167,56 @@
|
||||
<AdditionalDependencies>OpenGL32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<WarningLevel>EnableAllWarnings</WarningLevel>
|
||||
<Optimization>Full</Optimization>
|
||||
<PreprocessorDefinitions>IBM=1;XPLM200;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<SDLCheck>
|
||||
</SDLCheck>
|
||||
<DebugInformationFormat>OldStyle</DebugInformationFormat>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<OmitFramePointers>
|
||||
</OmitFramePointers>
|
||||
<FunctionLevelLinking>false</FunctionLevelLinking>
|
||||
<DisableSpecificWarnings>
|
||||
</DisableSpecificWarnings>
|
||||
<MinimalRebuild>false</MinimalRebuild>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<BasicRuntimeChecks>Default</BasicRuntimeChecks>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<InlineFunctionExpansion />
|
||||
<ExceptionHandling>false</ExceptionHandling>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>false</GenerateDebugInformation>
|
||||
<AdditionalDependencies>OpenGL32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
|
||||
<GenerateMapFile>
|
||||
</GenerateMapFile>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\C\src\xplaneConnect.h" />
|
||||
<ClInclude Include="..\xpcDrawing.h" />
|
||||
<ClInclude Include="..\xpcPluginTools.h" />
|
||||
<ClInclude Include="..\DataManager.h" />
|
||||
<ClInclude Include="..\DataMaps.h" />
|
||||
<ClInclude Include="..\Drawing.h" />
|
||||
<ClInclude Include="..\Log.h" />
|
||||
<ClInclude Include="..\Message.h" />
|
||||
<ClInclude Include="..\MessageHandlers.h" />
|
||||
<ClInclude Include="..\UDPSocket.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\C\src\xplaneConnect.c" />
|
||||
<ClCompile Include="..\xpcDrawing.cpp" />
|
||||
<ClCompile Include="..\DataManager.cpp" />
|
||||
<ClCompile Include="..\DataMaps.cpp" />
|
||||
<ClCompile Include="..\Drawing.cpp" />
|
||||
<ClCompile Include="..\Log.cpp" />
|
||||
<ClCompile Include="..\Message.cpp" />
|
||||
<ClCompile Include="..\MessageHandlers.cpp" />
|
||||
<ClCompile Include="..\UDPSocket.cpp" />
|
||||
<ClCompile Include="..\XPCPlugin.cpp" />
|
||||
<ClCompile Include="..\xpcPluginTools.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Library Include="..\SDK\Libraries\Win\XPLM.lib" />
|
||||
|
||||
@@ -15,27 +15,51 @@
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\C\src\xplaneConnect.h">
|
||||
<ClInclude Include="..\Log.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\xpcPluginTools.h">
|
||||
<ClInclude Include="..\Drawing.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\xpcDrawing.h">
|
||||
<ClInclude Include="..\UDPSocket.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Message.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\DataManager.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\DataMaps.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\MessageHandlers.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\C\src\xplaneConnect.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\XPCPlugin.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\xpcPluginTools.cpp">
|
||||
<ClCompile Include="..\Log.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\xpcDrawing.cpp">
|
||||
<ClCompile Include="..\Drawing.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\UDPSocket.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\Message.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\DataManager.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\MessageHandlers.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\DataMaps.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
|
||||
@@ -1,492 +0,0 @@
|
||||
// xpcPluginTools functions to support xpcPlugin
|
||||
//
|
||||
// FUNCTIONS
|
||||
// buildXPLMDataRefs
|
||||
// fmini
|
||||
// almostequal
|
||||
// updateLog
|
||||
// handleDREFSIM
|
||||
// getIP
|
||||
// printBuffertoLog
|
||||
// test
|
||||
// testi
|
||||
//
|
||||
// CONTACT
|
||||
// For questions email Christopher Teubert (christopher.a.teubert@nasa.gov)
|
||||
//
|
||||
// CONTRIBUTORS
|
||||
// CT: Christopher Teubert (christopher.a.teubert@nasa.gov)
|
||||
//
|
||||
// TO DO:
|
||||
// 1. Support sending -1 length to updateLog for it to calculate intself (look for /0)
|
||||
// 2. Have printbuffertolog run parse function
|
||||
// 3. Builddatarefs: Fill out & test options
|
||||
//
|
||||
// BEGIN CODE
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <math.h>
|
||||
#include "xpcPluginTools.h"
|
||||
|
||||
XPLMDataRef XPLMDataRefs[134][8];
|
||||
XPLMDataRef multiplayer[20][17];
|
||||
XPLMDataRef AIswitch;
|
||||
|
||||
void readMessage(struct xpcSocket * recSocket, struct XPCMessage * pMessage)
|
||||
{
|
||||
pMessage->msglen = readUDP( *recSocket, pMessage->msg, &(pMessage->recvaddr) );
|
||||
|
||||
if ( pMessage->msglen <= 0 ) // No Message
|
||||
{
|
||||
pMessage->msg[0] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
strncpy( pMessage->head, pMessage->msg, 4 );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void buildXPLMDataRefs()
|
||||
{
|
||||
int i, j;
|
||||
char multi[50] = {0};
|
||||
|
||||
for (i=0; i<134; i++)
|
||||
{
|
||||
for (j=0; j<8; j++)
|
||||
{
|
||||
XPLMDataRefs[i][j] = XPLMFindDataRef("sim/test/test_float");
|
||||
}
|
||||
}
|
||||
|
||||
/* Prefetch the sim variables we will use. */
|
||||
//Row 0: Frame Rates
|
||||
|
||||
//Row 1: Times
|
||||
XPLMDataRefs[1][1] = XPLMFindDataRef("sim/time/total_running_time_sec");
|
||||
XPLMDataRefs[1][2] = XPLMFindDataRef("sim/time/total_flight_time_sec");
|
||||
XPLMDataRefs[1][3] = XPLMFindDataRef("sim/time/timer_elapsed_time_sec");
|
||||
|
||||
//cockpit2/clock_time/zulu_time_hours
|
||||
//cockpit2/clock_time/zulu_time_minutes
|
||||
//cockpit2/clock_time/zulu_time_seconds
|
||||
|
||||
//cockpit2/clock_time/local_time_hours
|
||||
|
||||
//cockpit2/clock_time/hobbs_time_hours
|
||||
|
||||
//Row 2: Sim Stats
|
||||
|
||||
//Row 3: Velocities
|
||||
//READ ONLY
|
||||
XPLMDataRefs[3][0] = XPLMFindDataRef("sim/flightmodel/position/indicated_airspeed"); //Vind knots indicated airspeed TEST
|
||||
|
||||
//Vind knots equivilent airspeed (considering compressible flow)
|
||||
XPLMDataRefs[3][2] = XPLMFindDataRef("sim/flightmodel/position/true_airspeed"); //Vtrue knots true airspeed
|
||||
XPLMDataRefs[3][3] = XPLMFindDataRef("sim/flightmodel/position/groundspeed"); //Vtrue Knots true ground speed
|
||||
|
||||
//XPLMDataRefs[3][5] = Vind mph
|
||||
//XPLMDataRefs[3][6] = Vtrue mphas
|
||||
//XPLMDataRefs[3][7] = Vtre mphgs
|
||||
|
||||
//Row 4: Mach, VVI, G-loads
|
||||
XPLMDataRefs[4][0] = XPLMFindDataRef("sim/flightmodel/misc/machno"); // Mach Number
|
||||
XPLMDataRefs[4][4] = XPLMFindDataRef("sim/flightmodel2/misc/gforce_normal");
|
||||
XPLMDataRefs[4][5] = XPLMFindDataRef("sim/flightmodel2/misc/gforce_axial");
|
||||
XPLMDataRefs[4][6] = XPLMFindDataRef("sim/flightmodel2/misc/gforce_side");
|
||||
|
||||
//Row 5: Atmosphere: Weather
|
||||
XPLMDataRefs[5][0] = XPLMFindDataRef("sim/weather/barometer_sealevel_inhg");
|
||||
XPLMDataRefs[5][1] = XPLMFindDataRef("sim/weather/temperature_sealevel_c");
|
||||
XPLMDataRefs[5][3] = XPLMFindDataRef("sim/cockpit2/gauges/indicators/wind_speed_kts");
|
||||
|
||||
//Row 6: Atmosphere: Aircraft
|
||||
|
||||
//Row 7: System Pressures
|
||||
|
||||
//Row 8: Joystick
|
||||
XPLMDataRefs[8][0] = XPLMFindDataRef("sim/joystick/yoke_pitch_ratio");
|
||||
XPLMDataRefs[8][1] = XPLMFindDataRef("sim/joystick/yoke_roll_ratio");
|
||||
XPLMDataRefs[8][2] = XPLMFindDataRef("sim/joystick/yoke_heading_ratio");
|
||||
|
||||
//Row 9: Other Flight Controls
|
||||
|
||||
//Row 10: Art stab ail/elv/rud
|
||||
|
||||
//Row 11: Control Surfaces
|
||||
XPLMDataRefs[11][0] = XPLMFindDataRef("sim/cockpit2/controls/yoke_pitch_ratio"); //Elevator Position
|
||||
XPLMDataRefs[11][1] = XPLMFindDataRef("sim/cockpit2/controls/yoke_roll_ratio"); //Aileron Position
|
||||
XPLMDataRefs[11][2] = XPLMFindDataRef("sim/cockpit2/controls/yoke_heading_ratio"); //Rudder Position
|
||||
XPLMDataRefs[11][3] = NULL;
|
||||
XPLMDataRefs[11][4] = NULL;
|
||||
XPLMDataRefs[11][5] = NULL;
|
||||
XPLMDataRefs[11][6] = NULL;
|
||||
XPLMDataRefs[11][7] = NULL;
|
||||
|
||||
//Row 12: Wing Sweep/Trust Vec
|
||||
|
||||
//Row 13: trip/flap/slat/s-brakes
|
||||
XPLMDataRefs[13][3] = XPLMFindDataRef("sim/flightmodel/controls/flaprqst");
|
||||
XPLMDataRefs[13][4] = XPLMFindDataRef("sim/flightmodel/controls/flaprat");// should be equal to flap2rat
|
||||
|
||||
//Row 14: Gear, Brakes
|
||||
XPLMDataRefs[14][0] = XPLMFindDataRef("sim/aircraft/parts/acf_gear_deploy"); //Landing Gear-SPECIAL (Float[10])
|
||||
XPLMDataRefs[14][1] = XPLMFindDataRef("sim/flightmodel/controls/parkbrake"); //Parking Brake
|
||||
XPLMDataRefs[14][2] = XPLMFindDataRef("sim/cockpit2/controls/left_brake_ratio");
|
||||
XPLMDataRefs[14][3] = XPLMFindDataRef("sim/cockpit2/controls/right_brake_ratio");
|
||||
|
||||
XPLMDataRefs[14][7] = XPLMFindDataRef("sim/cockpit/switches/gear_handle_status"); //Landing Gear Handle
|
||||
|
||||
//Row 15: MNR (Angular Moments)
|
||||
//READ ONLY
|
||||
XPLMDataRefs[15][0] = XPLMFindDataRef("sim/flightmodel/position/M");
|
||||
XPLMDataRefs[15][1] = XPLMFindDataRef("sim/flightmodel/position/L");
|
||||
XPLMDataRefs[15][2] = XPLMFindDataRef("sim/flightmodel/position/N");
|
||||
|
||||
//Row 16: PQR (Angular Velocities)
|
||||
XPLMDataRefs[16][0] = XPLMFindDataRef("sim/flightmodel/position/Qrad");
|
||||
XPLMDataRefs[16][1] = XPLMFindDataRef("sim/flightmodel/position/Prad");
|
||||
XPLMDataRefs[16][2] = XPLMFindDataRef("sim/flightmodel/position/Rrad");
|
||||
XPLMDataRefs[16][3] = XPLMFindDataRef("sim/flightmodel/position/Q");
|
||||
XPLMDataRefs[16][4] = XPLMFindDataRef("sim/flightmodel/position/P");
|
||||
XPLMDataRefs[16][5] = XPLMFindDataRef("sim/flightmodel/position/R");
|
||||
|
||||
//Row 17: Orientation: pitch, roll, yaw, heading
|
||||
XPLMDataRefs[17][0] = XPLMFindDataRef("sim/flightmodel/position/theta"); //Pitch
|
||||
XPLMDataRefs[17][1] = XPLMFindDataRef("sim/flightmodel/position/phi"); //roll
|
||||
XPLMDataRefs[17][2] = XPLMFindDataRef("sim/flightmodel/position/psi"); //true heading (where nose is pointing)
|
||||
|
||||
//READ ONLY (always)
|
||||
XPLMDataRefs[17][3] = XPLMFindDataRef("sim/flightmodel/position/magpsi"); //magnetic heading
|
||||
|
||||
//WRITABLE
|
||||
XPLMDataRefs[17][4] = XPLMFindDataRef("sim/flightmodel/position/q"); //Quartonian
|
||||
|
||||
//Row 18: Orientation: alpha beta hpath vpath slip
|
||||
XPLMDataRefs[18][0] = XPLMFindDataRef("sim/flightmodel/position/alpha"); //Angle of Attack
|
||||
XPLMDataRefs[18][1] = XPLMFindDataRef("sim/cockpit2/gauges/indicators/sideslip_degrees"); //fix to beta
|
||||
XPLMDataRefs[18][2] = XPLMFindDataRef("sim/flightmodel/position/hpath"); //Heading the aircraft flies (velocity vector) TEST
|
||||
XPLMDataRefs[18][3] = XPLMFindDataRef("sim/flightmodel/position/vpath"); //VPath TEST
|
||||
XPLMDataRefs[18][7] = XPLMFindDataRef("sim/cockpit2/gauges/indicators/sideslip_degrees");
|
||||
|
||||
//Row 19: Mag Compass
|
||||
XPLMDataRefs[19][0] = XPLMFindDataRef("sim/flightmodel/position/magpsi");
|
||||
|
||||
//READ ONLY
|
||||
XPLMDataRefs[19][1] = XPLMFindDataRef("sim/flightmodel/position/magnetic_variation");
|
||||
|
||||
//Row 20: Global Position
|
||||
//READ ONLY
|
||||
XPLMDataRefs[20][0] = XPLMFindDataRef("sim/flightmodel/position/latitude"); // Read Only
|
||||
XPLMDataRefs[20][1] = XPLMFindDataRef("sim/flightmodel/position/longitude"); // Read Only
|
||||
XPLMDataRefs[20][3] = XPLMFindDataRef("sim/flightmodel/position/y_agl"); // Read Only
|
||||
|
||||
//Row 21: Local Position, Velocity
|
||||
XPLMDataRefs[21][0] = XPLMFindDataRef("sim/flightmodel/position/local_x");
|
||||
XPLMDataRefs[21][1] = XPLMFindDataRef("sim/flightmodel/position/local_y");
|
||||
XPLMDataRefs[21][2] = XPLMFindDataRef("sim/flightmodel/position/local_z");
|
||||
XPLMDataRefs[21][3] = XPLMFindDataRef("sim/flightmodel/position/local_vx");
|
||||
XPLMDataRefs[21][4] = XPLMFindDataRef("sim/flightmodel/position/local_vy");
|
||||
XPLMDataRefs[21][5] = XPLMFindDataRef("sim/flightmodel/position/local_vz");
|
||||
|
||||
//Row 22: All Planes: Lat (READ ONLY)
|
||||
XPLMDataRefs[22][0] = XPLMDataRefs[20][0];
|
||||
XPLMDataRefs[22][1] = XPLMFindDataRef("sim/multiplayer/position/plane1_lat");
|
||||
XPLMDataRefs[22][2] = XPLMFindDataRef("sim/multiplayer/position/plane2_lat");
|
||||
XPLMDataRefs[22][3] = XPLMFindDataRef("sim/multiplayer/position/plane3_lat");
|
||||
XPLMDataRefs[22][4] = XPLMFindDataRef("sim/multiplayer/position/plane4_lat");
|
||||
XPLMDataRefs[22][5] = XPLMFindDataRef("sim/multiplayer/position/plane5_lat");
|
||||
XPLMDataRefs[22][6] = XPLMFindDataRef("sim/multiplayer/position/plane6_lat");
|
||||
XPLMDataRefs[22][7] = XPLMFindDataRef("sim/multiplayer/position/plane7_lat");
|
||||
|
||||
//Row 23: All Planes: Lon
|
||||
XPLMDataRefs[23][0] = XPLMDataRefs[20][1];
|
||||
XPLMDataRefs[23][1] = XPLMFindDataRef("sim/multiplayer/position/plane1_lon");
|
||||
XPLMDataRefs[23][2] = XPLMFindDataRef("sim/multiplayer/position/plane2_lon");
|
||||
XPLMDataRefs[23][3] = XPLMFindDataRef("sim/multiplayer/position/plane3_lon");
|
||||
XPLMDataRefs[23][4] = XPLMFindDataRef("sim/multiplayer/position/plane4_lon");
|
||||
XPLMDataRefs[23][5] = XPLMFindDataRef("sim/multiplayer/position/plane5_lon");
|
||||
XPLMDataRefs[23][6] = XPLMFindDataRef("sim/multiplayer/position/plane6_lon");
|
||||
XPLMDataRefs[23][7] = XPLMFindDataRef("sim/multiplayer/position/plane7_lon");
|
||||
|
||||
//Row 24: All Planes: Alt
|
||||
XPLMDataRefs[24][0] = XPLMDataRefs[20][2];
|
||||
XPLMDataRefs[24][1] = XPLMFindDataRef("sim/multiplayer/position/plane1_el");
|
||||
XPLMDataRefs[24][2] = XPLMFindDataRef("sim/multiplayer/position/plane2_el");
|
||||
XPLMDataRefs[24][3] = XPLMFindDataRef("sim/multiplayer/position/plane3_el");
|
||||
XPLMDataRefs[24][4] = XPLMFindDataRef("sim/multiplayer/position/plane4_el");
|
||||
XPLMDataRefs[24][5] = XPLMFindDataRef("sim/multiplayer/position/plane5_el");
|
||||
XPLMDataRefs[24][6] = XPLMFindDataRef("sim/multiplayer/position/plane6_el");
|
||||
XPLMDataRefs[24][7] = XPLMFindDataRef("sim/multiplayer/position/plane7_el");
|
||||
|
||||
//Row 25: Throttle Command
|
||||
XPLMDataRefs[25][0] = XPLMFindDataRef("sim/flightmodel/engine/ENGN_thro"); //Throttle (array 8)
|
||||
|
||||
//Row 26: Throttle Actual
|
||||
XPLMDataRefs[26][0] = XPLMFindDataRef("sim/flightmodel2/engines/throttle_used_ratio"); // Trottle Actual (array 8) (Read Only)
|
||||
|
||||
//Row 27:
|
||||
|
||||
|
||||
// Multiplayer
|
||||
for ( i = 1; i < 20; i++ )
|
||||
{
|
||||
sprintf(multi, "sim/multiplayer/position/plane%i_x", i); // X
|
||||
multiplayer[i][0] = XPLMFindDataRef(multi);
|
||||
sprintf(multi, "sim/multiplayer/position/plane%i_y", i); // Y
|
||||
multiplayer[i][1] = XPLMFindDataRef(multi);
|
||||
sprintf(multi,"sim/multiplayer/position/plane%i_z", i); // Z
|
||||
multiplayer[i][2] = XPLMFindDataRef(multi);
|
||||
sprintf(multi,"sim/multiplayer/position/plane%i_the", i); // Theta (Pitch)
|
||||
multiplayer[i][3] = XPLMFindDataRef(multi);
|
||||
sprintf(multi,"sim/multiplayer/position/plane%i_phi", i); // Phi (Roll)
|
||||
multiplayer[i][4] = XPLMFindDataRef(multi);
|
||||
sprintf(multi,"sim/multiplayer/position/plane%i_psi", i); // Psi (Heading-True)
|
||||
multiplayer[i][5] = XPLMFindDataRef(multi);
|
||||
sprintf(multi, "sim/multiplayer/position/plane%i_gear_deploy", i); // Landing Gear
|
||||
multiplayer[i][6] = XPLMFindDataRef(multi);
|
||||
sprintf(multi, "sim/multiplayer/position/plane%i_flap_ratio", i);
|
||||
multiplayer[i][7] = XPLMFindDataRef(multi);
|
||||
sprintf(multi, "sim/multiplayer/position/plane%i_flap_ratio2", i);
|
||||
multiplayer[i][8] = XPLMFindDataRef(multi);
|
||||
sprintf(multi, "sim/multiplayer/position/plane%i_spoiler_ratio", i);
|
||||
multiplayer[i][9] = XPLMFindDataRef(multi);
|
||||
sprintf(multi, "sim/multiplayer/position/plane%i_speedbrake_ratio", i);
|
||||
multiplayer[i][10] = XPLMFindDataRef(multi);
|
||||
sprintf(multi, "sim/multiplayer/position/plane%i_slat_ratio", i);
|
||||
multiplayer[i][11] = XPLMFindDataRef(multi);
|
||||
sprintf(multi, "sim/multiplayer/position/plane%i_wing_sweep", i);
|
||||
multiplayer[i][12] = XPLMFindDataRef(multi);
|
||||
sprintf(multi, "sim/multiplayer/position/plane%i_throttle", i);
|
||||
multiplayer[i][13] = XPLMFindDataRef(multi);
|
||||
sprintf(multi, "sim/multiplayer/position/plane%i_yolk_pitch", i);
|
||||
multiplayer[i][14] = XPLMFindDataRef(multi);
|
||||
sprintf(multi, "sim/multiplayer/position/plane%i_yolk_roll", i);
|
||||
multiplayer[i][15] = XPLMFindDataRef(multi);
|
||||
sprintf(multi, "sim/multiplayer/position/plane%i_yolk_yaw", i);
|
||||
multiplayer[i][16] = XPLMFindDataRef(multi);
|
||||
}
|
||||
AIswitch = XPLMFindDataRef("sim/operation/override/override_plane_ai_autopilot");
|
||||
}
|
||||
|
||||
int fmini(int a, int b)
|
||||
{
|
||||
// Returns the minimum value of two integers
|
||||
return ((((a)-(b))&0x80000000) >> 31)? (a) : (b);
|
||||
}
|
||||
|
||||
int almostequal(float arg1, float arg2, float tol)
|
||||
{
|
||||
// Compares arg1 and arg 2. If they are within tol returns true
|
||||
return (abs(arg1-arg2)<tol);
|
||||
}
|
||||
|
||||
int updateLog(const char *buffer, int length)
|
||||
{
|
||||
// Writes buffer to logfile (xpcLog.txt)
|
||||
|
||||
time_t rawtime;
|
||||
struct tm * timeinfo;
|
||||
char logBuffer[523] = { 0 };
|
||||
FILE * logFile;
|
||||
|
||||
logFile = fopen("xpcLog.txt","a");
|
||||
|
||||
time(&rawtime);
|
||||
timeinfo = localtime(&rawtime);
|
||||
// Format is equivalent to [%F %T], but neither of those specifiers is
|
||||
// supported on Windows as of Visual Studio 13
|
||||
strftime(logBuffer, 523, "[%Y-%m-%d %H:%M:%S] ", timeinfo);
|
||||
|
||||
length = length < 500 ? length : 500;
|
||||
memcpy(&(logBuffer[22]), buffer, length);
|
||||
|
||||
fprintf(logFile,"%s\n",logBuffer);
|
||||
|
||||
fclose(logFile);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
unsigned short getIP(struct sockaddr recvaddr, char *IP)
|
||||
{
|
||||
// Gets the IP Address from sockaddr
|
||||
struct sockaddr_in *sendaddr;
|
||||
|
||||
sendaddr = (struct sockaddr_in *) &recvaddr;
|
||||
sprintf(IP,"%d.%d.%d.%d",(int) (*sendaddr).sin_addr.s_addr&0xFF, (int) ((*sendaddr).sin_addr.s_addr&0xFF00)>>8, (int) ((*sendaddr).sin_addr.s_addr&0xFF0000)>>16, (int) ((*sendaddr).sin_addr.s_addr&0xFF000000)>>24);
|
||||
|
||||
return ntohs((*sendaddr).sin_port);
|
||||
}
|
||||
|
||||
// DEBUGGING TOOLS
|
||||
// --------------------------------
|
||||
int printBufferToLog(struct XPCMessage & msg)
|
||||
{
|
||||
// Prints the entire buffer to the log (for debugging)
|
||||
char logmsg[350] = "[DEBUG]";
|
||||
int i;
|
||||
|
||||
for (i=0;i<msg.msglen && strlen(logmsg)<(sizeof(logmsg)-4);i++)
|
||||
{
|
||||
sprintf(logmsg,"%s %hhu",logmsg,msg.msg[i]);
|
||||
}
|
||||
|
||||
updateLog(logmsg,strlen(logmsg));
|
||||
memset(logmsg,0,strlen(logmsg));
|
||||
|
||||
sprintf(logmsg,"[%s-DEBUG](%i)",msg.head,msg.msg[4]);
|
||||
|
||||
//Switch for header
|
||||
if (strncmp(msg.head,"CONN",4)==0)
|
||||
{// Header = CONN (Connection)
|
||||
updateLog(logmsg,strlen(logmsg));
|
||||
|
||||
}
|
||||
else if (strncmp(msg.head,"SIMU",4)==0)
|
||||
{// Header = SIMU
|
||||
sprintf(logmsg,"%s %i",logmsg,msg.msg[5]);
|
||||
updateLog(logmsg,strlen(logmsg));
|
||||
|
||||
}
|
||||
else if (strncmp(msg.head,"POSI",4)==0)
|
||||
{// Header = POSI (Position)
|
||||
float position[8] = {0.0};
|
||||
float pos[3],orient[3];
|
||||
short aircraft = 0;
|
||||
float gear = -1.0;
|
||||
|
||||
// UPDATE LOG
|
||||
aircraft = parsePOSI(msg.msg,position,6, &gear);
|
||||
|
||||
//ADD AIRCRAFT HANDLING
|
||||
|
||||
// Position
|
||||
memcpy(pos,position,3*sizeof(float));
|
||||
|
||||
// Orientation
|
||||
memcpy(orient,&position[3],3*sizeof(float));
|
||||
|
||||
sprintf(logmsg,"%s %i (%f %f %f) (%f %f %f) %f",logmsg,aircraft,pos[0],pos[1],pos[2],orient[0],orient[1],orient[2],gear);
|
||||
|
||||
updateLog(logmsg,strlen(logmsg));
|
||||
}
|
||||
else if (strncmp(msg.head,"CTRL",4)==0)
|
||||
{// Header = CTRL (Control)
|
||||
xpcCtrl ctrl = parseCTRL(msg.msg);
|
||||
|
||||
sprintf(logmsg,"%s (%f %f %f) %f %hhi %f",logmsg, ctrl.pitch, ctrl.roll, ctrl.yaw, ctrl.throttle, ctrl.gear, ctrl.flaps);
|
||||
|
||||
updateLog(logmsg,strlen(logmsg));
|
||||
|
||||
}
|
||||
else if (strncmp(msg.head,"WYPT",4)==0)
|
||||
{// Header = WYPT (Waypoint Draw)
|
||||
|
||||
updateLog(logmsg,strlen(logmsg));
|
||||
|
||||
}
|
||||
else if (strncmp(msg.head,"GETD",4)==0)
|
||||
{// Header = GETD (Data Request)
|
||||
char DREF[100];
|
||||
int counter = 6;
|
||||
|
||||
updateLog(logmsg,strlen(logmsg));
|
||||
memset(logmsg,0,strlen(logmsg));
|
||||
|
||||
for (i=0;i<msg.msg[5];i++)
|
||||
{
|
||||
memcpy(DREF,&msg.msg[counter+1],msg.msg[counter]);
|
||||
sprintf(logmsg,"\t#%i/%i (size:%i) %s",i+1,msg.msg[5],msg.msg[counter],DREF);
|
||||
|
||||
updateLog(logmsg,strlen(logmsg));
|
||||
memset(logmsg,0,strlen(logmsg));
|
||||
memset(DREF,0,sizeof(DREF));
|
||||
|
||||
counter += msg.msg[counter]+1;
|
||||
}
|
||||
}
|
||||
else if (strncmp(msg.head,"DREF",4)==0)
|
||||
{// Header = DREF (By Data Ref) (this is slower than DATA)
|
||||
char DREF[100]={0};
|
||||
float tmp;
|
||||
updateLog(logmsg,strlen(logmsg));
|
||||
memset(logmsg,0,strlen(logmsg));
|
||||
|
||||
memcpy(DREF,&msg.msg[6],msg.msg[5]);
|
||||
sprintf(logmsg,"-\tDREF (size %i)= %s",msg.msg[5],DREF);
|
||||
updateLog(logmsg,strlen(logmsg));
|
||||
memset(logmsg,0,strlen(logmsg));
|
||||
sprintf(logmsg,"-\tValues(Size %i)=",msg.msg[6+msg.msg[5]]);
|
||||
for (i=0;i<msg.msg[6+msg.msg[5]];i++)
|
||||
{
|
||||
memcpy(&tmp,&msg.msg[7+msg.msg[5]+sizeof(float)*i],sizeof(float));
|
||||
sprintf(logmsg,"%s %f",logmsg,tmp);
|
||||
}
|
||||
updateLog(logmsg,strlen(logmsg));
|
||||
}
|
||||
else if (strncmp(msg.head,"VIEW",4)==0)
|
||||
{// Header = VIEW (Change View)
|
||||
updateLog(logmsg,strlen(logmsg));
|
||||
}
|
||||
else if (strncmp(msg.head,"DATA",4)==0)
|
||||
{// Header = DATA (UDP Data)
|
||||
int j;
|
||||
short totalColumns = ((msg.msglen-5)/36);
|
||||
float dataRef[30][9];
|
||||
|
||||
sprintf(logmsg,"%s (%i lines)",logmsg,totalColumns);
|
||||
updateLog(logmsg,strlen(logmsg));
|
||||
memset(logmsg,0,strlen(logmsg));
|
||||
|
||||
totalColumns = parseDATA(msg.msg, msg.msg[4], dataRef);
|
||||
|
||||
for (i=0; i<totalColumns; i++)
|
||||
{
|
||||
sprintf(logmsg,"\t#%i: ",(int) dataRef[i][0]);
|
||||
|
||||
for (j=1; j<9; j++)
|
||||
{
|
||||
sprintf(logmsg,"%s %f",logmsg,dataRef[i][j]);
|
||||
if (dataRef[i][j]!=dataRef[i][j]) sprintf(logmsg,"%s (not a number)",logmsg);
|
||||
}
|
||||
updateLog(logmsg,strlen(logmsg));
|
||||
memset(logmsg,0,strlen(logmsg));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1; //unrecognized header
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int test(const char *buffer)
|
||||
{
|
||||
// Prints "test buffer" to log (for debugging)
|
||||
char logmsg[100] = {0};
|
||||
char buffer2[95] = {0};
|
||||
strncpy(buffer2, buffer, 95);
|
||||
sprintf(logmsg,"[TEST] %s",buffer2);
|
||||
|
||||
updateLog(logmsg,strlen(logmsg));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int test(int buffer)
|
||||
{
|
||||
// Prints "test #[buffer]" to log (for debugging)
|
||||
char logmsg[100] = {0};
|
||||
sprintf(logmsg,"[TEST] #%i",buffer);
|
||||
|
||||
updateLog(logmsg,strlen(logmsg));
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
//
|
||||
// xpcPluginTools.pch
|
||||
// xpcPlugin
|
||||
//
|
||||
// Created by Chris Teubert on 4/14/14.
|
||||
//
|
||||
//
|
||||
|
||||
#ifndef xpcPlugin_xpcPluginTools_h
|
||||
#define xpcPlugin_xpcPluginTools_h
|
||||
|
||||
#include <time.h>
|
||||
#include "xplaneConnect.h"
|
||||
#include "XPLMDataAccess.h"
|
||||
|
||||
extern XPLMDataRef XPLMDataRefs[134][8];
|
||||
extern XPLMDataRef multiplayer[20][17];
|
||||
extern XPLMDataRef AIswitch;
|
||||
|
||||
struct XPCMessage
|
||||
{
|
||||
short connectionID;
|
||||
char head[5];
|
||||
char msg[5000];
|
||||
int msglen;
|
||||
struct sockaddr recvaddr;
|
||||
};
|
||||
|
||||
void readMessage(struct xpcSocket * recSocket, struct XPCMessage * pMessage);
|
||||
|
||||
void buildXPLMDataRefs(void);
|
||||
|
||||
int almostequal(float arg1, float arg2, float tol);
|
||||
|
||||
int test(const char *buffer);
|
||||
|
||||
int test(int buffer);
|
||||
|
||||
int updateLog(const char *buffer, int length);
|
||||
|
||||
unsigned short getIP(struct sockaddr recvaddr, char *IP);
|
||||
|
||||
int printBufferToLog(struct XPCMessage & msg);
|
||||
|
||||
int fmini(int a, int b);
|
||||
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user