Merge branch 'feature/consistency' into develop
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -1,119 +1,255 @@
|
|||||||
|
//Copyright (c) 2013-2015 United States Government as represented by the Administrator of the
|
||||||
|
//National Aeronautics and Space Administration. All Rights Reserved.
|
||||||
//
|
//
|
||||||
// xplaneConnect.h
|
//DISCLAIMERS
|
||||||
//
|
// No Warranty: THE SUBJECT SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY OF ANY KIND,
|
||||||
// Created by Chris Teubert on 12/2/13.
|
// 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
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef xplaneConnect_h
|
#include "stdlib.h"
|
||||||
#define xplaneConnect_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 */
|
typedef struct
|
||||||
#include <winsock2.h>
|
{
|
||||||
#include <ws2tcpip.h>
|
char open;
|
||||||
#pragma comment(lib,"ws2_32.lib") //Winsock Library
|
unsigned short port;
|
||||||
#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
|
// X-Plane IP and Port
|
||||||
{
|
char xpIP[16];
|
||||||
float pitch;
|
unsigned short xpPort;
|
||||||
float roll;
|
|
||||||
float yaw;
|
|
||||||
float throttle;
|
|
||||||
char gear;
|
|
||||||
float flaps;
|
|
||||||
char aircraft;
|
|
||||||
} xpcCtrl;
|
|
||||||
|
|
||||||
typedef struct
|
#ifdef _WIN32
|
||||||
{
|
SOCKET sock;
|
||||||
double latitude;
|
#else
|
||||||
double longitude;
|
int sock;
|
||||||
double altitude;
|
#endif
|
||||||
} Waypoint;
|
} XPCSocket;
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
xpc_WYPT_ADD = 1,
|
XPC_WYPT_ADD = 1,
|
||||||
xpc_WYPT_DEL = 2,
|
XPC_WYPT_DEL = 2,
|
||||||
xpc_WYPT_CLR = 3
|
XPC_WYPT_CLR = 3
|
||||||
} WYPT_OP;
|
} WYPT_OP;
|
||||||
|
|
||||||
|
// Low Level UDP Functions
|
||||||
|
|
||||||
typedef struct
|
/// Opens a new connection to XPC on an OS chosen port.
|
||||||
{
|
///
|
||||||
WYPT_OP op;
|
/// \param xpIP A string representing the IP address of the host running X-Plane.
|
||||||
Waypoint points[20];
|
/// \param xpPort The port of the X-Plane Connect plugin is listening on. Usually 49009.
|
||||||
size_t numPoints;
|
/// \returns An XPCSocket struct representing the newly created connection.
|
||||||
} xpcWypt;
|
XPCSocket aopenUDP(const char *xpIP, unsigned short xpPort);
|
||||||
|
|
||||||
// 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);
|
|
||||||
|
|
||||||
// Waypoints
|
/// Opens a new connection to XPC on the specified port.
|
||||||
xpcWypt parseWYPT(const char data[]);
|
///
|
||||||
short sendWYPT(struct xpcSocket sendfd, WYPT_OP op, float points[], int numPoints);
|
/// \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 openUDP(const char *xpIP, unsigned short xpPort, unsigned short port);
|
||||||
|
|
||||||
// Screen Text
|
/// Closes the specified connection and releases resources associated with it.
|
||||||
short sendTEXT(struct xpcSocket sendfd, char* msg, int x, int y);
|
///
|
||||||
|
/// \param sock The socket to close.
|
||||||
|
void closeUDP(XPCSocket sock);
|
||||||
|
|
||||||
|
/// Sends the given data to the X-Plane plugin.
|
||||||
|
///
|
||||||
|
/// \param sock The socket to use to send the data.
|
||||||
|
/// \param buffer A pointer to the data to send.
|
||||||
|
/// \param len The number of bytes to send.
|
||||||
|
/// \returns If an error occurs, a negative number. Otehrwise, the number of bytes sent.
|
||||||
|
int sendUDP(XPCSocket sock, char buffer[], int len);
|
||||||
|
|
||||||
|
/// Reads a datagram from the specified socket.
|
||||||
|
///
|
||||||
|
/// \param sock The socket to read from.
|
||||||
|
/// \param buffer A pointer to the location to store the data.
|
||||||
|
/// \param len The number of bytes to read.
|
||||||
|
/// \returns If an error occurs, a negative number. Otehrwise, the number of bytes read.
|
||||||
|
int readUDP(XPCSocket sock, char buffer[], int len);
|
||||||
|
|
||||||
|
// 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 dataRef 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 dataRef[][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 dataRef 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 dataRef[][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 setDREF(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 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 player 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.
|
||||||
|
/// \returns 0 if successful, otherwise a negative value.
|
||||||
|
int psendPOSI(XPCSocket sock, float values[], int size);
|
||||||
|
|
||||||
|
/// 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 player 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.
|
||||||
|
/// \returns 0 if successful, otherwise a negative value.
|
||||||
|
int psendCTRL(XPCSocket sock, float values[], int size);
|
||||||
|
|
||||||
|
/// 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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|||||||
Binary file not shown.
@@ -44,8 +44,7 @@ import java.util.Arrays;
|
|||||||
public class XPlaneConnect implements AutoCloseable
|
public class XPlaneConnect implements AutoCloseable
|
||||||
{
|
{
|
||||||
private static int clientNum;
|
private static int clientNum;
|
||||||
private DatagramSocket outSocket;
|
private DatagramSocket socket;
|
||||||
private DatagramSocket inSocket;
|
|
||||||
private InetAddress xplaneAddr;
|
private InetAddress xplaneAddr;
|
||||||
private int xplanePort;
|
private int xplanePort;
|
||||||
|
|
||||||
@@ -54,7 +53,7 @@ public class XPlaneConnect implements AutoCloseable
|
|||||||
*
|
*
|
||||||
* @return The incoming port number.
|
* @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.
|
* 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
|
public XPlaneConnect(int timeout) throws SocketException
|
||||||
{
|
{
|
||||||
this.inSocket = new DatagramSocket(49008);
|
this.socket = new DatagramSocket(0);
|
||||||
this.outSocket = new DatagramSocket(50000 + ++clientNum);
|
|
||||||
this.xplaneAddr = InetAddress.getLoopbackAddress();
|
this.xplaneAddr = InetAddress.getLoopbackAddress();
|
||||||
this.xplanePort = 49009;
|
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.
|
* 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 xpHost The network host on which X-Plane is running.
|
||||||
* @param xplaneHost The network host on which X-Plane is running.
|
* @param xpPort The port on which the X-Plane Connect plugin is listening.
|
||||||
* @param xplanePort 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.SocketException If this instance is unable to bind to the specified port.
|
||||||
* @throws java.net.UnknownHostException If the specified hostname can not be resolved.
|
* @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
|
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.
|
* 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 xpHost The network host on which X-Plane is running.
|
||||||
* @param xplaneHost The network host on which X-Plane is running.
|
* @param xpPort The port on which the X-Plane Connect plugin is listening.
|
||||||
* @param xplanePort 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.
|
* @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.SocketException If this instance is unable to bind to the specified port.
|
||||||
* @throws java.net.UnknownHostException If the specified hostname can not be resolved.
|
* @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
|
throws java.net.SocketException, java.net.UnknownHostException
|
||||||
{
|
{
|
||||||
this.inSocket = new DatagramSocket(port);
|
this.socket = new DatagramSocket(port);
|
||||||
this.outSocket = new DatagramSocket(50000 + ++clientNum);
|
this.xplaneAddr = InetAddress.getByName(xpHost);
|
||||||
this.xplaneAddr = InetAddress.getByName(xplaneHost);
|
this.xplanePort = xpPort;
|
||||||
this.xplanePort = xplanePort;
|
this.socket.setSoTimeout(timeout);
|
||||||
this.inSocket.setSoTimeout(timeout);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Closes the underlying inSocket.
|
* Closes the underlying socket.
|
||||||
*/
|
*/
|
||||||
public void close()
|
public void close()
|
||||||
{
|
{
|
||||||
if(inSocket != null)
|
if(socket != null)
|
||||||
{
|
{
|
||||||
inSocket.close();
|
socket.close();
|
||||||
inSocket = null;
|
socket = null;
|
||||||
}
|
|
||||||
if(outSocket != null)
|
|
||||||
{
|
|
||||||
outSocket.close();
|
|
||||||
outSocket = null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -181,13 +173,13 @@ public class XPlaneConnect implements AutoCloseable
|
|||||||
* @return The data send from X-Plane.
|
* @return The data send from X-Plane.
|
||||||
* @throws IOException If the read operation fails
|
* @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];
|
byte[] buffer = new byte[2048];
|
||||||
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
|
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
inSocket.receive(packet);
|
socket.receive(packet);
|
||||||
return Arrays.copyOf(buffer, buffer[4]);
|
return Arrays.copyOf(buffer, buffer[4]);
|
||||||
}
|
}
|
||||||
catch (SocketTimeoutException ex)
|
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,
|
* Send the given data to the X-Plane plugin.
|
||||||
* overwriting any value previously stored in @{code buffer[4]}.
|
|
||||||
*
|
*
|
||||||
* @param buffer The data to send.
|
* @param buffer The data to send.
|
||||||
* @throws IOException If the send operation fails.
|
* @throws IOException If the send operation fails.
|
||||||
*/
|
*/
|
||||||
private void sendUDP(byte[] buffer) throws IOException
|
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);
|
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.
|
* @return A byte array representing data dependent on the dref requested.
|
||||||
* @throws IOException If either the request or the response fails.
|
* @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.
|
* @return A multidimensional array representing the data for each requested dref.
|
||||||
* @throws IOException If either the request or the response fails.
|
* @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
|
//Preconditions
|
||||||
if(drefs == null || drefs.length == 0)
|
if(drefs == null || drefs.length == 0)
|
||||||
@@ -321,19 +306,19 @@ public class XPlaneConnect implements AutoCloseable
|
|||||||
throw new IOException("No response received.");
|
throw new IOException("No response received.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendDREF(String dref, float value) throws IOException
|
public void setDREF(String dref, float value) throws IOException
|
||||||
{
|
{
|
||||||
sendDREF(dref, new float[] {value});
|
setDREF(dref, new float[] {value});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends a command to X-Plane that sets the given DREF.
|
* 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.
|
* @param value An array of floating point values whose structure depends on the dref specified.
|
||||||
* @throws IOException If the command cannot be sent.
|
* @throws IOException If the command cannot be sent.
|
||||||
*/
|
*/
|
||||||
public void sendDREF(String dref, float[] value) throws IOException
|
public void setDREF(String dref, float[] value) throws IOException
|
||||||
{
|
{
|
||||||
//Preconditions
|
//Preconditions
|
||||||
if(dref == null)
|
if(dref == null)
|
||||||
@@ -559,6 +544,36 @@ public class XPlaneConnect implements AutoCloseable
|
|||||||
sendUDP(os.toByteArray());
|
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
|
public void sendDATA(float[][] data) throws IOException
|
||||||
{
|
{
|
||||||
//Preconditions
|
//Preconditions
|
||||||
@@ -594,6 +609,36 @@ public class XPlaneConnect implements AutoCloseable
|
|||||||
sendUDP(os.toByteArray());
|
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.
|
* 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());
|
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
|
public void sendWYPT(WaypointOp op, float[] points) throws IOException
|
||||||
{
|
{
|
||||||
//Preconditions
|
//Preconditions
|
||||||
@@ -672,12 +726,12 @@ public class XPlaneConnect implements AutoCloseable
|
|||||||
/**
|
/**
|
||||||
* Sets the port on which the client will receive data from X-Plane.
|
* Sets the port on which the client will receive data from X-Plane.
|
||||||
*
|
*
|
||||||
* @param recvPort The new incoming port number.
|
* @param port The new incoming port number.
|
||||||
* @throws IOException If the command cannnot be sent.
|
* @throws IOException If the command cannnot 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).");
|
throw new IllegalArgumentException("Invalid port (must be non-negative and less than 65536).");
|
||||||
}
|
}
|
||||||
@@ -685,14 +739,14 @@ public class XPlaneConnect implements AutoCloseable
|
|||||||
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
||||||
os.write("CONN".getBytes(StandardCharsets.UTF_8));
|
os.write("CONN".getBytes(StandardCharsets.UTF_8));
|
||||||
os.write(0xFF); //Placeholder for message length
|
os.write(0xFF); //Placeholder for message length
|
||||||
os.write((byte) recvPort);
|
os.write((byte) port);
|
||||||
os.write((byte) (recvPort >> 8));
|
os.write((byte) (port >> 8));
|
||||||
sendUDP(os.toByteArray());
|
sendUDP(os.toByteArray());
|
||||||
|
|
||||||
int soTimeout = inSocket.getSoTimeout();
|
int soTimeout = socket.getSoTimeout();
|
||||||
inSocket.close();
|
socket.close();
|
||||||
inSocket = new DatagramSocket(recvPort);
|
socket = new DatagramSocket(port);
|
||||||
inSocket.setSoTimeout(soTimeout);
|
socket.setSoTimeout(soTimeout);
|
||||||
readUDP(); // Try to read response
|
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,27 @@
|
|||||||
function [socket] = closeUDP(socket)
|
function closeUDP(socket)
|
||||||
% closeUDP Script that closes a UDP Socket
|
% closeUDP Closes the specified connection and releases resources associated with it.
|
||||||
%
|
%
|
||||||
% Inputs
|
% Inputs
|
||||||
% Socket: UDP Socket to be closed
|
% socket: An XPC client to close
|
||||||
%
|
|
||||||
% Outputs
|
|
||||||
% Socket: Closed Socket
|
|
||||||
%
|
%
|
||||||
% Use
|
% Use
|
||||||
% 1. import XPlaneConnect.*;
|
% 1. import XPlaneConnect.*;
|
||||||
% 2. Socket = openUDP(49005);
|
% 2. socket = openUDP();
|
||||||
% 3. Status = closeUDP(Socket);
|
% 3. closeUDP(socket);
|
||||||
%
|
%
|
||||||
% Contributors
|
% Contributors
|
||||||
% [CT] Christopher Teubert (SGT, Inc.)
|
% [CT] Christopher Teubert (SGT, Inc.)
|
||||||
% christopher.a.teubert@nasa.gov
|
% christopher.a.teubert@nasa.gov
|
||||||
%
|
% [JW] Jason Watkins
|
||||||
% To Do
|
% jason.w.watkins@nasa.gov
|
||||||
% 1. Verify Input
|
|
||||||
%
|
|
||||||
% BEGIN CODE
|
|
||||||
|
|
||||||
|
%% Close the socket
|
||||||
|
assert(isequal(class(socket), 'gov.nasa.xpc.XPlaneConnect'),...
|
||||||
|
'[closeUDP] ERROR: socket was not an XPC client.');
|
||||||
socket.close;
|
socket.close;
|
||||||
|
|
||||||
assert(isequal(socket.isClosed(),1),'closeUDP: Error- Could not close socket');
|
%% Track open clients
|
||||||
|
global clients;
|
||||||
|
%TODO: Remove stale clients
|
||||||
|
|
||||||
end
|
end
|
||||||
38
MATLAB/+XPlaneConnect/getDREFs.m
Normal file
38
MATLAB/+XPlaneConnect/getDREFs.m
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
function result = requestDREFs( 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,41 @@
|
|||||||
function [socket] = openUDP(port, varargin)
|
function [ socket ] = openUDP(varargin)
|
||||||
%openUDP Script that opens an UDP Socket
|
%openUDP Initializes a new instance of the XPC client and returns it.
|
||||||
%
|
%
|
||||||
%Inputs
|
%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)
|
% timeout (optional): Optional parameter for time to UDP timeout (in ms)
|
||||||
%Outputs
|
%Outputs
|
||||||
% Socket: UDP Socket
|
% socket: An instance of the XPC client.
|
||||||
%
|
%
|
||||||
% Use
|
% Use
|
||||||
% 1. import XPlaneConnect.*;
|
% 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
|
% 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
|
% Contributors
|
||||||
% [CT] Christopher Teubert (SGT, Inc.)
|
% [CT] Christopher Teubert (SGT, Inc.)
|
||||||
% christopher.a.teubert@nasa.gov
|
% christopher.a.teubert@nasa.gov
|
||||||
%
|
% [JW] Jason Watkins
|
||||||
% To Do
|
% jason.w.watkins@nasa.gov
|
||||||
% 1. Verify Input
|
|
||||||
%
|
|
||||||
% BEGIN CODE
|
|
||||||
|
|
||||||
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
|
%% Create client
|
||||||
socket = DatagramSocket(port);
|
[folder, ~, ~] = fileparts(which('XPlaneConnect.openUDP'));
|
||||||
socket.setSoTimeout(100);
|
javaaddpath([folder, '\XPlaneConnect.jar']);
|
||||||
socket.setReceiveBufferSize(2000);
|
import gov.nasa.xpc.*;
|
||||||
|
socket = XPlaneConnect(p.Results.xpHost, p.Results.xpPort, p.Results.port);
|
||||||
|
|
||||||
%% interpret input
|
%% Track open clients
|
||||||
if ~isempty(varargin)
|
global clients;
|
||||||
if isnumeric(varargin(1))
|
clients = [clients, socket];
|
||||||
socket.setSoTimeout(varargin(1));
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
assert(isequal(socket.isClosed(),0),'openUDP: Error- Could not open port');
|
end
|
||||||
|
|
||||||
end
|
|
||||||
@@ -1,13 +1,9 @@
|
|||||||
function status = pauseSim( pause, varargin )
|
function pauseSim( pause, socket )
|
||||||
%pauseSim pause Simulation
|
%pauseSim Pauses or unpauses X-Plane.
|
||||||
%
|
%
|
||||||
%Inputs
|
%Inputs
|
||||||
% Pause: binary value 0=run, 1=pause
|
% 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)
|
% socket (optional): The client to use when sending the command.
|
||||||
% 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
|
%Use
|
||||||
% 1. import XPlaneConnect.*;
|
% 1. import XPlaneConnect.*;
|
||||||
@@ -16,29 +12,26 @@ function status = pauseSim( pause, varargin )
|
|||||||
% Contributors
|
% Contributors
|
||||||
% [CT] Christopher Teubert (SGT, Inc.)
|
% [CT] Christopher Teubert (SGT, Inc.)
|
||||||
% christopher.a.teubert@nasa.gov
|
% christopher.a.teubert@nasa.gov
|
||||||
%
|
% [JW] Jason Watkins
|
||||||
% To Do
|
% jason.w.watkins@nasa.gov
|
||||||
% 1. Verify Input
|
|
||||||
%
|
|
||||||
%BEGIN CODE
|
|
||||||
|
|
||||||
import XPlaneConnect.*
|
import XPlaneConnect.*
|
||||||
|
|
||||||
%% Handle Input
|
%% Get client
|
||||||
% Optional parameters
|
global clients;
|
||||||
p = inputParser;
|
if ~exist('socket', 'var')
|
||||||
addRequired(p,'pause',@isnumeric);
|
assert(isequal(length(clients) < 2, 1), '[pauseSim] ERROR: Multiple clients open. You must specify which client to use.');
|
||||||
addOptional(p,'IP','127.0.0.1',@ischar);
|
if isempty(clients)
|
||||||
addOptional(p,'port',49009,@isnumeric);
|
socket = openUDP();
|
||||||
parse(p,pause,varargin{:});
|
else
|
||||||
|
socket = clients(1);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
% Check format of input-TODO
|
%% Validate input
|
||||||
|
pause = logical(pause);
|
||||||
|
|
||||||
%% BODY
|
%% Send command
|
||||||
message = zeros(1,6);
|
socket.pauseSim(pause);
|
||||||
|
|
||||||
message(1:4) = 'SIMU'-0;
|
|
||||||
message(6) = uint8(p.Results.pause);
|
|
||||||
|
|
||||||
status = sendUDP(message, p.Results.IP, p.Results.port);
|
|
||||||
end
|
end
|
||||||
@@ -1,9 +1,8 @@
|
|||||||
function [ sensor ] = readDATA( socket )
|
function [ result ] = readDATA( socket )
|
||||||
% readDATA Reads UDP Socket and interprets data
|
% readDATA Reads UDP Socket and interprets data
|
||||||
%
|
%
|
||||||
% Inputs
|
% Inputs
|
||||||
% location: Either an opened UDP Socket or integer port number
|
% socket (optional): The client to read from.
|
||||||
%
|
|
||||||
% Outputs
|
% Outputs
|
||||||
% If data is X-Plane data format:
|
% If data is X-Plane data format:
|
||||||
% data: Matlab X-Plane DATA Structure
|
% 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.
|
% 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
|
% Contributors
|
||||||
% [CT] Christopher Teubert (SGT, Inc.)
|
% Christopher Teubert (SGT, Inc.) <christopher.a.teubert@nasa.gov>
|
||||||
% christopher.a.teubert@nasa.gov
|
% Jason Watkins <jason.w.watkins@nasa.gov>
|
||||||
%
|
|
||||||
% To Do
|
|
||||||
% 1. Verify Input
|
|
||||||
%
|
|
||||||
% BEGIN CODE
|
|
||||||
|
|
||||||
import XPlaneConnect.*
|
import XPlaneConnect.*
|
||||||
|
|
||||||
%% Read UDP Socket
|
%% Get client
|
||||||
[ sensor.raw] = readUDP(socket);
|
global clients;
|
||||||
|
if ~exist('socket', 'var')
|
||||||
%% Interpret Input
|
assert(istrue(length(clients) < 2), '[readDATA] ERROR: Multiple clients open. You must specify which client to use.');
|
||||||
bits = size(sensor.raw);
|
if isempty(clients)
|
||||||
if sensor.raw ~= -998 %If the signal exists
|
socket = openUDP();
|
||||||
header = char(sensor.raw(1:4)');
|
else
|
||||||
if strcmp(header,'DATA') %DATA signal type
|
socket = clients(1);
|
||||||
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;
|
|
||||||
end
|
end
|
||||||
|
|
||||||
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
|
% selectDATA Choose specific X-Plane parameters to be send over UDP
|
||||||
%
|
%
|
||||||
% Inputs
|
% Inputs
|
||||||
% index: An array of the values that to be sent. Corresponds to the numbers on the XPlane Output screen
|
% rows: 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)
|
% socket (optional): The client to use when sending the command.
|
||||||
% 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.
|
|
||||||
%
|
%
|
||||||
% Use
|
% Use
|
||||||
% 1. import XPlaneConnect.*;
|
% 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
|
% 3. status = selectDATA( values, '127.0.0.1', 49005 ); % send to localhose port 49005
|
||||||
%
|
%
|
||||||
% Contributors
|
% Contributors
|
||||||
% [CT] Christopher Teubert (SGT, Inc.)
|
% Christopher Teubert (SGT, Inc.) <christopher.a.teubert@nasa.gov>
|
||||||
% christopher.a.teubert@nasa.gov
|
% Jason Watkins <jason.w.watkins@nasa.gov>
|
||||||
%
|
|
||||||
% To Do
|
|
||||||
% 1. Verify Input
|
|
||||||
%
|
|
||||||
% BEGIN CODE
|
|
||||||
|
|
||||||
import XPlaneConnect.*
|
import XPlaneConnect.*
|
||||||
|
|
||||||
%% Handle Input
|
%% Get client
|
||||||
p = inputParser;
|
global clients;
|
||||||
addRequired(p,'index');
|
if ~exist('socket', 'var')
|
||||||
addOptional(p,'IP','127.0.0.1',@ischar);
|
assert(istrue(length(clients) < 2), '[selectDATA] ERROR: Multiple clients open. You must specify which client to use.');
|
||||||
addOptional(p,'port',49009,@isnumeric);
|
if isempty(clients)
|
||||||
parse(p,index,varargin{:});
|
socket = openUDP();
|
||||||
|
else
|
||||||
%% BODY
|
socket = clients(1);
|
||||||
dataString = ['DSEL'-0,0];
|
|
||||||
for i=1:length(index)
|
|
||||||
dataString = [dataString, p.Results.index(i), 0, 0, 0];
|
|
||||||
end
|
end
|
||||||
status = sendUDP(dataStream, p.Results.IP, p.Results.port);
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
%% Validate input
|
||||||
|
rows = int32(rows);
|
||||||
|
|
||||||
|
%% Send command
|
||||||
|
socket.selectDATA(rows);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
function [ status ] = sendCTRL( ctrl, acft, IP, port )
|
function sendCTRL( ctrl, ac, socket )
|
||||||
% sendCTRL Send X-Plane Aircraft Control Commands over UDP
|
% sendCTRL Sends command to X-Plane setting control surfaces on the specified aircraft.
|
||||||
%
|
%
|
||||||
% Inputs
|
% Inputs
|
||||||
% ctrl: control array where the elements are as follows:
|
% ctrl: control array where the elements are as follows:
|
||||||
@@ -9,56 +9,45 @@ function [ status ] = sendCTRL( ctrl, acft, IP, port )
|
|||||||
% 4. Throttle [-1, 1]
|
% 4. Throttle [-1, 1]
|
||||||
% 5. Gear (0=up, 1=down)
|
% 5. Gear (0=up, 1=down)
|
||||||
% 6. Flaps [0, 1]
|
% 6. Flaps [0, 1]
|
||||||
% acft (optional): Aircraft # (default is 0; 0 = own aircraft)
|
% ac (optional): The aircraft to set. 0 for the player 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)
|
% socket (optional): The client to use when sending the command.
|
||||||
% 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
|
% Outputs
|
||||||
% status: If there was an error. Status<0 means there was an error.
|
% status: If there was an error. Status<0 means there was an error.
|
||||||
%
|
%
|
||||||
% Use
|
% Use
|
||||||
% 1. import XPlaneConnect.*;
|
% 1. import XPlaneConnect.*;
|
||||||
% 2. #Send the data array to port 49009 on the computer at IP address 172.0.100.54.
|
% 2. socket = openUDP();
|
||||||
% 3. status = sendCTRL([0, 0, 0, 0.8, 0, 1], 1, '172.0.100.54',49009);
|
% 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
|
% Contributors
|
||||||
% [CT] Christopher Teubert (SGT, Inc.)
|
% Christopher Teubert (SGT, Inc.) <christopher.a.teubert@nasa.gov>
|
||||||
% christopher.a.teubert@nasa.gov
|
% Jason Watkins <jason.w.watkins@nasa.gov>
|
||||||
%
|
|
||||||
% To Do
|
|
||||||
% 1. Verify Input
|
|
||||||
%
|
|
||||||
% BEGIN CODE
|
|
||||||
|
|
||||||
import XPlaneConnect.*
|
import XPlaneConnect.*
|
||||||
|
|
||||||
%% Handle Input
|
%% Get client
|
||||||
% Optional parameters
|
global clients;
|
||||||
if ~exist('IP','var'), IP = '127.0.0.1'; end
|
if ~exist('socket', 'var')
|
||||||
if ~exist('port','var'), port = 49009; end
|
assert(isequal(length(clients) < 2, 1), '[sendCTRL] ERROR: Multiple clients open. You must specify which client to use.');
|
||||||
if ~exist('acft','var'), acft = 0; end
|
if isempty(clients)
|
||||||
|
socket = openUDP();
|
||||||
% Check format of input-TODO
|
else
|
||||||
|
socket = clients(1);
|
||||||
%%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);
|
|
||||||
end
|
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
|
end
|
||||||
|
|
||||||
|
%% Validate input
|
||||||
|
ctrl = single(ctrl);
|
||||||
|
if ~exist('ac', 'var')
|
||||||
|
ac = 0;
|
||||||
|
end
|
||||||
|
ac = logical(ac);
|
||||||
|
|
||||||
|
%% Send command
|
||||||
|
socket.sendCTRL(ctrl, ac);
|
||||||
|
|
||||||
|
end
|
||||||
@@ -1,15 +1,11 @@
|
|||||||
function [ status ] = sendDATA(data, varargin)
|
function sendDATA(data, socket)
|
||||||
% sendDATA Send X-Plane formatted DATA over UDP
|
% sendDATA Send X-Plane formatted DATA over UDP
|
||||||
%
|
%
|
||||||
% Inputs
|
% Inputs
|
||||||
% data: X-Plane formatted data. Is a matlab structure with the following fields:
|
% 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.
|
% .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,:))
|
% .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)
|
% socket (optional): The client to use when sending the command.
|
||||||
% 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
|
|
||||||
%
|
%
|
||||||
% Use
|
% Use
|
||||||
% 1. import XPlaneConnect.*;
|
% 1. import XPlaneConnect.*;
|
||||||
@@ -29,29 +25,23 @@ function [ status ] = sendDATA(data, varargin)
|
|||||||
|
|
||||||
import XPlaneConnect.*
|
import XPlaneConnect.*
|
||||||
|
|
||||||
%% Handle Input
|
%% Get client
|
||||||
p = inputParser;
|
global clients;
|
||||||
addRequired(p,'data');
|
if ~exist('socket', 'var')
|
||||||
addOptional(p,'IP','127.0.0.1',@ischar);
|
assert(isequal(length(clients) < 2, 1), '[sendDATA] ERROR: Multiple clients open. You must specify which client to use.');
|
||||||
addOptional(p,'port',49009,@isnumeric);
|
if isempty(clients)
|
||||||
parse(p,data,varargin{:});
|
socket = openUDP();
|
||||||
|
|
||||||
%% 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);
|
|
||||||
else
|
else
|
||||||
disp('Warning in sendDATA: Sending empty dataStream')
|
socket = clients(1);
|
||||||
status = -2;
|
|
||||||
end
|
end
|
||||||
|
|
||||||
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 +0,0 @@
|
|||||||
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
|
|
||||||
%
|
|
||||||
% 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.
|
|
||||||
%
|
|
||||||
% Use
|
|
||||||
% 1. import XPlaneConnect.*
|
|
||||||
% 2. dataRef = 'sim/aircraft/parts/acf_gear_deploy'; // Landing Gear
|
|
||||||
% 3. Value = 0;
|
|
||||||
% 4. status = sendDREF(dataRef, Value);
|
|
||||||
%
|
|
||||||
% Contributors
|
|
||||||
% [CT] Christopher Teubert (SGT, Inc.)
|
|
||||||
% christopher.a.teubert@nasa.gov
|
|
||||||
%
|
|
||||||
% To Do
|
|
||||||
% 1. Verify Input
|
|
||||||
%
|
|
||||||
% BEGIN CODE
|
|
||||||
|
|
||||||
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{:});
|
|
||||||
|
|
||||||
%% 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');
|
|
||||||
|
|
||||||
% Send DREF
|
|
||||||
if length(dataStream) > 5
|
|
||||||
status = sendUDP(dataStream, p.Results.IP, p.Results.port);
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
function [ status ] = sendPOSI( posi, varargin )
|
function sendPOSI( posi, ac, socket )
|
||||||
% sendPOSI Send X-Plane Aircraft Position over UDP
|
% sendPOSI Sets the position of the specified aircraft.
|
||||||
%
|
%
|
||||||
% Inputs
|
% Inputs
|
||||||
% posi: Position array where the elements are as follows:
|
% posi: Position array where the elements are as follows:
|
||||||
@@ -10,52 +10,43 @@ function [ status ] = sendPOSI( posi, varargin )
|
|||||||
% 5. Pitch (deg)
|
% 5. Pitch (deg)
|
||||||
% 6. True Heading (deg)
|
% 6. True Heading (deg)
|
||||||
% 7. Gear (0=up, 1=down)
|
% 7. Gear (0=up, 1=down)
|
||||||
% acft (optional): Aircraft # (default is 0; 0 = own aircraft)
|
% acft (optional): The aircraft to set. 0 for the player 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)
|
% socket (optional): The client to use when sending the command.
|
||||||
% 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.
|
|
||||||
%
|
%
|
||||||
% Use
|
% Use
|
||||||
% 1. import XPlaneConnect.*;
|
% 1. import XPlaneConnect.*;
|
||||||
% 2. #Send the data array to port 49009 on the computer at IP address 172.0.100.54.
|
% 2. sendPOSI([37.5242422, -122.06899, 2500, 0, 0, 0, 1], 1);
|
||||||
% 3. status = sendPOSI([37.5242422, -122.06899, 2500, 0, 0, 0, 1], 1, '172.0.100.54');
|
|
||||||
%
|
%
|
||||||
% 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
|
% Contributors
|
||||||
% [CT] Christopher Teubert (SGT, Inc.)
|
% [CT] Christopher Teubert (SGT, Inc.)
|
||||||
% christopher.a.teubert@nasa.gov
|
% christopher.a.teubert@nasa.gov
|
||||||
%
|
% [JW] Jason Watkins
|
||||||
% To Do
|
% jason.w.watkins@nasa.gov
|
||||||
%
|
|
||||||
% BEGIN CODE
|
|
||||||
|
|
||||||
import XPlaneConnect.*
|
import XPlaneConnect.*
|
||||||
|
|
||||||
%% Handle Input
|
%% Get client
|
||||||
p = inputParser;
|
global clients;
|
||||||
addRequired(p,'posi');
|
if ~exist('socket', 'var')
|
||||||
addOptional(p,'acft',0,@isnumeric);
|
assert(isequal(length(clients) < 2, 1), '[sendPOSI] ERROR: Multiple clients open. You must specify which client to use.');
|
||||||
addOptional(p,'IP','127.0.0.1',@ischar);
|
if isempty(clients)
|
||||||
addOptional(p,'port',49009,@isnumeric);
|
socket = openUDP();
|
||||||
parse(p,posi,varargin{:});
|
else
|
||||||
|
socket = clients(1);
|
||||||
%% 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);
|
|
||||||
end
|
end
|
||||||
dataStream = [dataStream, typecast(single(position),'uint8')];
|
|
||||||
|
|
||||||
% Send POSI
|
|
||||||
status = sendUDP(dataStream, p.Results.IP, p.Results.port);
|
|
||||||
|
|
||||||
end
|
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.
|
% sendTEXT Sends a string to be displayed in X-Plane.
|
||||||
%
|
%
|
||||||
% Inputs
|
% Inputs
|
||||||
@@ -13,35 +13,35 @@ function [ status ] = sendTEXT( msg, varargin )
|
|||||||
%
|
%
|
||||||
% Use
|
% Use
|
||||||
% 1. import XPlaneConnect.*;
|
% 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);
|
% 3. status = sendTEXT('Some text', 512, 600);
|
||||||
%
|
%
|
||||||
% Contributors
|
% Contributors
|
||||||
% Jason Watkins
|
% Jason Watkins (jason.w.watkins@nasa.gov)
|
||||||
% jason.w.watkins@nasa.gov
|
|
||||||
%
|
|
||||||
% To Do
|
|
||||||
%
|
|
||||||
% BEGIN CODE
|
|
||||||
|
|
||||||
import XPlaneConnect.*
|
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
|
%% Get client
|
||||||
header = ['TEXT'-0,0];
|
global clients;
|
||||||
dataStream = [header,...
|
if ~exist('socket', 'var')
|
||||||
typecast(uint32(p.Results.x), 'uint8'),...
|
assert(isequal(length(clients) < 2, 1), '[sendTEXT] ERROR: Multiple clients open. You must specify which client to use.');
|
||||||
typecast(uint32(p.Results.y), 'uint8'),...
|
if isempty(clients)
|
||||||
uint8(length(msg)), msg-0];
|
socket = openUDP();
|
||||||
|
else
|
||||||
% Send TEXT
|
socket = clients(1);
|
||||||
status = sendUDP(dataStream, p.Results.IP, p.Results.port);
|
end
|
||||||
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,55 @@
|
|||||||
function [ status ] = sendWYPT( op, points, varargin )
|
function sendWYPT( op, points, socket )
|
||||||
% sendWYPT Adds, removes, or clears a set of waypoints to be rendered in
|
% sendWYPT Adds, removes, or clears a set of waypoints to be rendered in
|
||||||
% the simulator.
|
% the simulator.
|
||||||
%
|
%
|
||||||
% Inputs
|
% Inputs
|
||||||
% msg: The string to be displayed
|
% op: The operation to perform. 1=add, 2=remove, 3=clear.
|
||||||
% x (optional): The distance from the left edge of the screen to display the message.
|
% points: An array of values representing points. Each triplet in the
|
||||||
% y (optional): The distance from the bottom edge of the screen to display the message.
|
% array will be interpreted as a (Lat, Lon, Alt) point.
|
||||||
% 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)
|
% socket (optional): The client to use when sending the command.
|
||||||
% 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.
|
|
||||||
%
|
%
|
||||||
% Use
|
% Use
|
||||||
% 1. import XPlaneConnect.*;
|
% 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);
|
% 3. status = sendTEXT('Some text', 512, 600);
|
||||||
%
|
%
|
||||||
% Contributors
|
% Contributors
|
||||||
% Jason Watkins
|
% Jason Watkins (jason.w.watkins@nasa.gov)
|
||||||
% jason.w.watkins@nasa.gov
|
|
||||||
%
|
%
|
||||||
% To Do
|
% To Do
|
||||||
%
|
%
|
||||||
% BEGIN CODE
|
% BEGIN CODE
|
||||||
|
|
||||||
import XPlaneConnect.*
|
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
|
%% Get client
|
||||||
len = uint32(length(points));
|
global clients;
|
||||||
assert(op > 0 && op < 4);
|
if ~exist('socket', 'var')
|
||||||
assert(mod(len, 3) == 0);
|
assert(isequal(length(clients) < 2, 1), '[sendWYPT] ERROR: Multiple clients open. You must specify which client to use.');
|
||||||
assert(len / 3 < 20);
|
if isempty(clients)
|
||||||
|
socket = openUDP();
|
||||||
%% Body
|
else
|
||||||
header = ['WYPT'-0,0];
|
socket = clients(1);
|
||||||
dataStream = [header,...
|
end
|
||||||
uint8(op),...
|
|
||||||
uint8(len / 3),...
|
|
||||||
typecast(single(points), 'uint8')];
|
|
||||||
|
|
||||||
% Send TEXT
|
|
||||||
status = sendUDP(dataStream, p.Results.IP, p.Results.port);
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
%% Get WaypointOp class
|
||||||
|
[folder, ~, ~] = fileparts(which('XPlaneConnect.openUDP'));
|
||||||
|
javaaddpath([folder, '\XPlaneConnect.jar']);
|
||||||
|
import gov.nasa.xpc.*;
|
||||||
|
|
||||||
|
%% Validate input
|
||||||
|
len = uint32(length(points));
|
||||||
|
assert(op > 0 && op < 4);
|
||||||
|
wyptOp = WaypointOp.Add;
|
||||||
|
if isequal(op, 2)
|
||||||
|
wyptOp = WaypointOp.Del;
|
||||||
|
elseif isequal(op, 3)
|
||||||
|
wyptOp = WaypointOp.Clr;
|
||||||
|
end
|
||||||
|
assert(mod(len, 3) == 0);
|
||||||
|
|
||||||
|
%% Send command
|
||||||
|
socket.sendWYPT(wyptOp, points);
|
||||||
|
|
||||||
|
end
|
||||||
@@ -1,51 +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
|
% setConn Send a command to set up the port where you will receive data on
|
||||||
% this computer.
|
% this computer.
|
||||||
%
|
%
|
||||||
% Inputs
|
% Inputs
|
||||||
% Receiving Port: Port that data will be sent to in the future for this connection
|
% 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)
|
% socket (optional): The client to use when sending the command.
|
||||||
% 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.
|
|
||||||
%
|
%
|
||||||
% Use
|
% Use
|
||||||
% 1. import XPlaneConnect.*
|
% 1. import XPlaneConnect.*
|
||||||
% 2. status = setConn(49011);
|
% 2. status = setConn(49011);
|
||||||
%
|
%
|
||||||
% Contributors
|
% Contributors
|
||||||
% [CT] Christopher Teubert (SGT, Inc.)
|
% Christopher Teubert (SGT, Inc.) <christopher.a.teubert@nasa.gov>
|
||||||
% christopher.a.teubert@nasa.gov
|
% Jason Watkins <jason.w.watkins@nasa.gov>
|
||||||
%
|
|
||||||
% To Do
|
|
||||||
% 1. Verify Input
|
|
||||||
%
|
|
||||||
% BEGIN CODE
|
|
||||||
import XPlaneConnect.*
|
|
||||||
|
|
||||||
status = 0;
|
import XPlaneConnect.*
|
||||||
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
|
|
||||||
|
|
||||||
% 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
|
%% Validate input
|
||||||
% Header
|
port = int32(port);
|
||||||
message(1:4) = 'CONN'-0;
|
|
||||||
|
%% Send command
|
||||||
% RecvPort
|
socket.setCONN(port);
|
||||||
message(6:7) = typecast(uint16(recvPort),'uint8');
|
|
||||||
|
|
||||||
% Send
|
|
||||||
sendUDP(message,IP,port);
|
|
||||||
|
|
||||||
global udpReadPort;
|
|
||||||
udpReadPort = recvPort;
|
|
||||||
readUDP(); % Read and discard CONF message
|
|
||||||
|
|
||||||
end
|
end
|
||||||
38
MATLAB/+XPlaneConnect/setDREF.m
Normal file
38
MATLAB/+XPlaneConnect/setDREF.m
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
function setDREF( dref, value, socket )
|
||||||
|
% sendDREF Sends a command to X-Plane that sets the given DREF.
|
||||||
|
%
|
||||||
|
% Inputs
|
||||||
|
% 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 = setDREF(dataRef, Value);
|
||||||
|
%
|
||||||
|
% 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), '[setDREF] ERROR: Multiple clients open. You must specify which client to use.');
|
||||||
|
if isempty(clients)
|
||||||
|
socket = openUDP();
|
||||||
|
else
|
||||||
|
socket = clients(1);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
%% Validate input
|
||||||
|
value = single(value);
|
||||||
|
|
||||||
|
%%Send command
|
||||||
|
socket.setDREF(dref, value);
|
||||||
@@ -22,6 +22,9 @@
|
|||||||
<ClCompile Include="..\..\C\src\xplaneConnect.c" />
|
<ClCompile Include="..\..\C\src\xplaneConnect.c" />
|
||||||
<ClCompile Include="..\C Tests\main.c" />
|
<ClCompile Include="..\C Tests\main.c" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="..\..\C\src\xplaneConnect.h" />
|
||||||
|
</ItemGroup>
|
||||||
<PropertyGroup Label="Globals">
|
<PropertyGroup Label="Globals">
|
||||||
<ProjectGuid>{BC701AF4-552C-4C9D-82A1-B352542783A4}</ProjectGuid>
|
<ProjectGuid>{BC701AF4-552C-4C9D-82A1-B352542783A4}</ProjectGuid>
|
||||||
<RootNamespace>CTests</RootNamespace>
|
<RootNamespace>CTests</RootNamespace>
|
||||||
|
|||||||
@@ -22,4 +22,9 @@
|
|||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="..\..\C\src\xplaneConnect.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
@@ -16,12 +16,10 @@
|
|||||||
int testFailed = 0;
|
int testFailed = 0;
|
||||||
int testPassed = 0;
|
int testPassed = 0;
|
||||||
|
|
||||||
void runTest(short (*f)())
|
void runTest(int (*test)(), char* name)
|
||||||
{
|
{
|
||||||
short result;
|
int result = test(); // Run Test
|
||||||
|
printf("Test %i: %s - ", testPassed + testFailed + 1, name);
|
||||||
printf("Test %i: ",testPassed+testFailed+1);
|
|
||||||
result = (*f)(); // Run Test
|
|
||||||
if (result == 0)
|
if (result == 0)
|
||||||
{
|
{
|
||||||
printf("PASSED\n");
|
printf("PASSED\n");
|
||||||
@@ -34,63 +32,54 @@ void runTest(short (*f)())
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
short openTest() // openUDP Test
|
int openTest() // openUDP Test
|
||||||
{
|
{
|
||||||
printf("openUDP - ");
|
XPCSocket sock = openUDP("127.0.0.1", 49009, 49062);
|
||||||
struct xpcSocket sendPort = openUDP( 49062, "127.0.0.1", 49009 );
|
closeUDP(sock);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
short closeTest() // closeUDP test
|
int closeTest() // closeUDP test
|
||||||
{
|
{
|
||||||
printf("closeUDP - ");
|
XPCSocket sendPort = openUDP("127.0.0.1", 49009, 49063);
|
||||||
struct xpcSocket sendPort = openUDP( 49063, "127.0.0.1", 49009 );
|
|
||||||
closeUDP(sendPort);
|
closeUDP(sendPort);
|
||||||
sendPort = openUDP(49063, "127.0.0.1", 49009);
|
sendPort = openUDP("127.0.0.1", 49009, 49063);
|
||||||
closeUDP(sendPort);
|
closeUDP(sendPort);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
short sendReadTest() // send/read Test
|
int sendReadTest() // send/read Test
|
||||||
{
|
{
|
||||||
printf("send/readUDP - ");
|
|
||||||
|
|
||||||
// Initialization
|
// Initialization
|
||||||
int i; // Iterator
|
|
||||||
char test[] = {0, 1, 2, 3, 5};
|
char test[] = {0, 1, 2, 3, 5};
|
||||||
char buf[5] = {0};
|
char buf[5] = {0};
|
||||||
struct xpcSocket sendPort, recvPort;
|
XPCSocket outSock = openUDP("127.0.0.1", 49063, 49064);
|
||||||
|
XPCSocket inSock = openUDP("127.0.0.1", 49009, 49063);
|
||||||
// Setup
|
|
||||||
sendPort = openUDP( 49064, "127.0.0.1", 49063 );
|
|
||||||
recvPort = openUDP( 49063, "127.0.0.1", 49009 );
|
|
||||||
|
|
||||||
// Execution
|
// Execution
|
||||||
sendUDP( sendPort, test, sizeof(test) );
|
sendUDP(outSock, test, sizeof(test));
|
||||||
readUDP( recvPort, buf, NULL ); // Test
|
readUDP(inSock, buf, sizeof(buf), NULL);
|
||||||
|
|
||||||
// Close
|
// Close
|
||||||
closeUDP(sendPort);
|
closeUDP(outSock);
|
||||||
closeUDP(recvPort);
|
closeUDP(inSock);
|
||||||
|
|
||||||
// Tests
|
// Tests
|
||||||
for (i=0; i<4; i++)
|
for (int i = 0; i < sizeof(buf); i++)
|
||||||
{
|
{
|
||||||
if (test[i] != buf[i]) // Not received correctly
|
if (test[i] != buf[i]) // Not received correctly
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
short sendTEXTTest()
|
int sendTEXTTest()
|
||||||
{
|
{
|
||||||
printf("sendTEXT - ");
|
|
||||||
|
|
||||||
// Setup
|
// Setup
|
||||||
struct xpcSocket sendPort = openUDP(49064, "127.0.0.1", 49009);
|
XPCSocket sendPort = openUDP("127.0.0.1", 49009, 49064);
|
||||||
int x = 100;
|
int x = 100;
|
||||||
int y = 700;
|
int y = 700;
|
||||||
char* msg = "XPlaneConnect test message. Now with 100% fewer new lines!";
|
char* msg = "XPlaneConnect test message. Now with 100% fewer new lines!";
|
||||||
@@ -104,262 +93,177 @@ short sendTEXTTest()
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
short requestDREFTest() // Request DREF Test (Required for next tests)
|
int requestDREFTest() // Request DREF Test (Required for next tests)
|
||||||
{
|
{
|
||||||
printf("requestDREF - ");
|
|
||||||
|
|
||||||
// Initialization
|
// Initialization
|
||||||
int i; // Iterator
|
char* drefs[100] =
|
||||||
char DREFArray[100][100];
|
{
|
||||||
float *recDATA[100];
|
"sim/cockpit/switches/gear_handle_status",
|
||||||
short DREFSizes[100];
|
"sim/cockpit2/switches/panel_brightness_ratio"
|
||||||
struct xpcSocket sendPort, recvPort;
|
};
|
||||||
short result = 0;
|
float* data[100];
|
||||||
|
int sizes[100];
|
||||||
|
XPCSocket sock = openUDP("127.0.0.1", 49009, 49064);
|
||||||
|
|
||||||
// Setup
|
// Setup
|
||||||
for (i = 0; i < 100; i++) {
|
for (int i = 0; i < 100; ++i)
|
||||||
recDATA[i] = (float *) malloc(40*sizeof(float));
|
{
|
||||||
memset(DREFArray[i],0,100);
|
data[i] = (float*)malloc(40 * sizeof(float));
|
||||||
}
|
sizes[i] = 40;
|
||||||
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
|
// Execution
|
||||||
result = requestDREF(sendPort, recvPort, DREFArray, DREFSizes, 2, recDATA, DREFSizes);
|
int result = getDREFs(sock, drefs, data, 2, sizes);
|
||||||
|
|
||||||
// Close
|
// Close
|
||||||
closeUDP(sendPort);
|
closeUDP(sock);
|
||||||
closeUDP(recvPort);
|
|
||||||
|
|
||||||
// Tests
|
// Tests
|
||||||
if ( result < 0)// Request 2 values
|
if ( result < 0)// Request 2 values
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (DREFSizes[0] != 1 || DREFSizes[1] != 4)
|
if (sizes[0] != 1 || sizes[1] != 4)
|
||||||
{
|
{
|
||||||
return -2;
|
return -2;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
short sendDREFTest() // sendDREF test
|
int sendDREFTest() // sendDREF test
|
||||||
{
|
{
|
||||||
printf("sendDREF - ");
|
|
||||||
|
|
||||||
// Initialization
|
// Initialization
|
||||||
int i; // Iterator
|
char* drefs[100] =
|
||||||
char DREFArray[100][100];
|
{
|
||||||
float *recDATA[100];
|
"sim/cockpit/switches/gear_handle_status"
|
||||||
short DREFSizes[100];
|
};
|
||||||
float value = 0.0;
|
float* data[100];
|
||||||
struct xpcSocket sendPort, recvPort;
|
int sizes[100];
|
||||||
short result = 0;
|
XPCSocket sock = openUDP("127.0.0.1", 49009, 49066);
|
||||||
|
float value = 1.0F;
|
||||||
// Setup
|
|
||||||
for (i = 0; i < 100; i++) {
|
// Setup
|
||||||
recDATA[i] = (float *) malloc(40*sizeof(float));
|
for (int i = 0; i < 100; ++i)
|
||||||
memset(DREFArray[i],0,100);
|
{
|
||||||
}
|
data[i] = (float*)malloc(40 * sizeof(float));
|
||||||
sendPort = openUDP( 49066, "127.0.0.1", 49009 );
|
sizes[i] = 40;
|
||||||
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
|
// Execution
|
||||||
sendDREF(sendPort, DREFArray[0], DREFSizes[0], &value, 1);
|
setDREF(sock, drefs[0], &value, 1);
|
||||||
result = requestDREF(sendPort, recvPort, DREFArray, DREFSizes, 1, recDATA, DREFSizes);
|
int result = getDREFs(sock, drefs, data, 1, sizes);
|
||||||
|
|
||||||
// Close
|
// Close
|
||||||
closeUDP(sendPort);
|
closeUDP(sock);
|
||||||
closeUDP(recvPort);
|
|
||||||
|
|
||||||
// Tests
|
// Tests
|
||||||
if (result < 0)// Request 1 value
|
if (result < 0)// Request 1 value
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (DREFSizes[0] != 1)
|
if (sizes[0] != 1)
|
||||||
{
|
{
|
||||||
return -2;
|
return -2;
|
||||||
}
|
}
|
||||||
if (*recDATA[0] != value)
|
if (data[0][0] != value)
|
||||||
{
|
{
|
||||||
return -3;
|
return -3;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
short sendDATATest() // sendDATA test
|
int sendDATATest() // sendDATA test
|
||||||
{
|
{
|
||||||
printf("sendData - ");
|
|
||||||
|
|
||||||
// Initialize
|
// Initialize
|
||||||
int i,j; // Iterator
|
int i,j; // Iterator
|
||||||
char DREFArray[100][100];
|
char* drefs[100] =
|
||||||
float data[4][9] = {0};
|
{
|
||||||
float *recDATA[100];
|
"sim/aircraft/parts/acf_gear_deploy"
|
||||||
short DREFSizes[100];
|
};
|
||||||
struct xpcSocket sendPort, recvPort;
|
float* data[100];
|
||||||
short result = 0;
|
int sizes[100];
|
||||||
|
float DATA[4][9];
|
||||||
// Setup
|
XPCSocket sock = openUDP("127.0.0.1", 49009, 49066);
|
||||||
for (i = 0; i < 100; i++) {
|
|
||||||
recDATA[i] = (float *) malloc(40*sizeof(float));
|
// Setup
|
||||||
memset(DREFArray[i],0,100);
|
for (int i = 0; i < 100; ++i)
|
||||||
}
|
{
|
||||||
sendPort = openUDP( 49066, "127.0.0.1", 49009 );
|
data[i] = (float*)malloc(40 * sizeof(float));
|
||||||
recvPort = openUDP( 49008, "127.0.0.1", 49009 );
|
sizes[i] = 40;
|
||||||
strcpy(DREFArray[0],"sim/aircraft/parts/acf_gear_deploy");
|
}
|
||||||
for (i=0;i<1;i++) {
|
for (i = 0; i < 4; i++)
|
||||||
DREFSizes[i] = (int) strlen(DREFArray[i]);
|
{
|
||||||
}
|
for (j = 0; j < 9; j++)
|
||||||
for (i=0;i<4;i++) { // Set array to -999
|
{
|
||||||
for (j=0;j<9;j++) data[i][j] = -999;
|
data[i][j] = -998;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
data[0][0] = 14; // Gear
|
data[0][0] = 14; // Gear
|
||||||
data[0][1] = 1;
|
data[0][1] = 1;
|
||||||
data[0][2] = 0;
|
data[0][2] = 0;
|
||||||
|
|
||||||
// Execution
|
// Execution
|
||||||
sendDATA(sendPort, data, 1); // Gear
|
sendDATA(sock, DATA, 1);
|
||||||
result = requestDREF(sendPort, recvPort, DREFArray, DREFSizes, 1, recDATA, DREFSizes); // Test
|
int result = getDREFs(sock, drefs, data, 1, sizes);
|
||||||
|
|
||||||
// Close
|
// Close
|
||||||
closeUDP(sendPort);
|
closeUDP(sock);
|
||||||
closeUDP(recvPort);
|
|
||||||
|
|
||||||
// Tests
|
// Tests
|
||||||
if ( result < 0 )// Request 1 value
|
if ( result < 0 )// Request 1 value
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (DREFSizes[0] != 10)
|
if (sizes[0] != 10)
|
||||||
{
|
{
|
||||||
return -2;
|
return -2;
|
||||||
}
|
}
|
||||||
if (*recDATA[0] != data[0][1])
|
if (*data[0] != data[0][1])
|
||||||
{
|
{
|
||||||
return -3;
|
return -3;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
short sendCTRLTest() // sendCTRL test
|
int psendCTRLTest() // sendCTRL test
|
||||||
{
|
{
|
||||||
printf("sendCTRL - ");
|
|
||||||
|
|
||||||
// Initialize
|
// Initialize
|
||||||
int i; // Iterator
|
char* drefs[100] =
|
||||||
char DREFArray[100][100];
|
{
|
||||||
float CTRL[6] = { 0.0 };
|
"sim/cockpit2/controls/yoke_pitch_ratio",
|
||||||
float *recDATA[100];
|
"sim/cockpit2/controls/yoke_roll_ratio",
|
||||||
short DREFSizes[100];
|
"sim/cockpit2/controls/yoke_heading_ratio",
|
||||||
struct xpcSocket sendPort, recvPort;
|
"sim/flightmodel/engine/ENGN_thro",
|
||||||
short result;
|
"sim/cockpit/switches/gear_handle_status",
|
||||||
|
"sim/flightmodel/controls/flaprqst"
|
||||||
|
};
|
||||||
|
float* data[100];
|
||||||
|
int sizes[100];
|
||||||
|
float CTRL[6] = { 0.0F, 0.0F, 0.0F, 0.8F, 1.0F, 0.5F };
|
||||||
|
XPCSocket sock = openUDP("127.0.0.1", 49009, 49066);
|
||||||
|
|
||||||
// Setup
|
// Setup
|
||||||
for (i = 0; i < 100; i++) {
|
for (int i = 0; i < 100; i++)
|
||||||
recDATA[i] = (float *)malloc(40 * sizeof(float));
|
{
|
||||||
memset(DREFArray[i], 0, 100);
|
data[i] = (float*)malloc(40 * sizeof(float));
|
||||||
|
sizes[i] = 40;
|
||||||
}
|
}
|
||||||
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; // Gear
|
|
||||||
CTRL[5] = 0.5; // Flaps
|
|
||||||
|
|
||||||
// Execute
|
// Execute
|
||||||
sendCTRL(sendPort, 6, CTRL);
|
psendCTRL(sock, CTRL, 6);
|
||||||
result = requestDREF(sendPort, recvPort, DREFArray, DREFSizes, 6, recDATA, DREFSizes); // Test
|
int result = getDREFs(sock, drefs, data, 6, sizes);
|
||||||
|
|
||||||
// Close
|
// Close socket
|
||||||
closeUDP(sendPort);
|
closeUDP(sock);
|
||||||
closeUDP(recvPort);
|
|
||||||
|
|
||||||
// Tests
|
// Tests
|
||||||
if (result < 0)// Request 1 value
|
if (result < 0)// Request 1 value
|
||||||
{
|
{
|
||||||
return -6;
|
return -6;
|
||||||
}
|
}
|
||||||
for (i = 0; i<6; i++)
|
for (int i = 0; i < 6; i++)
|
||||||
{
|
{
|
||||||
if (fabs(recDATA[i][0] - CTRL[i])>1e-4)
|
if (fabs(data[i][0] - CTRL[i]) > 1e-4)
|
||||||
{
|
|
||||||
return -i - 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
short sendpCTRLTest()
|
|
||||||
{
|
|
||||||
printf("sendNonPlayerCTRL - ");
|
|
||||||
|
|
||||||
// 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/multiplayer/position/plane1_yolk_pitch");
|
|
||||||
strcpy(DREFArray[1], "sim/multiplayer/position/plane1_yolk_roll");
|
|
||||||
strcpy(DREFArray[2], "sim/multiplayer/position/plane1_yolk_yaw");
|
|
||||||
strcpy(DREFArray[3], "sim/multiplayer/position/plane1_throttle");
|
|
||||||
strcpy(DREFArray[4], "sim/multiplayer/position/plane1_gear_deploy");
|
|
||||||
strcpy(DREFArray[5], "sim/multiplayer/position/plane1_flap_ratio");
|
|
||||||
for (i = 0; i < 100; i++)
|
|
||||||
{
|
|
||||||
DREFSizes[i] = (int)strlen(DREFArray[i]);
|
|
||||||
}
|
|
||||||
CTRL[3] = 0.8; // Throttle
|
|
||||||
CTRL[4] = 1; // Gear
|
|
||||||
CTRL[5] = 0.5; // Flaps
|
|
||||||
|
|
||||||
// Execute
|
|
||||||
sendpCTRL(sendPort, 6, CTRL, 1);
|
|
||||||
result = requestDREF(sendPort, recvPort, DREFArray, DREFSizes, 9, recDATA, DREFSizes); // Test
|
|
||||||
|
|
||||||
// Close
|
|
||||||
closeUDP(sendPort);
|
|
||||||
closeUDP(recvPort);
|
|
||||||
|
|
||||||
// Tests
|
|
||||||
if (result < 0)// Request 1 value
|
|
||||||
{
|
|
||||||
return -6;
|
|
||||||
}
|
|
||||||
for (i = 0; i<6; i++)
|
|
||||||
{
|
|
||||||
if (fabs(recDATA[i][0] - CTRL[i])>1e-4)
|
|
||||||
{
|
{
|
||||||
return -i - 1;
|
return -i - 1;
|
||||||
}
|
}
|
||||||
@@ -368,51 +272,85 @@ short sendpCTRLTest()
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
short sendPOSITest() // sendPOSI test
|
int sendCTRLTest()
|
||||||
|
{
|
||||||
|
// Initialize
|
||||||
|
char* drefs[100] =
|
||||||
|
{
|
||||||
|
"sim/multiplayer/position/plane1_yolk_pitch",
|
||||||
|
"sim/multiplayer/position/plane1_yolk_roll",
|
||||||
|
"sim/multiplayer/position/plane1_yolk_yaw",
|
||||||
|
"sim/multiplayer/position/plane1_throttle",
|
||||||
|
"sim/multiplayer/position/plane1_gear_deploy",
|
||||||
|
"sim/multiplayer/position/plane1_flap_ratio",
|
||||||
|
};
|
||||||
|
float* data[100];
|
||||||
|
int sizes[100];
|
||||||
|
float CTRL[6] = { 0.0F, 0.0F, 0.0F, 0.8F, 1.0F, 0.5F };
|
||||||
|
XPCSocket sock = openUDP("127.0.0.1", 49009, 49066);
|
||||||
|
|
||||||
|
// Setup
|
||||||
|
for (int i = 0; i < 100; i++)
|
||||||
|
{
|
||||||
|
data[i] = (float*)malloc(40 * sizeof(float));
|
||||||
|
sizes[i] = 40;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Execute
|
||||||
|
sendCTRL(sock, CTRL, 6, 1);
|
||||||
|
int result = getDREFs(sock, drefs, data, 6, sizes);
|
||||||
|
|
||||||
|
// Close socket
|
||||||
|
closeUDP(sock);
|
||||||
|
|
||||||
|
// Tests
|
||||||
|
if (result < 0)// Request 1 value
|
||||||
|
{
|
||||||
|
return -6;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < 6; i++)
|
||||||
|
{
|
||||||
|
if (fabs(data[i][0] - CTRL[i]) > 1e-4)
|
||||||
|
{
|
||||||
|
return -i - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sendPOSITest() // sendPOSI test
|
||||||
{
|
{
|
||||||
printf("sendPOSI - ");
|
|
||||||
|
|
||||||
// Initialization
|
// Initialization
|
||||||
int i; // Iterator
|
int i; // Iterator
|
||||||
char DREFArray[100][100];
|
char* drefs[100] =
|
||||||
float POSI[8] = {0.0};
|
{
|
||||||
float *recDATA[100];
|
"sim/flightmodel/position/latitude",
|
||||||
short DREFSizes[100];
|
"sim/flightmodel/position/longitude",
|
||||||
struct xpcSocket sendPort, recvPort;
|
"sim/flightmodel/position/y_agl",
|
||||||
short result;
|
"sim/flightmodel/position/phi",
|
||||||
|
"sim/flightmodel/position/theta",
|
||||||
|
"sim/flightmodel/position/psi",
|
||||||
|
"sim/cockpit/switches/gear_handle_status"
|
||||||
|
};
|
||||||
|
float* data[100];
|
||||||
|
int sizes[100];
|
||||||
|
float POSI[8] = { 37.524F, -122.06899F, 2500, 0, 0, 0, 1 };
|
||||||
|
XPCSocket sock = openUDP("127.0.0.1", 49009, 49063);
|
||||||
|
|
||||||
// Setup
|
// Setup
|
||||||
for (i = 0; i < 100; i++) {
|
for (i = 0; i < 100; i++)
|
||||||
recDATA[i] = (float *) malloc(40*sizeof(float));
|
{
|
||||||
memset(DREFArray[i],0,100);
|
data[i] = (float*)malloc(40 * sizeof(float));
|
||||||
|
sizes[i] = 40;
|
||||||
}
|
}
|
||||||
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
|
// Execution
|
||||||
sendPOSI( sendPort, 0, 7, POSI );
|
sendPOSI(sock, POSI, 7, 0);
|
||||||
result = requestDREF(sendPort, recvPort, DREFArray, DREFSizes, 7, recDATA, DREFSizes); // Test
|
int result = getDREFs(sock, drefs, data, 7, sizes);
|
||||||
|
|
||||||
// Close
|
// Close
|
||||||
closeUDP(sendPort);
|
closeUDP(sock);
|
||||||
closeUDP(recvPort);
|
|
||||||
|
|
||||||
// Tests
|
// Tests
|
||||||
if ( result < 0 )// Request 1 value
|
if ( result < 0 )// Request 1 value
|
||||||
@@ -421,114 +359,104 @@ short sendPOSITest() // sendPOSI test
|
|||||||
}
|
}
|
||||||
for (i=0;i<7-1;i++)
|
for (i=0;i<7-1;i++)
|
||||||
{
|
{
|
||||||
if (i==2)
|
if (i == 2)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (fabs(recDATA[i][0]-POSI[i])>1e-4)
|
if (fabs(data[i][0] - POSI[i]) > 1e-4)
|
||||||
{
|
{
|
||||||
return -i;
|
return -i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
short sendWYPTTest()
|
int sendWYPTTest()
|
||||||
{
|
{
|
||||||
printf("sendWYPT - ");
|
|
||||||
|
|
||||||
// Setup
|
// Setup
|
||||||
struct xpcSocket sendPort = openUDP(49064, "127.0.0.1", 49009);
|
XPCSocket sock = openUDP("127.0.0.1", 49009, 49064);
|
||||||
float points[] =
|
float points[] =
|
||||||
{
|
{
|
||||||
37.5245, -122.06899, 2500,
|
37.5245F, -122.06899F, 2500,
|
||||||
37.455397, -122.050037, 2500,
|
37.455397F, -122.050037F, 2500,
|
||||||
37.469567, -122.051411, 2500,
|
37.469567F, -122.051411F, 2500,
|
||||||
37.479376, -122.060509, 2300,
|
37.479376F, -122.060509F, 2300,
|
||||||
37.482237, -122.076130, 2100,
|
37.482237F, -122.076130F, 2100,
|
||||||
37.474881, -122.087288, 1900,
|
37.474881F, -122.087288F, 1900,
|
||||||
37.467660, -122.079391, 1700,
|
37.467660F, -122.079391F, 1700,
|
||||||
37.466298, -122.090549, 1500,
|
37.466298F, -122.090549F, 1500,
|
||||||
37.362562, -122.039223, 1000,
|
37.362562F, -122.039223F, 1000,
|
||||||
37.361448, -122.034416, 1000,
|
37.361448F, -122.034416F, 1000,
|
||||||
37.361994, -122.026348, 1000,
|
37.361994F, -122.026348F, 1000,
|
||||||
37.365541, -122.022572, 1000,
|
37.365541F, -122.022572F, 1000,
|
||||||
37.373727, -122.024803, 1000,
|
37.373727F, -122.024803F, 1000,
|
||||||
37.403869, -122.041283, 50,
|
37.403869F, -122.041283F, 50,
|
||||||
37.418544, -122.049222, 6
|
37.418544F, -122.049222F, 6
|
||||||
};
|
};
|
||||||
|
|
||||||
// Test
|
// Test
|
||||||
sendWYPT(sendPort, xpc_WYPT_ADD, points, 15);
|
sendWYPT(sock, XPC_WYPT_ADD, points, 15);
|
||||||
|
// NOTE: Visually ensure waypoints are added in the sim
|
||||||
|
|
||||||
// Cleanup
|
// Cleanup
|
||||||
closeUDP(sendPort);
|
closeUDP(sock);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
short pauseTest() // pauseSim test
|
int pauseTest() // pauseSim test
|
||||||
{
|
{
|
||||||
printf("pauseSim - ");
|
|
||||||
|
|
||||||
// Initialize
|
// Initialize
|
||||||
int i; // Iterator
|
int i; // Iterator
|
||||||
char DREFArray[100][100];
|
char* drefs[100] =
|
||||||
float *recDATA[100];
|
{
|
||||||
short DREFSizes[100],RECSizes[100];
|
"sim/operation/override/override_planepath"
|
||||||
struct xpcSocket sendPort, recvPort;
|
};
|
||||||
short result;
|
float* data[100];
|
||||||
|
int sizes[100];
|
||||||
|
XPCSocket sock = openUDP("127.0.0.1", 49009, 49064);
|
||||||
|
|
||||||
// Setup
|
// Setup
|
||||||
for (i = 0; i < 100; i++) {
|
for (i = 0; i < 100; i++)
|
||||||
recDATA[i] = (float *) malloc(40*sizeof(float));
|
{
|
||||||
memset(DREFArray[i],0,100);
|
data[i] = (float*)malloc(40 * sizeof(float));
|
||||||
}
|
sizes[i] = 40;
|
||||||
|
|
||||||
// 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
|
// Execute
|
||||||
pauseSim(sendPort, 1);
|
pauseSim(sock, 1);
|
||||||
result = requestDREF(sendPort, recvPort, DREFArray, DREFSizes, 1, recDATA, RECSizes); // Test
|
int result = getDREF(sock, drefs[0], data[0], sizes);
|
||||||
|
|
||||||
// Close
|
// Close
|
||||||
closeUDP(sendPort);
|
closeUDP(sock);
|
||||||
closeUDP(recvPort);
|
|
||||||
|
|
||||||
// Test
|
// Test
|
||||||
if (result < 0) {
|
if (result < 0)
|
||||||
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (recDATA[0][0] != 1)
|
if (data[0][0] != 1)
|
||||||
{
|
{
|
||||||
return -2;
|
return -2;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reopen
|
// Reopen
|
||||||
sendPort = openUDP( 49064, "127.0.0.1", 49009 );
|
sock = openUDP("127.0.0.1", 49009, 49064);
|
||||||
recvPort = openUDP( 49008, "127.0.0.1", 49009 );
|
|
||||||
|
|
||||||
// Execute 2
|
// Execute 2
|
||||||
pauseSim(sendPort, 0);
|
pauseSim(sock, 0);
|
||||||
result = requestDREF(sendPort, recvPort, DREFArray, DREFSizes, 1, recDATA, RECSizes); // Test
|
result = getDREF(sock, drefs[0], data[0], sizes);
|
||||||
|
|
||||||
// Close 2
|
// Close 2
|
||||||
closeUDP(sendPort);
|
closeUDP(sock);
|
||||||
closeUDP(recvPort);
|
|
||||||
|
|
||||||
// Test 2
|
// Test 2
|
||||||
if (result < 0)
|
if (result < 0)
|
||||||
{
|
{
|
||||||
return -3;
|
return -3;
|
||||||
}
|
}
|
||||||
if (recDATA[0][0] != 0)
|
if (data[0][0] != 0)
|
||||||
{
|
{
|
||||||
return -4;
|
return -4;
|
||||||
}
|
}
|
||||||
@@ -536,48 +464,39 @@ short pauseTest() // pauseSim test
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
short connTest() // setConn test
|
int connTest() // setConn test
|
||||||
{
|
{
|
||||||
printf("setConn - ");
|
|
||||||
|
|
||||||
// Initialize
|
// Initialize
|
||||||
int i; // Iterator
|
char* drefs[100] =
|
||||||
char DREFArray[100][100];
|
{
|
||||||
float *recDATA[100];
|
"sim/cockpit/switches/gear_handle_status"
|
||||||
short DREFSizes[100];
|
};
|
||||||
struct xpcSocket sendPort, recvPort;
|
float* data[100];
|
||||||
short result = 0;
|
int sizes[100];
|
||||||
|
XPCSocket sock = openUDP("127.0.0.1", 49009, 49067);
|
||||||
#if (__APPLE__ || __linux)
|
#if (__APPLE__ || __linux)
|
||||||
usleep(0);
|
usleep(0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Setup
|
// Setup
|
||||||
sendPort = openUDP( 49067, "127.0.0.1", 49009 );
|
for (int i = 0; i < 100; ++i)
|
||||||
recvPort = openUDP( 49055, "127.0.0.1", 49009 );
|
{
|
||||||
strcpy(DREFArray[0],"sim/cockpit/switches/gear_handle_status");
|
data[i] = (float*)malloc(40 * sizeof(float));
|
||||||
for (i=0;i<1;i++) {
|
sizes[i] = 40;
|
||||||
DREFSizes[i] = (int) strlen(DREFArray[i]);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Execution
|
// Execution
|
||||||
setCONN(sendPort, 49055);
|
setCONN(&sock, 49055);
|
||||||
result = requestDREF(sendPort, recvPort, DREFArray, DREFSizes, 1, recDATA, DREFSizes); // Test
|
int result = getDREF(sock, drefs[0], data[0], sizes);
|
||||||
|
|
||||||
// Close
|
// Close
|
||||||
closeUDP(sendPort);
|
closeUDP(sock);
|
||||||
closeUDP(recvPort);
|
|
||||||
|
|
||||||
// Test
|
// Test
|
||||||
if ( result < 0 )// No data received
|
if ( result < 0 )// No data received
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Set up for next test
|
|
||||||
sendPort = openUDP( 49067, "127.0.0.1", 49009 );
|
|
||||||
setCONN(sendPort, 49008);
|
|
||||||
closeUDP(sendPort);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -593,19 +512,19 @@ int main(int argc, const char * argv[])
|
|||||||
printf("(Linux) \n");
|
printf("(Linux) \n");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
runTest(openTest);
|
runTest(openTest, "open");
|
||||||
runTest(closeTest);
|
runTest(closeTest, "close");
|
||||||
runTest(sendReadTest);
|
runTest(sendReadTest, "send/read");
|
||||||
runTest(sendTEXTTest);
|
runTest(sendTEXTTest, "TEXT");
|
||||||
runTest(requestDREFTest);
|
runTest(requestDREFTest, "GETD");
|
||||||
runTest(sendDREFTest);
|
runTest(sendDREFTest, "DREF");
|
||||||
runTest(sendDATATest);
|
runTest(sendDATATest, "DATA");
|
||||||
runTest(sendCTRLTest);
|
runTest(sendCTRLTest, "CTRL");
|
||||||
runTest(sendpCTRLTest);
|
runTest(psendCTRLTest, "CTRL (player)");
|
||||||
runTest(sendPOSITest);
|
runTest(sendPOSITest, "POSI");
|
||||||
runTest(sendWYPTTest);
|
runTest(sendWYPTTest, "WYPT");
|
||||||
runTest(pauseTest);
|
runTest(pauseTest, "SIMU");
|
||||||
runTest(connTest);
|
runTest(connTest, "CONN");
|
||||||
|
|
||||||
printf( "----------------\nTest Summary\n\tFailed: %i\n\tPassed: %i\n", testFailed, testPassed );
|
printf( "----------------\nTest Summary\n\tFailed: %i\n\tPassed: %i\n", testFailed, testPassed );
|
||||||
|
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ public class XPlaneConnectTest
|
|||||||
{
|
{
|
||||||
fail();
|
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);
|
assertNotNull(xpc);
|
||||||
}
|
}
|
||||||
@@ -39,7 +39,7 @@ public class XPlaneConnectTest
|
|||||||
{
|
{
|
||||||
fail();
|
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);
|
assertNotNull(xpc);
|
||||||
}
|
}
|
||||||
@@ -50,9 +50,9 @@ public class XPlaneConnectTest
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@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());
|
assertEquals(49008, xpc.getRecvPort());
|
||||||
}
|
}
|
||||||
@@ -87,11 +87,11 @@ public class XPlaneConnectTest
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@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();
|
fail();
|
||||||
}
|
}
|
||||||
@@ -106,7 +106,7 @@ public class XPlaneConnectTest
|
|||||||
@Test(expected = UnknownHostException.class)
|
@Test(expected = UnknownHostException.class)
|
||||||
public void constructorTest_InvalidHost() throws UnknownHostException
|
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";
|
String dref = "sim/cockpit/switches/gear_handle_status";
|
||||||
try(XPlaneConnect xpc = new XPlaneConnect())
|
try(XPlaneConnect xpc = new XPlaneConnect())
|
||||||
{
|
{
|
||||||
float[] result = xpc.requestDREF(dref);
|
float[] result = xpc.getDREF(dref);
|
||||||
assertEquals(1, result.length);
|
assertEquals(1, result.length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -138,7 +138,7 @@ public class XPlaneConnectTest
|
|||||||
};
|
};
|
||||||
try(XPlaneConnect xpc = new XPlaneConnect())
|
try(XPlaneConnect xpc = new XPlaneConnect())
|
||||||
{
|
{
|
||||||
float[][] result = xpc.requestDREFs(drefs);
|
float[][] result = xpc.getDREFs(drefs);
|
||||||
assertEquals(2, result.length);
|
assertEquals(2, result.length);
|
||||||
assertEquals(1, result[0].length);
|
assertEquals(1, result[0].length);
|
||||||
assertEquals(4, result[1].length);
|
assertEquals(4, result[1].length);
|
||||||
@@ -150,7 +150,7 @@ public class XPlaneConnectTest
|
|||||||
{
|
{
|
||||||
try(XPlaneConnect xpc = new XPlaneConnect())
|
try(XPlaneConnect xpc = new XPlaneConnect())
|
||||||
{
|
{
|
||||||
xpc.requestDREFs(null);
|
xpc.getDREFs(null);
|
||||||
fail();
|
fail();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -161,7 +161,7 @@ public class XPlaneConnectTest
|
|||||||
String[] drefs = new String[0];
|
String[] drefs = new String[0];
|
||||||
try(XPlaneConnect xpc = new XPlaneConnect())
|
try(XPlaneConnect xpc = new XPlaneConnect())
|
||||||
{
|
{
|
||||||
xpc.requestDREFs(drefs);
|
xpc.getDREFs(drefs);
|
||||||
fail();
|
fail();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -172,7 +172,7 @@ public class XPlaneConnectTest
|
|||||||
String[] drefs = new String[300];
|
String[] drefs = new String[300];
|
||||||
try(XPlaneConnect xpc = new XPlaneConnect())
|
try(XPlaneConnect xpc = new XPlaneConnect())
|
||||||
{
|
{
|
||||||
xpc.requestDREFs(drefs);
|
xpc.getDREFs(drefs);
|
||||||
fail();
|
fail();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -184,7 +184,7 @@ public class XPlaneConnectTest
|
|||||||
String[] drefs = new String[]{longDREF};
|
String[] drefs = new String[]{longDREF};
|
||||||
try(XPlaneConnect xpc = new XPlaneConnect())
|
try(XPlaneConnect xpc = new XPlaneConnect())
|
||||||
{
|
{
|
||||||
xpc.requestDREFs(drefs);
|
xpc.getDREFs(drefs);
|
||||||
fail();
|
fail();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -195,7 +195,7 @@ public class XPlaneConnectTest
|
|||||||
String dref = "";
|
String dref = "";
|
||||||
try(XPlaneConnect xpc = new XPlaneConnect())
|
try(XPlaneConnect xpc = new XPlaneConnect())
|
||||||
{
|
{
|
||||||
xpc.requestDREF(dref);
|
xpc.getDREF(dref);
|
||||||
fail();
|
fail();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -207,12 +207,12 @@ public class XPlaneConnectTest
|
|||||||
try(XPlaneConnect xpc = new XPlaneConnect())
|
try(XPlaneConnect xpc = new XPlaneConnect())
|
||||||
{
|
{
|
||||||
xpc.pauseSim(true);
|
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.length); //TODO: Why is this result 20 elements long in Java? (It's only one in MATLAB)
|
||||||
assertEquals(1, result[0], 1e-4);
|
assertEquals(1, result[0], 1e-4);
|
||||||
|
|
||||||
xpc.pauseSim(false);
|
xpc.pauseSim(false);
|
||||||
result = xpc.requestDREF(dref);
|
result = xpc.getDREF(dref);
|
||||||
//assertEquals(1, result.length);
|
//assertEquals(1, result.length);
|
||||||
assertEquals(0, result[0], 1e-4);
|
assertEquals(0, result[0], 1e-4);
|
||||||
}
|
}
|
||||||
@@ -305,12 +305,12 @@ public class XPlaneConnectTest
|
|||||||
String dref = "sim/cockpit/switches/gear_handle_status";
|
String dref = "sim/cockpit/switches/gear_handle_status";
|
||||||
try(XPlaneConnect xpc = new XPlaneConnect())
|
try(XPlaneConnect xpc = new XPlaneConnect())
|
||||||
{
|
{
|
||||||
float gearHandle = xpc.requestDREF(dref)[0];
|
float gearHandle = xpc.getDREF(dref)[0];
|
||||||
|
|
||||||
float value = gearHandle > 0.5 ? 0 : 1;
|
float value = gearHandle > 0.5 ? 0 : 1;
|
||||||
xpc.sendDREF(dref, value);
|
xpc.setDREF(dref, value);
|
||||||
|
|
||||||
float result = xpc.requestDREF(dref)[0];
|
float result = xpc.getDREF(dref)[0];
|
||||||
assertEquals(value, result, 1e-4);
|
assertEquals(value, result, 1e-4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -320,7 +320,7 @@ public class XPlaneConnectTest
|
|||||||
{
|
{
|
||||||
try(XPlaneConnect xpc = new XPlaneConnect())
|
try(XPlaneConnect xpc = new XPlaneConnect())
|
||||||
{
|
{
|
||||||
xpc.sendDREF(null, 0);
|
xpc.setDREF(null, 0);
|
||||||
fail();
|
fail();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -332,7 +332,7 @@ public class XPlaneConnectTest
|
|||||||
|
|
||||||
try(XPlaneConnect xpc = new XPlaneConnect())
|
try(XPlaneConnect xpc = new XPlaneConnect())
|
||||||
{
|
{
|
||||||
xpc.sendDREF(dref, null);
|
xpc.setDREF(dref, null);
|
||||||
fail();
|
fail();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -343,19 +343,22 @@ public class XPlaneConnectTest
|
|||||||
String dref = "sim/cockpit/switches/gear_handle_status";
|
String dref = "sim/cockpit/switches/gear_handle_status";
|
||||||
try(XPlaneConnect xpc = new XPlaneConnect())
|
try(XPlaneConnect xpc = new XPlaneConnect())
|
||||||
{
|
{
|
||||||
xpc.sendDREF(dref, new float[0]);
|
xpc.setDREF(dref, new float[0]);
|
||||||
fail();
|
fail();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = IllegalArgumentException.class)
|
@Test
|
||||||
public void testSendDREF_MessageTooLong() throws IOException
|
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";
|
String dref = "sim/cockpit/switches/gear_handle_status";
|
||||||
try(XPlaneConnect xpc = new XPlaneConnect())
|
try(XPlaneConnect xpc = new XPlaneConnect())
|
||||||
{
|
{
|
||||||
xpc.sendDREF(dref, new float[200]);
|
xpc.setDREF(dref, new float[200]);
|
||||||
fail();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -365,7 +368,7 @@ public class XPlaneConnectTest
|
|||||||
String dref = "sim/cockpit/switches/i/am/a/very/long/fake/dref/that/is/over/255/characters/./which/means/that/my/length/cant/be/encoded/in/the/single/byte/allocated/by/the/message/format/,/so/i/should/cause/an/exception/instead/./i/am/still/not/long/enough/./almost/there";
|
String dref = "sim/cockpit/switches/i/am/a/very/long/fake/dref/that/is/over/255/characters/./which/means/that/my/length/cant/be/encoded/in/the/single/byte/allocated/by/the/message/format/,/so/i/should/cause/an/exception/instead/./i/am/still/not/long/enough/./almost/there";
|
||||||
try(XPlaneConnect xpc = new XPlaneConnect())
|
try(XPlaneConnect xpc = new XPlaneConnect())
|
||||||
{
|
{
|
||||||
xpc.sendDREF(dref, 0);
|
xpc.setDREF(dref, 0);
|
||||||
fail();
|
fail();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -376,7 +379,7 @@ public class XPlaneConnectTest
|
|||||||
String dref = "";
|
String dref = "";
|
||||||
try(XPlaneConnect xpc = new XPlaneConnect())
|
try(XPlaneConnect xpc = new XPlaneConnect())
|
||||||
{
|
{
|
||||||
xpc.sendDREF(dref, 0);
|
xpc.setDREF(dref, 0);
|
||||||
fail();
|
fail();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -396,7 +399,7 @@ public class XPlaneConnectTest
|
|||||||
try(XPlaneConnect xpc = new XPlaneConnect())
|
try(XPlaneConnect xpc = new XPlaneConnect())
|
||||||
{
|
{
|
||||||
xpc.sendCTRL(ctrl);
|
xpc.sendCTRL(ctrl);
|
||||||
float[][] result = xpc.requestDREFs(drefs);
|
float[][] result = xpc.getDREFs(drefs);
|
||||||
if(result.length < ctrl.length)
|
if(result.length < ctrl.length)
|
||||||
{
|
{
|
||||||
fail();
|
fail();
|
||||||
@@ -425,8 +428,8 @@ public class XPlaneConnectTest
|
|||||||
try(XPlaneConnect xpc = new XPlaneConnect())
|
try(XPlaneConnect xpc = new XPlaneConnect())
|
||||||
{
|
{
|
||||||
xpc.sendCTRL(ctrl, 1);
|
xpc.sendCTRL(ctrl, 1);
|
||||||
float[][] result1 = xpc.requestDREFs(drefs1);
|
float[][] result1 = xpc.getDREFs(drefs1);
|
||||||
float[][] result2 = xpc.requestDREFs(drefs2);
|
float[][] result2 = xpc.getDREFs(drefs2);
|
||||||
if(result1.length != 4 || result2.length != 2)
|
if(result1.length != 4 || result2.length != 2)
|
||||||
{
|
{
|
||||||
fail();
|
fail();
|
||||||
@@ -480,7 +483,7 @@ public class XPlaneConnectTest
|
|||||||
xpc.sendPOSI(posi);
|
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.
|
//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){}
|
try {Thread.sleep(100);}catch(InterruptedException ex){}
|
||||||
float[][] result = xpc.requestDREFs(drefs);
|
float[][] result = xpc.getDREFs(drefs);
|
||||||
xpc.pauseSim(false);
|
xpc.pauseSim(false);
|
||||||
if(result.length < posi.length)
|
if(result.length < posi.length)
|
||||||
{
|
{
|
||||||
@@ -543,7 +546,7 @@ public class XPlaneConnectTest
|
|||||||
try(XPlaneConnect xpc = new XPlaneConnect())
|
try(XPlaneConnect xpc = new XPlaneConnect())
|
||||||
{
|
{
|
||||||
xpc.sendDATA(data);
|
xpc.sendDATA(data);
|
||||||
float[] result = xpc.requestDREF(dref);
|
float[] result = xpc.getDREF(dref);
|
||||||
assertEquals(data[0][1], result[0], 1e-4);
|
assertEquals(data[0][1], result[0], 1e-4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -575,15 +578,9 @@ public class XPlaneConnectTest
|
|||||||
String dref = "sim/cockpit/switches/gear_handle_status";
|
String dref = "sim/cockpit/switches/gear_handle_status";
|
||||||
try(XPlaneConnect xpc = new XPlaneConnect())
|
try(XPlaneConnect xpc = new XPlaneConnect())
|
||||||
{
|
{
|
||||||
int p = xpc.getRecvPort();
|
|
||||||
xpc.setCONN(49055);
|
xpc.setCONN(49055);
|
||||||
assertEquals(49055, xpc.getRecvPort());
|
assertEquals(49055, xpc.getRecvPort());
|
||||||
float[] result = xpc.requestDREF(dref);
|
float[] result = xpc.getDREF(dref);
|
||||||
assertEquals(1, result.length);
|
|
||||||
|
|
||||||
xpc.setCONN(p);
|
|
||||||
assertEquals(p, xpc.getRecvPort());
|
|
||||||
result = xpc.requestDREF(dref);
|
|
||||||
assertEquals(1, result.length);
|
assertEquals(1, result.length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
function CTRLTest( )
|
function CTRLTest( )
|
||||||
%CTRLTest Summary of this function goes here
|
%CTRLTest Summary of this function goes here
|
||||||
% Detailed explanation goes here
|
% Detailed explanation goes here
|
||||||
|
%% Test player aircraft
|
||||||
addpath('../../MATLAB')
|
addpath('../../MATLAB')
|
||||||
import XPlaneConnect.*
|
import XPlaneConnect.*
|
||||||
|
|
||||||
@@ -14,14 +15,15 @@ THROT = rand();
|
|||||||
CTRL = [0.0, 0.0, 1.0, THROT, 0.0, 1.0];
|
CTRL = [0.0, 0.0, 1.0, THROT, 0.0, 1.0];
|
||||||
|
|
||||||
sendCTRL(CTRL);
|
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),6),'CTRLTest: getDREFs 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{4}),8),'CTRLTest: getDREFs unsucessful- element 1 incorrect size (should be size 8)');
|
||||||
for i=1:length(CTRL)-1
|
for i=1:length(CTRL)-1
|
||||||
assert(abs(result{i}(1)-CTRL(i))<1e-4,['CTRLTest: DATA set unsucessful-',num2str(i)]);
|
assert(abs(result{i}(1)-CTRL(i))<1e-4,['CTRLTest: DATA set unsucessful-',num2str(i)]);
|
||||||
end
|
end
|
||||||
|
|
||||||
|
%% Test NPC aircraft
|
||||||
DREFS = {'sim/multiplayer/position/plane1_yolk_pitch',...
|
DREFS = {'sim/multiplayer/position/plane1_yolk_pitch',...
|
||||||
'sim/multiplayer/position/plane1_yolk_roll',...
|
'sim/multiplayer/position/plane1_yolk_roll',...
|
||||||
'sim/multiplayer/position/plane1_yolk_yaw',...
|
'sim/multiplayer/position/plane1_yolk_yaw',...
|
||||||
@@ -32,7 +34,7 @@ THROT = rand();
|
|||||||
CTRL = [0.0, 0.0, 1.0, THROT, 0.0, 1.0];
|
CTRL = [0.0, 0.0, 1.0, THROT, 0.0, 1.0];
|
||||||
|
|
||||||
sendCTRL(CTRL, 1);
|
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),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{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]);
|
data = struct('h',25,'d',[value,-998,-998,-998,-998,-998,-998,-998]);
|
||||||
|
|
||||||
sendDATA(data);
|
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),8),'DATATest: getDREFs 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)-value)<1e-4,'DATATest: DATA set unsucessful');
|
||||||
assert(abs(result{1}(1)-value)<1e-4,'DATATest: DATA set unsucessful');
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -14,14 +14,14 @@ DREFS = {'sim/flightmodel/position/latitude', ...
|
|||||||
POSI = [37.524, -122.06899, 2500, 0, 0, 0, 1]; % Gear
|
POSI = [37.524, -122.06899, 2500, 0, 0, 0, 1]; % Gear
|
||||||
|
|
||||||
sendPOSI(POSI);
|
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)
|
for i=1:length(POSI)
|
||||||
if i==3
|
if i==3
|
||||||
continue
|
continue
|
||||||
end
|
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
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
function requestDREFTest( )
|
function getDREFsTest( )
|
||||||
%SENDREADTEST Summary of this function goes here
|
%SENDREADTEST Summary of this function goes here
|
||||||
% Detailed explanation goes here
|
% Detailed explanation goes here
|
||||||
addpath('../../MATLAB')
|
addpath('../../MATLAB')
|
||||||
@@ -7,7 +7,7 @@ import XPlaneConnect.*
|
|||||||
DREFS = {'sim/cockpit/switches/gear_handle_status',...
|
DREFS = {'sim/cockpit/switches/gear_handle_status',...
|
||||||
'sim/cockpit2/switches/panel_brightness_ratio'};
|
'sim/cockpit2/switches/panel_brightness_ratio'};
|
||||||
|
|
||||||
result = requestDREF(DREFS);
|
result = getDREFs(DREFS);
|
||||||
|
|
||||||
assert(isequal(length(result),2));
|
assert(isequal(length(result),2));
|
||||||
assert(isequal(length(result{1}),1));
|
assert(isequal(length(result{1}),1));
|
||||||
@@ -4,13 +4,10 @@ function openCloseTest()
|
|||||||
addpath('../../MATLAB')
|
addpath('../../MATLAB')
|
||||||
import XPlaneConnect.*
|
import XPlaneConnect.*
|
||||||
|
|
||||||
socket = openUDP( 49007 );
|
socket = openUDP();
|
||||||
|
closeUDP(socket);
|
||||||
closeUDP( socket );
|
socket = openUDP();
|
||||||
assert(isequal(socket.isClosed(),1),'openCloseTest: socket is still open');
|
closeUDP(socket);
|
||||||
|
|
||||||
socket = openUDP( 49007 );
|
|
||||||
closeUDP( socket );
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -9,17 +9,15 @@ DREFS = {'sim/operation/override/override_planepath'};
|
|||||||
value = 1; % Pause
|
value = 1; % Pause
|
||||||
|
|
||||||
pauseSim(value);
|
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)-value)<1e-4,'pauseTest: Pause Unsuccessful');
|
||||||
assert(abs(result{1}(1)-value)<1e-4,'pauseTest: Pause Unsuccessful');
|
|
||||||
value = 0; % Resume
|
value = 0; % Resume
|
||||||
|
|
||||||
pauseSim(value);
|
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)-value)<1e-4,'pauseTest: Pause Unsuccessful');
|
||||||
assert(abs(result{1}(1)-value)<1e-4,'pauseTest: Pause Unsuccessful');
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -1,19 +0,0 @@
|
|||||||
function sendDREFTest( )
|
|
||||||
%SENDREADTEST Summary of this function goes here
|
|
||||||
% Detailed explanation goes here
|
|
||||||
addpath('../../MATLAB')
|
|
||||||
import XPlaneConnect.*
|
|
||||||
|
|
||||||
DREFS = {'sim/cockpit/switches/gear_handle_status'};
|
|
||||||
value = randi([0 10]);
|
|
||||||
|
|
||||||
sendDREF(DREFS{1},value);
|
|
||||||
result = requestDREF(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(result{1},value),'sendDREFTest: 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'};
|
DREFS = {'sim/cockpit/switches/gear_handle_status'};
|
||||||
|
|
||||||
setConn(49055);
|
setConn(49055);
|
||||||
result = requestDREF(DREFS);
|
result = getDREFs(DREFS);
|
||||||
|
|
||||||
assert(isequal(length(result),1),'setConnTest: requestDREF unsucessful-wrong number of elements returned');
|
assert(isequal(length(result),1),'setConnTest: requestDREF unsucessful-wrong number of elements returned');
|
||||||
|
|
||||||
|
|||||||
18
TestScripts/MATLAB Tests/setDREFTest.m
Normal file
18
TestScripts/MATLAB Tests/setDREFTest.m
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
function setDREFTest( )
|
||||||
|
%SENDREADTEST Summary of this function goes here
|
||||||
|
% Detailed explanation goes here
|
||||||
|
addpath('../../MATLAB')
|
||||||
|
import XPlaneConnect.*
|
||||||
|
|
||||||
|
DREFS = {'sim/cockpit/switches/gear_handle_status'};
|
||||||
|
value = randi([0 10]);
|
||||||
|
|
||||||
|
setDREF(DREFS{1},value);
|
||||||
|
result = getDREFs(DREFS);
|
||||||
|
|
||||||
|
assert(isequal(length(result),1),'setDREFTest: requestDREF unsucessful-wrong number of elements returned');
|
||||||
|
|
||||||
|
assert(isequal(result(1),value),'setDREFTest: DREF set unsucessful');
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
@@ -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, ')']);
|
disp(['XPC Tests-MATLAB (', os, ')']);
|
||||||
|
|
||||||
theTests = {{@openCloseTest, 'Open/Close Test', 0},...
|
theTests = {{@openCloseTest, 'Open/Close Test', 0},...
|
||||||
{@sendReadTest,'Send/Read Test', 0},...
|
|
||||||
{@sendTEXTTest,'TEXT Test', 0},...
|
{@sendTEXTTest,'TEXT Test', 0},...
|
||||||
{@requestDREFTest,'Request DREF Test', 0},...
|
{@getDREFsTest,'Request DREF Test', 0},...
|
||||||
{@sendDREFTest,'Send DREF Test', 0},...
|
{@setDREFTest,'Send DREF Test', 0},...
|
||||||
{@DATATest,'DATA Test', 0},...
|
{@DATATest,'DATA Test', 0},...
|
||||||
{@CTRLTest,'CTRL Test', 0},...
|
{@CTRLTest,'CTRL Test', 0},...
|
||||||
{@POSITest,'POSI Test', 0},...
|
{@POSITest,'POSI Test', 0},...
|
||||||
{@sendWYPTTest,'WYPT Test', 0},...
|
{@sendWYPTTest,'WYPT Test', 0},...
|
||||||
{@pauseTest,'Pause Test', 0},...
|
{@pauseTest,'Pause Test', 0},...
|
||||||
{@struTest,'Struct Test', 0},...
|
|
||||||
{@setConnTest, 'setConn Test', 0}};
|
{@setConnTest, 'setConn Test', 0}};
|
||||||
|
|
||||||
for i=1:length(theTests)
|
for i=1:length(theTests)
|
||||||
|
|||||||
@@ -3,12 +3,17 @@
|
|||||||
#ifndef XPC_DRAWING_H
|
#ifndef XPC_DRAWING_H
|
||||||
#define XPC_DRAWING_H
|
#define XPC_DRAWING_H
|
||||||
|
|
||||||
#include "xplaneConnect.h"
|
|
||||||
|
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
|
||||||
namespace XPC
|
namespace XPC
|
||||||
{
|
{
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
double latitude;
|
||||||
|
double longitude;
|
||||||
|
double altitude;
|
||||||
|
} Waypoint;
|
||||||
|
|
||||||
/// Handles tasks that involve drawing to the screen in X-Plane.
|
/// Handles tasks that involve drawing to the screen in X-Plane.
|
||||||
///
|
///
|
||||||
/// \author Jason Watkins
|
/// \author Jason Watkins
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
//National Aeronautics and Space Administration. All Rights Reserved.
|
//National Aeronautics and Space Administration. All Rights Reserved.
|
||||||
#include "Message.h"
|
#include "Message.h"
|
||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
#include "xplaneConnect.h"
|
|
||||||
|
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
@@ -71,6 +70,7 @@ namespace XPC
|
|||||||
}
|
}
|
||||||
Log::WriteLine(ss.str());
|
Log::WriteLine(ss.str());
|
||||||
|
|
||||||
|
ss << std::dec;
|
||||||
ss.str("");
|
ss.str("");
|
||||||
ss << "[" << GetHead() << "-DEBUG] (" << GetSize() << ")";
|
ss << "[" << GetHead() << "-DEBUG] (" << GetSize() << ")";
|
||||||
switch (GetMagicNumber()) // Binary version of head
|
switch (GetMagicNumber()) // Binary version of head
|
||||||
@@ -84,25 +84,41 @@ namespace XPC
|
|||||||
}
|
}
|
||||||
case 0x4C525443: // CTRL
|
case 0x4C525443: // CTRL
|
||||||
{
|
{
|
||||||
xpcCtrl ctrl = parseCTRL((char*)buffer);
|
// Parse message data
|
||||||
ss << " (" << ctrl.pitch << " " << ctrl.roll << " " << ctrl.yaw << ") ";
|
float pitch = *((float*)(buffer + 5));
|
||||||
ss << ctrl.throttle << " " << ctrl.gear << " " << ctrl.flaps;
|
float roll = *((float*)(buffer + 9));
|
||||||
|
float yaw = *((float*)(buffer + 13));
|
||||||
|
float thr = *((float*)(buffer + 17));
|
||||||
|
char gear = buffer[21];
|
||||||
|
float flaps = *((float*)(buffer + 22));
|
||||||
|
std::uint8_t 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());
|
Log::WriteLine(ss.str());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 0x41544144: // DATA
|
case 0x41544144: // DATA
|
||||||
{
|
{
|
||||||
float dataRef[30][9];
|
std::size_t numCols = (size - 5) / 36;
|
||||||
short numCols = parseDATA((char*)buffer, size, dataRef);
|
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)";
|
ss << " (" << numCols << " lines)";
|
||||||
Log::WriteLine(ss.str());
|
Log::WriteLine(ss.str());
|
||||||
for (int i = 0; i < numCols; ++i)
|
for (int i = 0; i < numCols; ++i)
|
||||||
{
|
{
|
||||||
ss.str("");
|
ss.str("");
|
||||||
ss << "\t#" << dataRef[i][0];
|
ss << "\t#" << values[i][0];
|
||||||
for (int j = 1; j < 9; ++j)
|
for (int j = 1; j < 9; ++j)
|
||||||
{
|
{
|
||||||
ss << " " << dataRef[i][j];
|
ss << " " << values[i][j];
|
||||||
}
|
}
|
||||||
Log::WriteLine(ss.str());
|
Log::WriteLine(ss.str());
|
||||||
}
|
}
|
||||||
@@ -136,14 +152,16 @@ namespace XPC
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 0x49534F50: // POSI
|
case 0x49534F50: // POSI
|
||||||
{
|
{
|
||||||
float position[6] = { 0.0 };
|
char aircraft = buffer[5];
|
||||||
short aircraft = 0;
|
float gear = *((float*)(buffer + 30));
|
||||||
float gear = -1.0;
|
float pos[3];
|
||||||
aircraft = parsePOSI((char*)buffer, position, 6, &gear);
|
float orient[3];
|
||||||
ss << ' ' << aircraft;
|
memcpy(pos, buffer + 6, 12);
|
||||||
ss << " (" << position[0] << ' ' << position[1] << ' ' << position[2] << ") (";
|
memcpy(orient, buffer + 18, 12);
|
||||||
ss << position[3] << ' ' << position[4] << ' ' << position[5] << ") ";
|
ss << " AC:" << (int)aircraft;
|
||||||
|
ss << " Pos:(" << pos[0] << ' ' << pos[1] << ' ' << pos[2] << ") Orient:(";
|
||||||
|
ss << orient[3] << ' ' << orient[4] << ' ' << orient[5] << ") Gear:";
|
||||||
ss << gear;
|
ss << gear;
|
||||||
Log::WriteLine(ss.str());
|
Log::WriteLine(ss.str());
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -55,48 +55,6 @@ namespace XPC
|
|||||||
MessageHandlers::sock = socket;
|
MessageHandlers::sock = socket;
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string getIP(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);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case AF_INET6:
|
|
||||||
{
|
|
||||||
sockaddr_in6* sin = reinterpret_cast<sockaddr_in6*>(sa);
|
|
||||||
inet_ntop(AF_INET6, &sin->sin6_addr, ip, INET6_ADDRSTRLEN);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return "UNKNOWN";
|
|
||||||
}
|
|
||||||
return std::string(ip);
|
|
||||||
}
|
|
||||||
|
|
||||||
static unsigned short getPort(sockaddr* sa)
|
|
||||||
{
|
|
||||||
switch (sa->sa_family)
|
|
||||||
{
|
|
||||||
case AF_INET:
|
|
||||||
{
|
|
||||||
sockaddr_in *sin = reinterpret_cast<sockaddr_in*>(sa);
|
|
||||||
return ntohs((*sin).sin_port);
|
|
||||||
}
|
|
||||||
case AF_INET6:
|
|
||||||
{
|
|
||||||
sockaddr_in6 *sin = reinterpret_cast<sockaddr_in6*>(sa);
|
|
||||||
return ntohs((*sin).sin6_port);
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return ~0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MessageHandlers::HandleMessage(Message& msg)
|
void MessageHandlers::HandleMessage(Message& msg)
|
||||||
{
|
{
|
||||||
// Make sure we really have a message to handle.
|
// Make sure we really have a message to handle.
|
||||||
@@ -109,9 +67,7 @@ namespace XPC
|
|||||||
|
|
||||||
// Set current connection
|
// Set current connection
|
||||||
sockaddr sourceaddr = msg.GetSource();
|
sockaddr sourceaddr = msg.GetSource();
|
||||||
std::string ip = getIP(&sourceaddr);
|
connectionKey = UDPSocket::GetHost(&sourceaddr);
|
||||||
unsigned short port = getPort(&sourceaddr);
|
|
||||||
connectionKey = ip + ":" + std::to_string(port);
|
|
||||||
#if LOG_VERBOSITY > 4
|
#if LOG_VERBOSITY > 4
|
||||||
Log::FormatLine("[MSGH] Handling message from %s", connectionKey.c_str());
|
Log::FormatLine("[MSGH] Handling message from %s", connectionKey.c_str());
|
||||||
#endif
|
#endif
|
||||||
@@ -124,22 +80,20 @@ namespace XPC
|
|||||||
// to connections. As long as we never remove elements, the size of
|
// to connections. As long as we never remove elements, the size of
|
||||||
// connections will serve as a unique id.
|
// connections will serve as a unique id.
|
||||||
static_cast<unsigned char>(connections.size()),
|
static_cast<unsigned char>(connections.size()),
|
||||||
ip,
|
sourceaddr,
|
||||||
49008, // By default, send information to the client on this port.
|
|
||||||
port,
|
|
||||||
0
|
0
|
||||||
};
|
};
|
||||||
connections[connectionKey] = connection;
|
connections[connectionKey] = connection;
|
||||||
#if LOG_VERBOSITY > 4
|
#if LOG_VERBOSITY > 2
|
||||||
Log::FormatLine("[MSGH] New connection. ID=%u, Remote=%s:%u", connection.id, ip.c_str(), port);
|
Log::FormatLine("[MSGH] New connection. ID=%u, Remote=%s", connection.id, connectionKey.c_str());
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
connection = (*conn).second;
|
connection = (*conn).second;
|
||||||
#if LOG_VERBOSITY > 4
|
#if LOG_VERBOSITY > 3
|
||||||
Log::FormatLine("[MSGH] Existing connection. ID=%u, Remote=%s:%u",
|
Log::FormatLine("[MSGH] Existing connection. ID=%u, Remote=%s",
|
||||||
connection.id, connection.ip.c_str(), connection.srcPort);
|
connection.id, connectionKey.c_str());
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -162,7 +116,30 @@ namespace XPC
|
|||||||
const unsigned char* buffer = msg.GetBuffer();
|
const unsigned char* buffer = msg.GetBuffer();
|
||||||
|
|
||||||
// Store new port
|
// Store new port
|
||||||
connection.dstPort = *((unsigned short*)(buffer + 5));
|
std::uint16_t port = *((std::uint16_t*)(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;
|
connections[connectionKey] = connection;
|
||||||
|
|
||||||
// Create response
|
// Create response
|
||||||
@@ -170,19 +147,19 @@ namespace XPC
|
|||||||
response[5] = connection.id;
|
response[5] = connection.id;
|
||||||
|
|
||||||
// Update log
|
// Update log
|
||||||
#if LOG_VERBOSITY > 0
|
#if LOG_VERBOSITY > 1
|
||||||
Log::FormatLine("[CONN] ID: %u New destination port: %u",
|
Log::FormatLine("[CONN] ID: %u New destination port: %u",
|
||||||
connection.id, connection.dstPort);
|
connection.id, port);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Send response
|
// Send response
|
||||||
sock->SendTo(response, 6, connection.ip, connection.dstPort);
|
sock->SendTo(response, 6, &connection.addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MessageHandlers::HandleCtrl(Message& msg)
|
void MessageHandlers::HandleCtrl(Message& msg)
|
||||||
{
|
{
|
||||||
// Update Log
|
// Update Log
|
||||||
#if LOG_VERBOSITY > 0
|
#if LOG_VERBOSITY > 2
|
||||||
Log::FormatLine("[CTRL] Message Received (Conn %i)", connection.id);
|
Log::FormatLine("[CTRL] Message Received (Conn %i)", connection.id);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -192,7 +169,7 @@ namespace XPC
|
|||||||
//Packets specifying an A/C num should be 27 bytes.
|
//Packets specifying an A/C num should be 27 bytes.
|
||||||
if (size != 26 && size != 27)
|
if (size != 26 && size != 27)
|
||||||
{
|
{
|
||||||
#if LOG_VERBOSITY > 1
|
#if LOG_VERBOSITY > 0
|
||||||
Log::FormatLine("[CTRL] ERROR: Unexpected message length (%i)", size);
|
Log::FormatLine("[CTRL] ERROR: Unexpected message length (%i)", size);
|
||||||
#endif
|
#endif
|
||||||
return;
|
return;
|
||||||
@@ -244,20 +221,20 @@ namespace XPC
|
|||||||
std::size_t numCols = (size - 5) / 36;
|
std::size_t numCols = (size - 5) / 36;
|
||||||
if (numCols > 0)
|
if (numCols > 0)
|
||||||
{
|
{
|
||||||
#if LOG_VERBOSITY > 3
|
#if LOG_VERBOSITY > 2
|
||||||
Log::FormatLine("[DATA] Message Received (Conn %i)", connection.id);
|
Log::FormatLine("[DATA] Message Received (Conn %i)", connection.id);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
if (numCols > 32) // Error. Will overflow values
|
if (numCols > 32) // Error. Will overflow values
|
||||||
{
|
{
|
||||||
#if LOG_VERBOSITY > 2
|
#if LOG_VERBOSITY > 0
|
||||||
Log::FormatLine("[DATA] ERROR numCols to large.");
|
Log::FormatLine("[DATA] ERROR numCols to large.");
|
||||||
#endif
|
#endif
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
#if LOG_VERBOSITY > 2
|
#if LOG_VERBOSITY > 1
|
||||||
Log::FormatLine("[DATA] WARNING: Empty data packet received (Conn %i)", connection.id);
|
Log::FormatLine("[DATA] WARNING: Empty data packet received (Conn %i)", connection.id);
|
||||||
#endif
|
#endif
|
||||||
return;
|
return;
|
||||||
@@ -405,8 +382,7 @@ namespace XPC
|
|||||||
std::string dref = std::string((char*)buffer + 6, len);
|
std::string dref = std::string((char*)buffer + 6, len);
|
||||||
|
|
||||||
unsigned char valueCount = buffer[6 + len];
|
unsigned char valueCount = buffer[6 + len];
|
||||||
float values[40];
|
float* values = (float*)(buffer + 7 + len);
|
||||||
memcpy(values, buffer + len + 7, valueCount * sizeof(float));
|
|
||||||
|
|
||||||
#if LOG_VERBOSITY > 1
|
#if LOG_VERBOSITY > 1
|
||||||
Log::FormatLine("[DREF] Request to set DREF value received (Conn %i): %s", connection.id, dref.c_str());
|
Log::FormatLine("[DREF] Request to set DREF value received (Conn %i): %s", connection.id, dref.c_str());
|
||||||
@@ -462,7 +438,7 @@ namespace XPC
|
|||||||
cur += count * sizeof(float);
|
cur += count * sizeof(float);
|
||||||
}
|
}
|
||||||
|
|
||||||
sock->SendTo(response, cur, connection.ip, connection.dstPort);
|
sock->SendTo(response, cur, &connection.addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MessageHandlers::HandlePosi(Message& msg)
|
void MessageHandlers::HandlePosi(Message& msg)
|
||||||
@@ -599,13 +575,13 @@ namespace XPC
|
|||||||
#endif
|
#endif
|
||||||
switch (op)
|
switch (op)
|
||||||
{
|
{
|
||||||
case xpc_WYPT_ADD:
|
case 1:
|
||||||
Drawing::AddWaypoints(points, count);
|
Drawing::AddWaypoints(points, count);
|
||||||
break;
|
break;
|
||||||
case xpc_WYPT_DEL:
|
case 2:
|
||||||
Drawing::RemoveWaypoints(points, count);
|
Drawing::RemoveWaypoints(points, count);
|
||||||
break;
|
break;
|
||||||
case xpc_WYPT_CLR:
|
case 3:
|
||||||
Drawing::ClearWaypoints();
|
Drawing::ClearWaypoints();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -621,7 +597,11 @@ namespace XPC
|
|||||||
#if LOG_VERBOSITY > 1
|
#if LOG_VERBOSITY > 1
|
||||||
Log::WriteLine("[MSGH] Sending raw data to X-Plane");
|
Log::WriteLine("[MSGH] Sending raw data to X-Plane");
|
||||||
#endif
|
#endif
|
||||||
sock->SendTo((unsigned char*)msg.GetBuffer(), msg.GetSize(), "127.0.0.1", 49000);
|
sockaddr_in loopback;
|
||||||
|
loopback.sin_family = AF_INET;
|
||||||
|
loopback.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
||||||
|
loopback.sin_port = htons(49000);
|
||||||
|
sock->SendTo((std::uint8_t*)msg.GetBuffer(), msg.GetSize(), (sockaddr*)&loopback);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MessageHandlers::HandleUnknown(Message& msg)
|
void MessageHandlers::HandleUnknown(Message& msg)
|
||||||
|
|||||||
@@ -52,9 +52,7 @@ namespace XPC
|
|||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
unsigned char id;
|
unsigned char id;
|
||||||
std::string ip;
|
sockaddr addr;
|
||||||
unsigned short dstPort;
|
|
||||||
unsigned short srcPort;
|
|
||||||
unsigned char getdCount;
|
unsigned char getdCount;
|
||||||
std::string getdRequest[255];
|
std::string getdRequest[255];
|
||||||
} ConnectionInfo;
|
} ConnectionInfo;
|
||||||
|
|||||||
@@ -133,41 +133,49 @@ namespace XPC
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Add IPV6 support
|
void UDPSocket::SendTo(std::uint8_t* buffer, std::size_t len, sockaddr* remote)
|
||||||
void UDPSocket::SendTo(unsigned char* buffer, std::size_t len, std::string remoteHost, unsigned short remotePort)
|
|
||||||
{
|
{
|
||||||
#if LOG_VERBOSITY > 4
|
buffer[4] = (std::uint8_t)len;
|
||||||
Log::FormatLine("[SOCK] Sending message to %s:%u (length=%u)", remoteHost.c_str(), remotePort, len);
|
if (sendto(sock, (char*)buffer, (int)len, 0, remote, sizeof(*remote)) < 0)
|
||||||
#endif
|
|
||||||
if (remoteHost == "localhost")
|
|
||||||
{
|
|
||||||
remoteHost = "127.0.0.1";
|
|
||||||
}
|
|
||||||
unsigned long ip;
|
|
||||||
inet_pton(AF_INET, remoteHost.c_str(), &ip);
|
|
||||||
SendTo(buffer, len, ip, remotePort);
|
|
||||||
}
|
|
||||||
|
|
||||||
void UDPSocket::SendTo(unsigned char* buffer, std::size_t len, unsigned long remoteIP, unsigned short remotePort)
|
|
||||||
{
|
|
||||||
struct sockaddr_in remoteAddr;
|
|
||||||
remoteAddr.sin_family = AF_INET;
|
|
||||||
remoteAddr.sin_port = htons(remotePort);
|
|
||||||
remoteAddr.sin_addr.s_addr = remoteIP;
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
const char on = 1;
|
|
||||||
#else
|
|
||||||
int on = 1;
|
|
||||||
#endif
|
|
||||||
setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on));
|
|
||||||
|
|
||||||
buffer[4] = (unsigned char)len;
|
|
||||||
if (sendto(sock, (char*)buffer, (int)len, 0, (const struct sockaddr *) &remoteAddr, sizeof(remoteAddr)) < 0)
|
|
||||||
{
|
{
|
||||||
#if LOG_VERBOSITY > 0
|
#if LOG_VERBOSITY > 0
|
||||||
Log::FormatLine("[SOCK] Send failed. (remote: %s:%d)", remoteAddr, remotePort);
|
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
|
#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++] = ':';
|
||||||
|
sprintf(ip + len, "%d", 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++] = ':';
|
||||||
|
sprintf(ip + len, "%d", ntohs((*sin).sin6_port));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return "UNKNOWN";
|
||||||
|
}
|
||||||
|
return std::string(ip);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -52,20 +52,16 @@ namespace XPC
|
|||||||
|
|
||||||
/// Sends data to the specified remote endpoint.
|
/// Sends data to the specified remote endpoint.
|
||||||
///
|
///
|
||||||
/// \param data The data to be sent.
|
/// \param data The data to be sent.
|
||||||
/// \param len The number of bytes to send.
|
/// \param len The number of bytes to send.
|
||||||
/// \param remoteHost The hostname of the destination client.
|
/// \param remote The destination socket.
|
||||||
/// \param remotePort The port of the destination client.
|
void SendTo(std::uint8_t* buffer, std::size_t len, sockaddr* remote);
|
||||||
void SendTo(unsigned char* buffer, std::size_t len, std::string remoteHost, unsigned short remotePort);
|
|
||||||
|
|
||||||
/// Sends data to the specified remote endpoint.
|
/// Gets a string containing the IP address and port contained in the given sockaddr.
|
||||||
///
|
///
|
||||||
/// \param data The data to be sent.
|
/// \param addr The socket address to parse.
|
||||||
/// \param len The number of bytes to send.
|
/// \returns A string representation of the socket address.
|
||||||
/// \param remoteHost The hostname of the destination client.
|
static std::string GetHost(sockaddr* addr);
|
||||||
/// \param remotePort The port of the destination client.
|
|
||||||
void SendTo(unsigned char* buffer, std::size_t len, unsigned long remoteIP, unsigned short remotePort);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
SOCKET sock;
|
SOCKET sock;
|
||||||
|
|||||||
@@ -70,11 +70,9 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define RECVPORT 49009 // Port that the plugin receives commands on
|
#define RECVPORT 49009 // Port that the plugin receives commands on
|
||||||
#define SENDPORT 49097 // Port that the plugin sends on
|
|
||||||
#define OPS_PER_CYCLE 20 // Max Number of operations per cycle
|
#define OPS_PER_CYCLE 20 // Max Number of operations per cycle
|
||||||
|
|
||||||
XPC::UDPSocket* recvSocket = nullptr;
|
XPC::UDPSocket* sock = nullptr;
|
||||||
XPC::UDPSocket* sendSocket = nullptr;
|
|
||||||
|
|
||||||
double start,lap;
|
double start,lap;
|
||||||
static double timeConvert = 0.0;
|
static double timeConvert = 0.0;
|
||||||
@@ -125,10 +123,8 @@ PLUGIN_API void XPluginStop(void)
|
|||||||
PLUGIN_API void XPluginDisable(void)
|
PLUGIN_API void XPluginDisable(void)
|
||||||
{
|
{
|
||||||
// Close sockets
|
// Close sockets
|
||||||
delete recvSocket;
|
delete sock;
|
||||||
delete sendSocket;
|
sock = nullptr;
|
||||||
recvSocket = nullptr;
|
|
||||||
sendSocket = nullptr;
|
|
||||||
|
|
||||||
// Stop rendering messages to screen.
|
// Stop rendering messages to screen.
|
||||||
XPC::Drawing::ClearMessage();
|
XPC::Drawing::ClearMessage();
|
||||||
@@ -142,9 +138,8 @@ PLUGIN_API void XPluginDisable(void)
|
|||||||
PLUGIN_API int XPluginEnable(void)
|
PLUGIN_API int XPluginEnable(void)
|
||||||
{
|
{
|
||||||
// Open sockets
|
// Open sockets
|
||||||
recvSocket = new XPC::UDPSocket(RECVPORT);
|
sock = new XPC::UDPSocket(RECVPORT);
|
||||||
sendSocket = new XPC::UDPSocket(SENDPORT);
|
XPC::MessageHandlers::SetSocket(sock);
|
||||||
XPC::MessageHandlers::SetSocket(sendSocket);
|
|
||||||
|
|
||||||
XPC::Log::WriteLine("[EXEC] Plugin Enabled, sockets opened");
|
XPC::Log::WriteLine("[EXEC] Plugin Enabled, sockets opened");
|
||||||
if (benchmarkingSwitch > 0)
|
if (benchmarkingSwitch > 0)
|
||||||
@@ -188,7 +183,7 @@ float XPCFlightLoopCallback(float inElapsedSinceLastCall,
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
XPC::Message msg = XPC::Message::ReadFrom(*recvSocket);
|
XPC::Message msg = XPC::Message::ReadFrom(*sock);
|
||||||
if (msg.GetHead() == "")
|
if (msg.GetHead() == "")
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
@@ -208,8 +203,8 @@ float XPCFlightLoopCallback(float inElapsedSinceLastCall,
|
|||||||
if (cyclesToClear != -1 && counter%cyclesToClear == 0)
|
if (cyclesToClear != -1 && counter%cyclesToClear == 0)
|
||||||
{
|
{
|
||||||
XPC::Log::WriteLine("[EXEC] Cleared UDP Buffer");
|
XPC::Log::WriteLine("[EXEC] Cleared UDP Buffer");
|
||||||
delete recvSocket;
|
delete sock;
|
||||||
recvSocket = new XPC::UDPSocket(RECVPORT);
|
sock = new XPC::UDPSocket(RECVPORT);
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
Binary file not shown.
Binary file not shown.
@@ -42,7 +42,7 @@
|
|||||||
<LinkIncremental>true</LinkIncremental>
|
<LinkIncremental>true</LinkIncremental>
|
||||||
<OutDir>..\XPlaneConnect\</OutDir>
|
<OutDir>..\XPlaneConnect\</OutDir>
|
||||||
<TargetExt>.xpl</TargetExt>
|
<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>
|
<LibraryPath>..\xpcPlugin\SDK\Libraries\Win;$(LibraryPath)</LibraryPath>
|
||||||
<TargetName>win</TargetName>
|
<TargetName>win</TargetName>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
@@ -99,7 +99,6 @@
|
|||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="..\..\C\src\xplaneConnect.h" />
|
|
||||||
<ClInclude Include="..\DataManager.h" />
|
<ClInclude Include="..\DataManager.h" />
|
||||||
<ClInclude Include="..\DataMaps.h" />
|
<ClInclude Include="..\DataMaps.h" />
|
||||||
<ClInclude Include="..\Drawing.h" />
|
<ClInclude Include="..\Drawing.h" />
|
||||||
@@ -109,7 +108,6 @@
|
|||||||
<ClInclude Include="..\UDPSocket.h" />
|
<ClInclude Include="..\UDPSocket.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="..\..\C\src\xplaneConnect.c" />
|
|
||||||
<ClCompile Include="..\DataManager.cpp" />
|
<ClCompile Include="..\DataManager.cpp" />
|
||||||
<ClCompile Include="..\DataMaps.cpp" />
|
<ClCompile Include="..\DataMaps.cpp" />
|
||||||
<ClCompile Include="..\Drawing.cpp" />
|
<ClCompile Include="..\Drawing.cpp" />
|
||||||
|
|||||||
@@ -15,9 +15,6 @@
|
|||||||
</Filter>
|
</Filter>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="..\..\C\src\xplaneConnect.h">
|
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="..\Log.h">
|
<ClInclude Include="..\Log.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
@@ -41,9 +38,6 @@
|
|||||||
</ClInclude>
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="..\..\C\src\xplaneConnect.c">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\XPCPlugin.cpp">
|
<ClCompile Include="..\XPCPlugin.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
|||||||
Reference in New Issue
Block a user