@@ -366,32 +366,46 @@ int readDATA(XPCSocket sock, float data[][9], int rows)
|
|||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
int sendDREF(XPCSocket sock, const char* dref, float value[], int size)
|
int sendDREF(XPCSocket sock, const char* dref, float value[], int size)
|
||||||
{
|
{
|
||||||
// Setup command
|
return sendDREFs(sock, &dref, &value, &size, 1);
|
||||||
// 5 byte header + max 255 char dref name + max 255 values * 4 bytes per value = 1279
|
}
|
||||||
unsigned char buffer[1279] = "DREF";
|
|
||||||
int drefLen = strnlen(dref, 256);
|
|
||||||
if (drefLen > 255)
|
|
||||||
{
|
|
||||||
printError("setDREF", "dref length is too long. Must be less than 256 characters.");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (size > 255)
|
|
||||||
{
|
|
||||||
printError("setDREF", "size is too big. Must be less than 256.");
|
|
||||||
return -2;
|
|
||||||
}
|
|
||||||
int len = 7 + drefLen + size * sizeof(float);
|
|
||||||
|
|
||||||
// Copy dref to buffer
|
|
||||||
buffer[5] = (unsigned char)drefLen;
|
|
||||||
memcpy(buffer + 6, dref, drefLen);
|
|
||||||
|
|
||||||
// Copy values to buffer
|
int sendDREFs(XPCSocket sock, const char* drefs[], float* values[], int sizes[], int count)
|
||||||
buffer[6 + drefLen] = (unsigned char)size;
|
{
|
||||||
memcpy(buffer + 7 + drefLen, value, size * sizeof(float));
|
// Setup command
|
||||||
|
// Max size is technically unlimited.
|
||||||
|
unsigned char buffer[65536] = "DREF";
|
||||||
|
int pos = 5;
|
||||||
|
for (int i = 0; i < count; ++i)
|
||||||
|
{
|
||||||
|
int drefLen = strnlen(drefs[i], 256);
|
||||||
|
if (pos + drefLen + sizes[i] * 4 + 2 > 65536)
|
||||||
|
{
|
||||||
|
printError("sendDREF", "About to overrun the send buffer!");
|
||||||
|
return -4;
|
||||||
|
}
|
||||||
|
if (drefLen > 255)
|
||||||
|
{
|
||||||
|
printError("sendDREF", "dref %d is too long. Must be less than 256 characters.", i);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (sizes[i] > 255)
|
||||||
|
{
|
||||||
|
printError("sendDREF", "size %d is too big. Must be less than 256.", i);
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
// Copy dref to buffer
|
||||||
|
buffer[pos++] = (unsigned char)drefLen;
|
||||||
|
memcpy(buffer + pos, drefs[i], drefLen);
|
||||||
|
pos += drefLen;
|
||||||
|
|
||||||
|
// Copy values to buffer
|
||||||
|
buffer[pos++] = (unsigned char)sizes[i];
|
||||||
|
memcpy(buffer + pos, values[i], sizes[i] * sizeof(float));
|
||||||
|
pos += sizes[i] * sizeof(float);
|
||||||
|
}
|
||||||
|
|
||||||
// Send command
|
// Send command
|
||||||
if (sendUDP(sock, buffer, len) < 0)
|
if (sendUDP(sock, buffer, pos) < 0)
|
||||||
{
|
{
|
||||||
printError("setDREF", "Failed to send command");
|
printError("setDREF", "Failed to send command");
|
||||||
return -3;
|
return -3;
|
||||||
|
|||||||
@@ -127,13 +127,27 @@ int sendDATA(XPCSocket sock, float data[][9], int rows);
|
|||||||
/// http://www.xsquawkbox.net/xpsdk/docs/DataRefs.html. The size of values should match
|
/// 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 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.
|
/// 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 sock The socket to use to send the command.
|
||||||
/// \param dref The name of the dataref to set.
|
/// \param dref The name of the dataref to set.
|
||||||
/// \param values An array of values representing the data to set.
|
/// \param value An array of values representing the data to set.
|
||||||
/// \param size The number of elements in values.
|
/// \param size The number of elements in values.
|
||||||
/// \returns 0 if successful, otherwise a negative value.
|
/// \returns 0 if successful, otherwise a negative value.
|
||||||
int sendDREF(XPCSocket sock, const char* dref, float value[], int size);
|
int sendDREF(XPCSocket sock, const char* dref, float value[], int size);
|
||||||
|
|
||||||
|
/// Sets the specified datarefs to the specified values.
|
||||||
|
///
|
||||||
|
/// \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 set.
|
||||||
|
/// \param values A multidimensional array containing the values for each dataref to set.
|
||||||
|
/// \param sizes The number of elements in each array in values
|
||||||
|
/// \param count The number of datarefs being set.
|
||||||
|
/// \returns 0 if successful, otherwise a negative value.
|
||||||
|
int sendDREFs(XPCSocket sock, const char* drefs[], float* values[], int sizes[], int count);
|
||||||
|
|
||||||
/// Gets the value of the specified dataref.
|
/// Gets the value of the specified dataref.
|
||||||
///
|
///
|
||||||
/// \details dref names and their associated data types can be found on the XPSDK wiki at
|
/// \details dref names and their associated data types can be found on the XPSDK wiki at
|
||||||
|
|||||||
@@ -331,43 +331,70 @@ public class XPlaneConnect implements AutoCloseable
|
|||||||
* @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 sendDREF(String dref, float[] value) throws IOException
|
||||||
|
{
|
||||||
|
sendDREFs(new String[] {dref}, new float[][] {value});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends a command to X-Plane that sets the given DREF.
|
||||||
|
*
|
||||||
|
* @param drefs The names of the X-Plane datarefs to set.
|
||||||
|
* @param values A sequence of arrays of floating point values whose structure depends on the drefs specified.
|
||||||
|
* @throws IOException If the command cannot be sent.
|
||||||
|
*/
|
||||||
|
public void sendDREFs(String[] drefs, float[][] values) throws IOException
|
||||||
{
|
{
|
||||||
//Preconditions
|
//Preconditions
|
||||||
if(dref == null)
|
if(drefs == null || drefs.length == 0)
|
||||||
{
|
{
|
||||||
throw new IllegalArgumentException("dref must be a valid string.");
|
throw new IllegalArgumentException(("drefs must be non-empty."));
|
||||||
}
|
}
|
||||||
if(value == null || value.length == 0)
|
if(values == null || values.length != drefs.length)
|
||||||
{
|
{
|
||||||
throw new IllegalArgumentException("value must be non-null and should contain at least one value.");
|
throw new IllegalArgumentException("values must be of the same size as drefs.");
|
||||||
}
|
}
|
||||||
|
|
||||||
//Convert drefs to bytes.
|
|
||||||
byte[] drefBytes = dref.getBytes(StandardCharsets.UTF_8);
|
|
||||||
if(drefBytes.length == 0)
|
|
||||||
{
|
|
||||||
throw new IllegalArgumentException("DREF is an empty string!");
|
|
||||||
}
|
|
||||||
if(drefBytes.length > 255)
|
|
||||||
{
|
|
||||||
throw new IllegalArgumentException("dref must be less than 255 bytes in UTF-8. Are you sure this is a valid dref?");
|
|
||||||
}
|
|
||||||
|
|
||||||
ByteBuffer bb = ByteBuffer.allocate(4 * value.length);
|
|
||||||
bb.order(ByteOrder.LITTLE_ENDIAN);
|
|
||||||
for(int i = 0; i < value.length; ++i)
|
|
||||||
{
|
|
||||||
bb.putFloat(i * 4, value[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
//Build and send message
|
|
||||||
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
||||||
os.write("DREF".getBytes(StandardCharsets.UTF_8));
|
os.write("DREF".getBytes(StandardCharsets.UTF_8));
|
||||||
os.write(0xFF); //Placeholder for message length
|
os.write(0xFF); //Placeholder for message length
|
||||||
os.write(drefBytes.length);
|
for(int i = 0; i < drefs.length; ++i)
|
||||||
os.write(drefBytes, 0, drefBytes.length);
|
{
|
||||||
os.write(value.length);
|
String dref = drefs[i];
|
||||||
os.write(bb.array());
|
float[] value = values[i];
|
||||||
|
|
||||||
|
if (dref == null)
|
||||||
|
{
|
||||||
|
throw new IllegalArgumentException("dref must be a valid string.");
|
||||||
|
}
|
||||||
|
if (value == null || value.length == 0)
|
||||||
|
{
|
||||||
|
throw new IllegalArgumentException("value must be non-null and should contain at least one value.");
|
||||||
|
}
|
||||||
|
|
||||||
|
//Convert drefs to bytes.
|
||||||
|
byte[] drefBytes = dref.getBytes(StandardCharsets.UTF_8);
|
||||||
|
if (drefBytes.length == 0)
|
||||||
|
{
|
||||||
|
throw new IllegalArgumentException("DREF is an empty string!");
|
||||||
|
}
|
||||||
|
if (drefBytes.length > 255)
|
||||||
|
{
|
||||||
|
throw new IllegalArgumentException("dref must be less than 255 bytes in UTF-8. Are you sure this is a valid dref?");
|
||||||
|
}
|
||||||
|
|
||||||
|
ByteBuffer bb = ByteBuffer.allocate(4 * value.length);
|
||||||
|
bb.order(ByteOrder.LITTLE_ENDIAN);
|
||||||
|
for (int j = 0; j < value.length; ++j)
|
||||||
|
{
|
||||||
|
bb.putFloat(j * 4, value[j]);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Build and send message
|
||||||
|
os.write(drefBytes.length);
|
||||||
|
os.write(drefBytes, 0, drefBytes.length);
|
||||||
|
os.write(value.length);
|
||||||
|
os.write(bb.array());
|
||||||
|
}
|
||||||
sendUDP(os.toByteArray());
|
sendUDP(os.toByteArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
@@ -1,17 +1,8 @@
|
|||||||
function sendDREF( dref, value, socket )
|
function sendDREF( dref, value, socket )
|
||||||
% sendDREF Sends a command to X-Plane that sets the given DREF.
|
% sendDREFs Sends a command to X-Plane that sets the given DREF. This
|
||||||
|
% function is now an alias to sendDREFs. It is kept only for backwards
|
||||||
|
% compatibility.
|
||||||
%
|
%
|
||||||
% 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
|
% Contributors
|
||||||
% [CT] Christopher Teubert (SGT, Inc.)
|
% [CT] Christopher Teubert (SGT, Inc.)
|
||||||
% christopher.a.teubert@nasa.gov
|
% christopher.a.teubert@nasa.gov
|
||||||
@@ -20,19 +11,8 @@ function sendDREF( dref, value, socket )
|
|||||||
|
|
||||||
import XPlaneConnect.*
|
import XPlaneConnect.*
|
||||||
|
|
||||||
%% Get client
|
|
||||||
global clients;
|
|
||||||
if ~exist('socket', 'var')
|
if ~exist('socket', 'var')
|
||||||
assert(isequal(length(clients) < 2, 1), '[setDREF] ERROR: Multiple clients open. You must specify which client to use.');
|
sendDREFs(dref, value)
|
||||||
if isempty(clients)
|
else
|
||||||
socket = openUDP();
|
sendDREFs(dref, value, socket)
|
||||||
else
|
end
|
||||||
socket = clients(1);
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
%% Validate input
|
|
||||||
value = single(value);
|
|
||||||
|
|
||||||
%%Send command
|
|
||||||
socket.sendDREF(dref, value);
|
|
||||||
37
MATLAB/+XPlaneConnect/sendDREFs.m
Normal file
37
MATLAB/+XPlaneConnect/sendDREFs.m
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
function sendDREFs( drefs, values, socket )
|
||||||
|
% sendDREFs Sends a command to X-Plane that sets the given DREF(s).
|
||||||
|
%
|
||||||
|
% Inputs
|
||||||
|
% dref: The name or names of the X-Plane dataref(s) to set.
|
||||||
|
% Value: An array or an multidimensional 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
|
||||||
|
% [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
|
||||||
|
values = single(values);
|
||||||
|
|
||||||
|
%%Send command
|
||||||
|
socket.sendDREFs(drefs, values);
|
||||||
@@ -79,8 +79,20 @@ class XPlaneConnect(object):
|
|||||||
if port < 0 or port > 65535:
|
if port < 0 or port > 65535:
|
||||||
raise ValueError("The specified port is not a valid port number.")
|
raise ValueError("The specified port is not a valid port number.")
|
||||||
|
|
||||||
|
#Send command
|
||||||
buffer = struct.pack("<4sxH", "CONN", port)
|
buffer = struct.pack("<4sxH", "CONN", port)
|
||||||
self.sendUDP(buffer)
|
self.sendUDP(buffer)
|
||||||
|
|
||||||
|
#Rebind socket
|
||||||
|
clientAddr = ("0.0.0.0", port)
|
||||||
|
timeout = self.socket.gettimeout();
|
||||||
|
self.socket.close();
|
||||||
|
self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
|
||||||
|
self.socket.bind(clientAddr)
|
||||||
|
self.socket.settimeout(timeout)
|
||||||
|
|
||||||
|
#Read response
|
||||||
|
buffer = self.socket.recv(1024)
|
||||||
|
|
||||||
def pauseSim(self, pause):
|
def pauseSim(self, pause):
|
||||||
'''Pauses or un-pauses the physics simulation engine in X-Plane.
|
'''Pauses or un-pauses the physics simulation engine in X-Plane.
|
||||||
@@ -208,31 +220,45 @@ class XPlaneConnect(object):
|
|||||||
# Send
|
# Send
|
||||||
self.sendUDP(buffer)
|
self.sendUDP(buffer)
|
||||||
|
|
||||||
# DREF Manipulation
|
# DREF Manipulation
|
||||||
def sendDREF(self, dref, values):
|
def sendDREF(self, dref, values):
|
||||||
'''Sets the specified dataref to the specified value.
|
'''Sets the specified dataref to the specified value.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
dref: The name of the dataref to set.
|
dref: The name of the datarefs to set.
|
||||||
values: Either a scalar value or a sequence of values.
|
values: Either a scalar value or a sequence of values.
|
||||||
'''
|
'''
|
||||||
# Preconditions
|
self.sendDREFs([dref], [values])
|
||||||
if len(dref) == 0 or len(dref) > 255:
|
|
||||||
raise ValueError("dref must be a non-empty string less than 256 characters.")
|
def sendDREFs(self, drefs, values):
|
||||||
if values == None:
|
'''Sets the specified datarefs to the specified values.
|
||||||
raise ValueError("values must be a scalar or sequence of floats.")
|
|
||||||
|
Args:
|
||||||
|
drefs: A list of names of the datarefs to set.
|
||||||
|
values: A list of scalar or vector values to set.
|
||||||
|
'''
|
||||||
|
if len(drefs) != len(values):
|
||||||
|
raise ValueError("drefs and values must have the same number of elements.")
|
||||||
|
|
||||||
|
buffer = struct.pack("<4sx", "DREF")
|
||||||
|
for i in range(len(drefs)):
|
||||||
|
dref = drefs[i]
|
||||||
|
value = values[i]
|
||||||
|
# Preconditions
|
||||||
|
if len(dref) == 0 or len(dref) > 255:
|
||||||
|
raise ValueError("dref must be a non-empty string less than 256 characters.")
|
||||||
|
if value == None:
|
||||||
|
raise ValueError("value must be a scalar or sequence of floats.")
|
||||||
|
|
||||||
# Pack message
|
# Pack message
|
||||||
fmt = ""
|
if hasattr(value, "__len__"):
|
||||||
buffer = None
|
if len(value) > 255:
|
||||||
if hasattr(values, "__len__"):
|
raise ValueError("value must have less than 256 items.")
|
||||||
if len(values) > 255:
|
fmt = "<B{0:d}sB{1:d}f".format(len(dref), len(value))
|
||||||
raise ValueError("values must have less than 256 items.")
|
buffer += struct.pack(fmt, len(dref), dref, len(value), value)
|
||||||
fmt = "<4sxB{0:d}sB{1:d}f".format(len(dref), len(values))
|
else:
|
||||||
buffer = struct.pack(fmt, "DREF", len(dref), dref, len(values), values)
|
fmt = "<B{0:d}sBf".format(len(dref))
|
||||||
else:
|
buffer += struct.pack(fmt, len(dref), dref, 1, value)
|
||||||
fmt = "<4sxB{0:d}sBf".format(len(dref))
|
|
||||||
buffer = struct.pack(fmt, "DREF", len(dref), dref, 1, values)
|
|
||||||
|
|
||||||
# Send
|
# Send
|
||||||
self.sendUDP(buffer)
|
self.sendUDP(buffer)
|
||||||
|
|||||||
@@ -21,9 +21,19 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="..\..\C\src\xplaneConnect.c" />
|
<ClCompile Include="..\..\C\src\xplaneConnect.c" />
|
||||||
<ClCompile Include="..\C Tests\main.c" />
|
<ClCompile Include="..\C Tests\main.c" />
|
||||||
|
<ClCompile Include="..\C Tests\Test.c" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="..\..\C\src\xplaneConnect.h" />
|
<ClInclude Include="..\..\C\src\xplaneConnect.h" />
|
||||||
|
<ClInclude Include="..\C Tests\CtrlTests.h" />
|
||||||
|
<ClInclude Include="..\C Tests\DataTests.h" />
|
||||||
|
<ClInclude Include="..\C Tests\DrefTests.h" />
|
||||||
|
<ClInclude Include="..\C Tests\PosiTests.h" />
|
||||||
|
<ClInclude Include="..\C Tests\SimuTests.h" />
|
||||||
|
<ClInclude Include="..\C Tests\Test.h" />
|
||||||
|
<ClInclude Include="..\C Tests\TextTests.h" />
|
||||||
|
<ClInclude Include="..\C Tests\UDPTests.h" />
|
||||||
|
<ClInclude Include="..\C Tests\WyptTests.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<PropertyGroup Label="Globals">
|
<PropertyGroup Label="Globals">
|
||||||
<ProjectGuid>{BC701AF4-552C-4C9D-82A1-B352542783A4}</ProjectGuid>
|
<ProjectGuid>{BC701AF4-552C-4C9D-82A1-B352542783A4}</ProjectGuid>
|
||||||
|
|||||||
@@ -21,10 +21,40 @@
|
|||||||
<ClCompile Include="..\..\C\src\xplaneConnect.c">
|
<ClCompile Include="..\..\C\src\xplaneConnect.c">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\C Tests\Test.c">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="..\..\C\src\xplaneConnect.h">
|
<ClInclude Include="..\..\C\src\xplaneConnect.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\C Tests\UDPTests.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\C Tests\DrefTests.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\C Tests\TextTests.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\C Tests\SimuTests.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\C Tests\CtrlTests.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\C Tests\DataTests.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\C Tests\PosiTests.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\C Tests\WyptTests.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\C Tests\Test.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
147
TestScripts/C Tests/CtrlTests.h
Normal file
147
TestScripts/C Tests/CtrlTests.h
Normal file
@@ -0,0 +1,147 @@
|
|||||||
|
//Copyright (c) 2013-2015 United States Government as represented by the Administrator of the
|
||||||
|
//National Aeronautics and Space Administration. All Rights Reserved.
|
||||||
|
#ifndef CTRLTESTS_H
|
||||||
|
#define CTRLTESTS_H
|
||||||
|
|
||||||
|
#include "Test.h"
|
||||||
|
#include "xplaneConnect.h"
|
||||||
|
|
||||||
|
int doCTRLTest(char* drefs[7], float values[], int size, int ac, float expected[7])
|
||||||
|
{
|
||||||
|
float* data[7];
|
||||||
|
int sizes[7];
|
||||||
|
for (int i = 0; i < 7; ++i)
|
||||||
|
{
|
||||||
|
data[i] = (float*)malloc(sizeof(float) * 16);
|
||||||
|
sizes[i] = 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Execute command
|
||||||
|
XPCSocket sock = openUDP(IP);
|
||||||
|
int result = sendCTRL(sock, values, size, ac);
|
||||||
|
if (result >= 0)
|
||||||
|
{
|
||||||
|
result = getDREFs(sock, drefs, data, 7, sizes);
|
||||||
|
}
|
||||||
|
closeUDP(sock);
|
||||||
|
if (result < 0)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test values
|
||||||
|
float actual[7];
|
||||||
|
for (int i = 0; i < 7; ++i)
|
||||||
|
{
|
||||||
|
actual[i] = data[i][0];
|
||||||
|
}
|
||||||
|
return compareArray(expected, actual, 7);
|
||||||
|
}
|
||||||
|
|
||||||
|
int basicCTRLTest(char** drefs, int ac)
|
||||||
|
{
|
||||||
|
// Set control surfaces to known state.
|
||||||
|
float CTRL[6] = { 0.0F, 0.0F, 0.0F, 0.8F, 1.0F, 0.5F };
|
||||||
|
float expected[7] = { 0.0F, 0.0F, 0.0F, NAN, NAN, NAN, NAN };
|
||||||
|
int result = doCTRLTest(drefs, CTRL, 3, ac, expected);
|
||||||
|
if (result < 0)
|
||||||
|
{
|
||||||
|
return -10000 + result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test control surfaces and set other values to known state.
|
||||||
|
expected[0] = CTRL[0] = 0.2F;
|
||||||
|
expected[1] = CTRL[1] = 0.1F;
|
||||||
|
expected[2] = CTRL[2] = 0.1F;
|
||||||
|
expected[3] = 0.8F;
|
||||||
|
expected[4] = 1.0F;
|
||||||
|
expected[5] = 0.5F;
|
||||||
|
result = doCTRLTest(drefs, CTRL, 6, ac, expected);
|
||||||
|
if (result < 0)
|
||||||
|
{
|
||||||
|
return -20000 + result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test other values and verify control surfaces unchanged.
|
||||||
|
CTRL[0] = -998;
|
||||||
|
CTRL[1] = -998;
|
||||||
|
CTRL[2] = -998;
|
||||||
|
expected[3] = CTRL[3] = 0.9F;
|
||||||
|
expected[4] = CTRL[4] = 0.0F;
|
||||||
|
expected[5] = CTRL[5] = 0.75F;
|
||||||
|
result = doCTRLTest(drefs, CTRL, 6, ac, expected);
|
||||||
|
if (result < 0)
|
||||||
|
{
|
||||||
|
return -30000 + result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int testCTRL_Player()
|
||||||
|
{
|
||||||
|
char* drefs[] =
|
||||||
|
{
|
||||||
|
"sim/cockpit2/controls/yoke_pitch_ratio",
|
||||||
|
"sim/cockpit2/controls/yoke_roll_ratio",
|
||||||
|
"sim/cockpit2/controls/yoke_heading_ratio",
|
||||||
|
"sim/flightmodel/engine/ENGN_thro",
|
||||||
|
"sim/cockpit/switches/gear_handle_status",
|
||||||
|
"sim/flightmodel/controls/flaprqst",
|
||||||
|
"sim/flightmodel/controls/sbrkrqst"
|
||||||
|
};
|
||||||
|
return basicCTRLTest(drefs, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int testCTRL_NonPlayer()
|
||||||
|
{
|
||||||
|
char* drefs[] =
|
||||||
|
{
|
||||||
|
"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",
|
||||||
|
"sim/multiplayer/position/plane1_sbrkrqst"
|
||||||
|
};
|
||||||
|
return basicCTRLTest(drefs, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int testCTRL_Speedbrakes()
|
||||||
|
{
|
||||||
|
char* drefs[] =
|
||||||
|
{
|
||||||
|
"sim/cockpit2/controls/yoke_pitch_ratio",
|
||||||
|
"sim/cockpit2/controls/yoke_roll_ratio",
|
||||||
|
"sim/cockpit2/controls/yoke_heading_ratio",
|
||||||
|
"sim/flightmodel/engine/ENGN_thro",
|
||||||
|
"sim/cockpit/switches/gear_handle_status",
|
||||||
|
"sim/flightmodel/controls/flaprqst",
|
||||||
|
"sim/flightmodel/controls/sbrkrqst"
|
||||||
|
};
|
||||||
|
|
||||||
|
// Arm
|
||||||
|
float CTRL[7] = { -998, -998, -998, -998, -998, -998, -0.5F };
|
||||||
|
float expected[7] = { NAN, NAN, NAN, NAN, NAN, NAN, -0.5F };
|
||||||
|
int result = doCTRLTest(drefs, CTRL, 7, 0, expected);
|
||||||
|
if (result < 0)
|
||||||
|
{
|
||||||
|
return -10000 + result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set to full
|
||||||
|
expected[6] = CTRL[6] = 1.5F;
|
||||||
|
result = doCTRLTest(drefs, CTRL, 7, 0, expected);
|
||||||
|
if (result < 0)
|
||||||
|
{
|
||||||
|
return -20000 + result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Retract
|
||||||
|
expected[6] = CTRL[6] = 0.0F;
|
||||||
|
result = doCTRLTest(drefs, CTRL, 7, 0, expected);
|
||||||
|
if (result < 0)
|
||||||
|
{
|
||||||
|
return -30000 + result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
62
TestScripts/C Tests/DataTests.h
Normal file
62
TestScripts/C Tests/DataTests.h
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
//Copyright (c) 2013-2015 United States Government as represented by the Administrator of the
|
||||||
|
//National Aeronautics and Space Administration. All Rights Reserved.
|
||||||
|
#ifndef DATATESTS_H
|
||||||
|
#define DATATESTS_H
|
||||||
|
|
||||||
|
#include "Test.h"
|
||||||
|
#include "xplaneConnect.h"
|
||||||
|
|
||||||
|
int testDATA()
|
||||||
|
{
|
||||||
|
// Initialize
|
||||||
|
int i, j; // Iterator
|
||||||
|
char* drefs[100] =
|
||||||
|
{
|
||||||
|
"sim/aircraft/parts/acf_gear_deploy"
|
||||||
|
};
|
||||||
|
float* data[100]; // array for result of getDREFs
|
||||||
|
int sizes[100];
|
||||||
|
float DATA[4][9]; // Array for sendDATA
|
||||||
|
XPCSocket sock = openUDP(IP);
|
||||||
|
|
||||||
|
// Setup
|
||||||
|
for (int i = 0; i < 100; ++i)
|
||||||
|
{
|
||||||
|
data[i] = (float*)malloc(40 * sizeof(float));
|
||||||
|
sizes[i] = 40;
|
||||||
|
}
|
||||||
|
for (i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
for (j = 0; j < 9; j++)
|
||||||
|
{
|
||||||
|
data[i][j] = -998;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DATA[0][0] = 14; // Gear
|
||||||
|
DATA[0][1] = 1;
|
||||||
|
DATA[0][2] = 0;
|
||||||
|
|
||||||
|
// Execution
|
||||||
|
sendDATA(sock, DATA, 1);
|
||||||
|
int result = getDREFs(sock, drefs, data, 1, sizes);
|
||||||
|
|
||||||
|
// Close
|
||||||
|
closeUDP(sock);
|
||||||
|
|
||||||
|
// Tests
|
||||||
|
if (result < 0)// Request 1 value
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (sizes[0] != 10)
|
||||||
|
{
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
if (*data[0] != data[0][1])
|
||||||
|
{
|
||||||
|
return -3;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
247
TestScripts/C Tests/DrefTests.h
Normal file
247
TestScripts/C Tests/DrefTests.h
Normal file
@@ -0,0 +1,247 @@
|
|||||||
|
//Copyright (c) 2013-2015 United States Government as represented by the Administrator of the
|
||||||
|
//National Aeronautics and Space Administration. All Rights Reserved.
|
||||||
|
#ifndef DREFTESTS_H
|
||||||
|
#define DREFTESTS_H
|
||||||
|
|
||||||
|
#include "Test.h"
|
||||||
|
#include "xplaneConnect.h"
|
||||||
|
|
||||||
|
int doGETDTest(char* drefs[], float* expected[], int count, int sizes[])
|
||||||
|
{
|
||||||
|
// Setup memory
|
||||||
|
int* asizes = (int*)malloc(sizeof(int) * count);
|
||||||
|
float** actual = (float**)malloc(sizeof(float*) * count);
|
||||||
|
for (int i = 0; i < count; ++i)
|
||||||
|
{
|
||||||
|
asizes[i] = sizes[i];
|
||||||
|
actual[i] = (float*)malloc(sizeof(float) * sizes[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Execute command
|
||||||
|
XPCSocket sock = openUDP(IP);
|
||||||
|
int result = getDREFs(sock, drefs, actual, count, asizes);
|
||||||
|
closeUDP(sock);
|
||||||
|
if (result < 0)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test sizes and values
|
||||||
|
result = compareArrays(expected, sizes, actual, asizes, count);
|
||||||
|
for (int i = 0; i < count; ++i)
|
||||||
|
{
|
||||||
|
free(actual[i]);
|
||||||
|
}
|
||||||
|
free(actual);
|
||||||
|
free(asizes);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int doDREFTest(char* drefs[], float* values[], float* expected[], int count, int sizes[])
|
||||||
|
{
|
||||||
|
// Setup memory
|
||||||
|
int* asizes = (int*)malloc(sizeof(int) * count);
|
||||||
|
float** actual = (float**)malloc(sizeof(float*) * count);
|
||||||
|
for (int i = 0; i < count; ++i)
|
||||||
|
{
|
||||||
|
asizes[i] = sizes[i];
|
||||||
|
actual[i] = (float*)malloc(sizeof(float) * sizes[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Execute command
|
||||||
|
XPCSocket sock = openUDP(IP);
|
||||||
|
int result = sendDREFs(sock, drefs, values, sizes, count);
|
||||||
|
if (result >= 0)
|
||||||
|
{
|
||||||
|
result = getDREFs(sock, drefs, actual, count, asizes);
|
||||||
|
}
|
||||||
|
closeUDP(sock);
|
||||||
|
if (result < 0)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test sizes and values
|
||||||
|
result = compareArrays(expected, sizes, actual, asizes, count);
|
||||||
|
for (int i = 0; i < count; ++i)
|
||||||
|
{
|
||||||
|
free(actual[i]);
|
||||||
|
}
|
||||||
|
free(actual);
|
||||||
|
free(asizes);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int testGETD_Basic()
|
||||||
|
{
|
||||||
|
char* drefs[] =
|
||||||
|
{
|
||||||
|
"sim/cockpit/switches/gear_handle_status", //int
|
||||||
|
"sim/cockpit/autopilot/altitude", //float
|
||||||
|
"sim/aircraft/prop/acf_prop_type", //int[8]
|
||||||
|
"sim/cockpit2/switches/panel_brightness_ratio", //float[4]
|
||||||
|
"sim/aircraft/view/acf_tailnum", //byte[40]
|
||||||
|
"sim/flightmodel/position/elevation" //double
|
||||||
|
};
|
||||||
|
int sizes[] = { 1, 1, 8, 4, 40, 1 };
|
||||||
|
float* expected[6];
|
||||||
|
for (int i = 0; i < 6; ++i)
|
||||||
|
{
|
||||||
|
expected[i] = (float*)malloc(sizeof(float) * sizes[i]);
|
||||||
|
for (int j = 0; j < sizes[i]; ++j)
|
||||||
|
{
|
||||||
|
expected[i][j] = NAN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return doGETDTest(drefs, expected, 6, sizes);
|
||||||
|
}
|
||||||
|
|
||||||
|
int testGETD_TestFloat()
|
||||||
|
{
|
||||||
|
char* dref = "sim/test/test_float";
|
||||||
|
int size = 1;
|
||||||
|
float* expected[1];
|
||||||
|
expected[0] = (float*)malloc(sizeof(float));
|
||||||
|
expected[0][0] = 0.0F;
|
||||||
|
|
||||||
|
int result = doGETDTest(&dref, &expected, 1, &size);
|
||||||
|
free(expected[0]);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int testGETD_Types()
|
||||||
|
{
|
||||||
|
char* drefs[] =
|
||||||
|
{
|
||||||
|
"sim/cockpit/switches/gear_handle_status", //int
|
||||||
|
"sim/cockpit/autopilot/altitude", //float
|
||||||
|
"sim/aircraft/prop/acf_prop_type", //int[8]
|
||||||
|
"sim/cockpit2/switches/panel_brightness_ratio", //float[4]
|
||||||
|
"sim/aircraft/view/acf_tailnum", //byte[40]
|
||||||
|
"sim/flightmodel/position/elevation" //double
|
||||||
|
};
|
||||||
|
int sizes[] = { 1, 1, 8, 4, 40, 1 };
|
||||||
|
float* data[6];
|
||||||
|
for (int i = 0; i < 6; ++i)
|
||||||
|
{
|
||||||
|
data[i] = (float*)malloc(sizeof(float) * sizes[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Execute command
|
||||||
|
XPCSocket sock = openUDP(IP);
|
||||||
|
int result = getDREFs(sock, drefs, data, 6, sizes);
|
||||||
|
closeUDP(sock);
|
||||||
|
|
||||||
|
// Tests
|
||||||
|
if (result < 0)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
// Verify sizes
|
||||||
|
if (sizes[0] != 1 || sizes[1] != 1 || sizes[2] != 8
|
||||||
|
|| sizes[3] != 4 || sizes[4] != 40 || sizes[5] != 1)
|
||||||
|
{
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
// Verify integer drefs are integers
|
||||||
|
if ((float)((int)data[0][0]) != data[0][0])
|
||||||
|
{
|
||||||
|
return -3;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < 8; ++i)
|
||||||
|
{
|
||||||
|
if ((float)((int)data[2][i]) != data[2][i])
|
||||||
|
{
|
||||||
|
return -3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int i = 0; i < 40; ++i)
|
||||||
|
{
|
||||||
|
if ((float)((char)data[4][i]) != data[4][i])
|
||||||
|
{
|
||||||
|
return -3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Verify tail number has at least one valid character
|
||||||
|
if (data[4][0] <= 0 || data[4][0] > 127)
|
||||||
|
{
|
||||||
|
return -4;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int testDREF()
|
||||||
|
{
|
||||||
|
char* drefs[] =
|
||||||
|
{
|
||||||
|
"sim/cockpit/switches/gear_handle_status", //int
|
||||||
|
"sim/cockpit/autopilot/altitude", //float
|
||||||
|
"sim/aircraft/prop/acf_prop_type", //int[8]
|
||||||
|
"sim/cockpit2/switches/panel_brightness_ratio", //float[4]
|
||||||
|
"sim/aircraft/view/acf_tailnum", //byte[40]
|
||||||
|
"sim/flightmodel/position/elevation" //double - Read only
|
||||||
|
};
|
||||||
|
float* values[6];
|
||||||
|
float* expected[6];
|
||||||
|
int sizes[6];
|
||||||
|
|
||||||
|
// Setup
|
||||||
|
sizes[0] = 1;
|
||||||
|
values[0] = (float*)malloc(sizes[0] * sizeof(float));
|
||||||
|
expected[0] = values[0];
|
||||||
|
values[0][0] = 1;
|
||||||
|
|
||||||
|
sizes[1] = 1;
|
||||||
|
values[1] = (float*)malloc(sizes[1] * sizeof(float));
|
||||||
|
expected[1] = values[1];
|
||||||
|
values[1][0] = 4000.0F;
|
||||||
|
|
||||||
|
sizes[2] = 8;
|
||||||
|
values[2] = (float*)malloc(sizes[2] * sizeof(float));
|
||||||
|
expected[2] = values[2];
|
||||||
|
for (int i = 0; i < 8; ++i)
|
||||||
|
{
|
||||||
|
values[2][i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
sizes[3] = 4;
|
||||||
|
values[3] = (float*)malloc(sizes[3] * sizeof(float));
|
||||||
|
expected[3] = values[3];
|
||||||
|
for (int i = 0; i < 4; ++i)
|
||||||
|
{
|
||||||
|
values[3][i] = 0.25F;
|
||||||
|
}
|
||||||
|
|
||||||
|
sizes[4] = 40;
|
||||||
|
values[4] = (float*)malloc(sizes[4] * sizeof(float));
|
||||||
|
expected[4] = (float*)malloc(sizes[4] * sizeof(float));
|
||||||
|
memset(values[4], 0, sizes[4] * sizeof(float));
|
||||||
|
values[4][0] = 78.0F; //N
|
||||||
|
values[4][1] = 55.0F; //7
|
||||||
|
values[4][2] = 52.0F; //4
|
||||||
|
values[4][3] = 56.0F; //8
|
||||||
|
values[4][4] = 53.0F; //5
|
||||||
|
values[4][5] = 89.0F; //Y
|
||||||
|
|
||||||
|
expected[4][0] = 78.0F; //N
|
||||||
|
expected[4][1] = 55.0F; //7
|
||||||
|
expected[4][2] = 52.0F; //4
|
||||||
|
expected[4][3] = 56.0F; //8
|
||||||
|
expected[4][4] = 53.0F; //5
|
||||||
|
expected[4][5] = 89.0F; //Y
|
||||||
|
for (int i = 6; i < sizes[4]; ++i)
|
||||||
|
{
|
||||||
|
expected[4][i] = NAN;
|
||||||
|
}
|
||||||
|
|
||||||
|
sizes[5] = 1;
|
||||||
|
values[5] = (float*)malloc(sizes[5] * sizeof(float));
|
||||||
|
expected[5] = (float*)malloc(sizes[5] * sizeof(float));
|
||||||
|
values[5][0] = 5000.0F;
|
||||||
|
expected[5][0] = NAN;
|
||||||
|
|
||||||
|
return doDREFTest(drefs, values, expected, 6, sizes);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
120
TestScripts/C Tests/PosiTests.h
Normal file
120
TestScripts/C Tests/PosiTests.h
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
//Copyright (c) 2013-2015 United States Government as represented by the Administrator of the
|
||||||
|
//National Aeronautics and Space Administration. All Rights Reserved.
|
||||||
|
#ifndef POSITESTS_H
|
||||||
|
#define POSITESTS_H
|
||||||
|
|
||||||
|
#include "Test.h"
|
||||||
|
#include "xplaneConnect.h"
|
||||||
|
|
||||||
|
int doPOSITest(char* drefs[7], float values[], int size, int ac, float expected[7])
|
||||||
|
{
|
||||||
|
float* data[7];
|
||||||
|
int sizes[7];
|
||||||
|
for (int i = 0; i < 7; ++i)
|
||||||
|
{
|
||||||
|
data[i] = (float*)malloc(sizeof(float) * 10);
|
||||||
|
sizes[i] = 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Execute command
|
||||||
|
XPCSocket sock = openUDP(IP);
|
||||||
|
pauseSim(sock, 1);
|
||||||
|
int result = sendPOSI(sock, values, size, ac);
|
||||||
|
if (result >= 0)
|
||||||
|
{
|
||||||
|
result = getDREFs(sock, drefs, data, 7, sizes);
|
||||||
|
}
|
||||||
|
pauseSim(sock, 0);
|
||||||
|
closeUDP(sock);
|
||||||
|
if (result < 0)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test values
|
||||||
|
float actual[7];
|
||||||
|
for (int i = 0; i < 7; ++i)
|
||||||
|
{
|
||||||
|
actual[i] = data[i][0];
|
||||||
|
}
|
||||||
|
return compareArray(expected, actual, 7);
|
||||||
|
}
|
||||||
|
|
||||||
|
int basicPOSITest(char** drefs, int ac)
|
||||||
|
{
|
||||||
|
// Set psoition and initial orientation
|
||||||
|
float POSI[7] = { 37.524F, -122.06899F, 2500, 0, 0, 0, 1 };
|
||||||
|
float expected[7] = { 37.524F, -122.06899F, 2500, 0, 0, 0, 1 };
|
||||||
|
int result = doPOSITest(drefs, POSI, 7, ac, expected);
|
||||||
|
if (result < 0)
|
||||||
|
{
|
||||||
|
return -10000 + result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set orientation
|
||||||
|
POSI[0] = -998.0F;
|
||||||
|
POSI[1] = -998.0F;
|
||||||
|
POSI[2] = -998.0F;
|
||||||
|
POSI[3] = 5.0F;
|
||||||
|
POSI[4] = -5.0F;
|
||||||
|
POSI[5] = 10.0F;
|
||||||
|
POSI[6] = 0;
|
||||||
|
|
||||||
|
float *loc[3];
|
||||||
|
for (int i = 0; i < 3; ++i)
|
||||||
|
{
|
||||||
|
loc[i] = (float*)malloc(sizeof(float));
|
||||||
|
}
|
||||||
|
int sizes[3] = { 1, 1, 1 };
|
||||||
|
XPCSocket sock = openUDP(IP);
|
||||||
|
pauseSim(sock, 1);
|
||||||
|
getDREFs(sock, drefs, loc, 3, sizes);
|
||||||
|
closeUDP(sock);
|
||||||
|
|
||||||
|
expected[0] = loc[0][0];
|
||||||
|
expected[1] = loc[1][0];
|
||||||
|
expected[2] = loc[2][0];
|
||||||
|
expected[3] = 5.0F;
|
||||||
|
expected[4] = -5.0F;
|
||||||
|
expected[5] = 10.0F;
|
||||||
|
expected[6] = 0.0F;
|
||||||
|
result = doPOSITest(drefs, POSI, 7, ac, expected);
|
||||||
|
if (result < 0)
|
||||||
|
{
|
||||||
|
return -20000 + result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int testPOSI_Player()
|
||||||
|
{
|
||||||
|
char* drefs[] =
|
||||||
|
{
|
||||||
|
"sim/flightmodel/position/latitude",
|
||||||
|
"sim/flightmodel/position/longitude",
|
||||||
|
"sim/flightmodel/position/elevation",
|
||||||
|
"sim/flightmodel/position/theta",
|
||||||
|
"sim/flightmodel/position/phi",
|
||||||
|
"sim/flightmodel/position/psi",
|
||||||
|
"sim/cockpit/switches/gear_handle_status"
|
||||||
|
};
|
||||||
|
return basicPOSITest(drefs, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int testPOSI_NonPlayer()
|
||||||
|
{
|
||||||
|
char* drefs[] =
|
||||||
|
{
|
||||||
|
"sim/multiplayer/position/plane1_lat",
|
||||||
|
"sim/multiplayer/position/plane1_lon",
|
||||||
|
"sim/multiplayer/position/plane1_el",
|
||||||
|
"sim/multiplayer/position/plane1_the",
|
||||||
|
"sim/multiplayer/position/plane1_phi",
|
||||||
|
"sim/multiplayer/position/plane1_psi",
|
||||||
|
"sim/multiplayer/position/plane1_gear_deploy"
|
||||||
|
};
|
||||||
|
return basicPOSITest(drefs, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
80
TestScripts/C Tests/SimuTests.h
Normal file
80
TestScripts/C Tests/SimuTests.h
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
//Copyright (c) 2013-2015 United States Government as represented by the Administrator of the
|
||||||
|
//National Aeronautics and Space Administration. All Rights Reserved.
|
||||||
|
#ifndef SIMUTESTS_H
|
||||||
|
#define SIMIUTESTS_H
|
||||||
|
|
||||||
|
#include "Test.h"
|
||||||
|
#include "xplaneConnect.h"
|
||||||
|
|
||||||
|
int doSIMUTest(int value, float expected)
|
||||||
|
{
|
||||||
|
int size = 20;
|
||||||
|
float actual[20];
|
||||||
|
char* dref = "sim/operation/override/override_planepath";
|
||||||
|
|
||||||
|
XPCSocket sock = openUDP(IP);
|
||||||
|
int result = pauseSim(sock, value);
|
||||||
|
if (result >= 0)
|
||||||
|
{
|
||||||
|
result = getDREF(sock, dref, &actual, &size);
|
||||||
|
}
|
||||||
|
closeUDP(sock);
|
||||||
|
if (result < 0)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < 20; ++i)
|
||||||
|
{
|
||||||
|
if (!feq(actual[i], expected) && !isnan(expected))
|
||||||
|
{
|
||||||
|
return -100 - i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int testSIMU_Basic()
|
||||||
|
{
|
||||||
|
int result = doSIMUTest(0, 0);
|
||||||
|
if (result < 0)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = doSIMUTest(1, 1);
|
||||||
|
if (result < 0)
|
||||||
|
{
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = doSIMUTest(0, 0);
|
||||||
|
if (result < 0)
|
||||||
|
{
|
||||||
|
return -3;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int testSIMU_Toggle()
|
||||||
|
{
|
||||||
|
int result = doSIMUTest(0, 0);
|
||||||
|
if (result < 0)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = doSIMUTest(2, 1);
|
||||||
|
if (result < 0)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = doSIMUTest(2, 0);
|
||||||
|
if (result < 0)
|
||||||
|
{
|
||||||
|
return -3;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
51
TestScripts/C Tests/Test.c
Normal file
51
TestScripts/C Tests/Test.c
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
//Copyright (c) 2013-2015 United States Government as represented by the Administrator of the
|
||||||
|
//National Aeronautics and Space Administration. All Rights Reserved.
|
||||||
|
#include "Test.h"
|
||||||
|
|
||||||
|
int testFailed = 0;
|
||||||
|
int testPassed = 0;
|
||||||
|
|
||||||
|
void runTest(int(*test)(), char* name)
|
||||||
|
{
|
||||||
|
printf("Running test %s... ", name);
|
||||||
|
int result = test(); // Run Test
|
||||||
|
if (result == 0)
|
||||||
|
{
|
||||||
|
printf("PASSED\n");
|
||||||
|
testPassed++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("Test %s - FAILED\n\tError: %i\n", name, result);
|
||||||
|
testFailed++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int compareFloat(float expected, float actual)
|
||||||
|
{
|
||||||
|
return feq(expected, actual) || isnan(expected) ? 0 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int compareArray(float expected[], float actual[], int size)
|
||||||
|
{
|
||||||
|
return compareArrays(&expected, &size, &actual, &size, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int compareArrays(float* expected[], int esizes[], float* actual[], int asizes[], int count)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < count; ++i)
|
||||||
|
{
|
||||||
|
if (esizes[i] != asizes[i])
|
||||||
|
{
|
||||||
|
return -100 - i;
|
||||||
|
}
|
||||||
|
for (int j = 0; j < esizes[i]; ++j)
|
||||||
|
{
|
||||||
|
if (!feq(actual[i][j], expected[i][j]) && !isnan(expected[i][j]))
|
||||||
|
{
|
||||||
|
return -1000 - i * 100 - j;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
25
TestScripts/C Tests/Test.h
Normal file
25
TestScripts/C Tests/Test.h
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
//Copyright (c) 2013-2015 United States Government as represented by the Administrator of the
|
||||||
|
//National Aeronautics and Space Administration. All Rights Reserved.
|
||||||
|
#ifndef TESTRUNNER_H
|
||||||
|
#define TESTRUNNER_H
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#define feq(x, y) (fabs(x - y) < 1e-4)
|
||||||
|
|
||||||
|
#define IP "127.0.0.1"
|
||||||
|
|
||||||
|
extern int testFailed;
|
||||||
|
extern int testPassed;
|
||||||
|
|
||||||
|
void runTest(int(*test)(), char* name);
|
||||||
|
|
||||||
|
int compareFloat(float expected, float actual);
|
||||||
|
int compareArray(float expected[], float actual[], int size);
|
||||||
|
int compareArrays(float* expected[], int esizes[], float* actual[], int asizes[], int count);
|
||||||
|
|
||||||
|
#endif
|
||||||
32
TestScripts/C Tests/TextTests.h
Normal file
32
TestScripts/C Tests/TextTests.h
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
//Copyright (c) 2013-2015 United States Government as represented by the Administrator of the
|
||||||
|
//National Aeronautics and Space Administration. All Rights Reserved.
|
||||||
|
#ifndef TEXTTESTS_H
|
||||||
|
#define TEXTTESTS_H
|
||||||
|
|
||||||
|
#include "Test.h"
|
||||||
|
#include "xplaneConnect.h"
|
||||||
|
|
||||||
|
int testTEXT()
|
||||||
|
{
|
||||||
|
// Setup
|
||||||
|
XPCSocket sendPort = openUDP(IP);
|
||||||
|
int x = 100;
|
||||||
|
int y = 700;
|
||||||
|
char* msg = "This is an X-Plane Connect test message.\nThis should be a new line.\r\nThat will be parsed as two line breaks.";
|
||||||
|
|
||||||
|
// Test
|
||||||
|
sendTEXT(sendPort, msg, x, y);
|
||||||
|
// NOTE: Manually verify that msg appears on the screen in X-Plane!
|
||||||
|
|
||||||
|
sendTEXT(sendPort, "Another test message", x, y);
|
||||||
|
// NOTE: Manually verify that msg appears on the screen and that no part of the previous
|
||||||
|
// message is visible.
|
||||||
|
|
||||||
|
sendTEXT(sendPort, NULL, -1, -1);
|
||||||
|
|
||||||
|
// Cleanup
|
||||||
|
closeUDP(sendPort);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
55
TestScripts/C Tests/UDPTests.h
Normal file
55
TestScripts/C Tests/UDPTests.h
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
//Copyright (c) 2013-2015 United States Government as represented by the Administrator of the
|
||||||
|
//National Aeronautics and Space Administration. All Rights Reserved.
|
||||||
|
#ifndef UDPTESTS_H
|
||||||
|
#define UDPTESTS_H
|
||||||
|
|
||||||
|
#include "Test.h"
|
||||||
|
#include "xplaneConnect.h"
|
||||||
|
|
||||||
|
int testOpen()
|
||||||
|
{
|
||||||
|
XPCSocket sock = openUDP("localhost");
|
||||||
|
int result = strncmp(sock.xpIP, "127.0.0.1", 16);
|
||||||
|
closeUDP(sock);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int testClose()
|
||||||
|
{
|
||||||
|
XPCSocket sendPort = aopenUDP(IP, 49009, 49063);
|
||||||
|
closeUDP(sendPort);
|
||||||
|
sendPort = aopenUDP(IP, 49009, 49063);
|
||||||
|
closeUDP(sendPort);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int testCONN()
|
||||||
|
{
|
||||||
|
// Initialize
|
||||||
|
char* drefs[] =
|
||||||
|
{
|
||||||
|
"sim/cockpit/switches/gear_handle_status"
|
||||||
|
};
|
||||||
|
float data[1];
|
||||||
|
int size = 1;
|
||||||
|
XPCSocket sock = openUDP(IP);
|
||||||
|
#if (__APPLE__ || __linux)
|
||||||
|
usleep(0);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Execution
|
||||||
|
setCONN(&sock, 49055);
|
||||||
|
int result = getDREF(sock, drefs[0], data, &size);
|
||||||
|
|
||||||
|
// Close
|
||||||
|
closeUDP(sock);
|
||||||
|
|
||||||
|
// Test
|
||||||
|
if (result < 0)// No data received
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
42
TestScripts/C Tests/WyptTests.h
Normal file
42
TestScripts/C Tests/WyptTests.h
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
//Copyright (c) 2013-2015 United States Government as represented by the Administrator of the
|
||||||
|
//National Aeronautics and Space Administration. All Rights Reserved.
|
||||||
|
#ifndef WYPTTESTS_H
|
||||||
|
#define WYPTTESTS_H
|
||||||
|
|
||||||
|
#include "Test.h"
|
||||||
|
#include "xplaneConnect.h"
|
||||||
|
|
||||||
|
int testWYPT()
|
||||||
|
{
|
||||||
|
// Setup
|
||||||
|
XPCSocket sock = openUDP(IP);
|
||||||
|
float points[] =
|
||||||
|
{
|
||||||
|
37.5245F, -122.06899F, 2500,
|
||||||
|
37.455397F, -122.050037F, 2500,
|
||||||
|
37.469567F, -122.051411F, 2500,
|
||||||
|
37.479376F, -122.060509F, 2300,
|
||||||
|
37.482237F, -122.076130F, 2100,
|
||||||
|
37.474881F, -122.087288F, 1900,
|
||||||
|
37.467660F, -122.079391F, 1700,
|
||||||
|
37.466298F, -122.090549F, 1500,
|
||||||
|
37.362562F, -122.039223F, 1000,
|
||||||
|
37.361448F, -122.034416F, 1000,
|
||||||
|
37.361994F, -122.026348F, 1000,
|
||||||
|
37.365541F, -122.022572F, 1000,
|
||||||
|
37.373727F, -122.024803F, 1000,
|
||||||
|
37.403869F, -122.041283F, 50,
|
||||||
|
37.418544F, -122.049222F, 6
|
||||||
|
};
|
||||||
|
|
||||||
|
// Test
|
||||||
|
sendWYPT(sock, XPC_WYPT_CLR, NULL, 0);
|
||||||
|
sendWYPT(sock, XPC_WYPT_ADD, points, 15);
|
||||||
|
// NOTE: Visually ensure waypoints are added in the sim
|
||||||
|
|
||||||
|
// Cleanup
|
||||||
|
closeUDP(sock);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -333,6 +333,33 @@ public class XPlaneConnectTest
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSendDREFs() throws IOException
|
||||||
|
{
|
||||||
|
String[] drefs =
|
||||||
|
{
|
||||||
|
"sim/cockpit/switches/gear_handle_status",
|
||||||
|
"sim/cockpit/autopilot/altitude"
|
||||||
|
};
|
||||||
|
try(XPlaneConnect xpc = new XPlaneConnect())
|
||||||
|
{
|
||||||
|
float[][] values = {{1}, {2000}};
|
||||||
|
xpc.sendDREFs(drefs, values);
|
||||||
|
|
||||||
|
float[][] result = xpc.getDREFs(drefs);
|
||||||
|
assertEquals(values[0][0], result[0][0], 1e-4);
|
||||||
|
assertEquals(values[1][0], result[1][0], 1e-4);
|
||||||
|
|
||||||
|
values[0][0] = 0;
|
||||||
|
values[1][0] = 4000;
|
||||||
|
xpc.sendDREFs(drefs, values);
|
||||||
|
|
||||||
|
result = xpc.getDREFs(drefs);
|
||||||
|
assertEquals(values[0][0], result[0][0], 1e-4);
|
||||||
|
assertEquals(values[1][0], result[1][0], 1e-4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test(expected = IllegalArgumentException.class)
|
@Test(expected = IllegalArgumentException.class)
|
||||||
public void testSendDREF_NullDREF() throws IOException
|
public void testSendDREF_NullDREF() throws IOException
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -117,6 +117,37 @@ class XPCTests(unittest.TestCase):
|
|||||||
value = 0
|
value = 0
|
||||||
do_test()
|
do_test()
|
||||||
|
|
||||||
|
def test_sendDREFs(self):
|
||||||
|
drefs = [\
|
||||||
|
"sim/cockpit/switches/gear_handle_status",\
|
||||||
|
"sim/cockpit/autopilot/altitude"]
|
||||||
|
values = None
|
||||||
|
def do_test():
|
||||||
|
# Setup
|
||||||
|
client = xpc.XPlaneConnect()
|
||||||
|
|
||||||
|
# Execute
|
||||||
|
client.sendDREFs(drefs, values)
|
||||||
|
result = client.getDREFs(drefs)
|
||||||
|
|
||||||
|
# Cleanup
|
||||||
|
client.close()
|
||||||
|
|
||||||
|
# Tests
|
||||||
|
self.assertEqual(2, len(result))
|
||||||
|
self.assertEqual(1, len(result[0]))
|
||||||
|
self.assertEqual(values[0], result[0][0])
|
||||||
|
self.assertEqual(1, len(result[1]))
|
||||||
|
self.assertEqual(values[1], result[1][0])
|
||||||
|
|
||||||
|
# Test 1
|
||||||
|
values = [1, 2000]
|
||||||
|
do_test()
|
||||||
|
|
||||||
|
# Test 2
|
||||||
|
values = [0, 4000]
|
||||||
|
do_test()
|
||||||
|
|
||||||
def test_sendDATA(self):
|
def test_sendDATA(self):
|
||||||
# Setup
|
# Setup
|
||||||
dref = "sim/aircraft/parts/acf_gear_deploy"
|
dref = "sim/aircraft/parts/acf_gear_deploy"
|
||||||
|
|||||||
@@ -12,10 +12,11 @@
|
|||||||
// As a result, these log messages may be the only indication of failure.
|
// As a result, these log messages may be the only indication of failure.
|
||||||
// 2: All errors. Any time something unexpected happens, log it.
|
// 2: All errors. Any time something unexpected happens, log it.
|
||||||
// 3: Significant actions. Any time something happens outside of normal
|
// 3: Significant actions. Any time something happens outside of normal
|
||||||
// command processing, log it.
|
// command processing, log it. Will also log when commands are received.
|
||||||
|
// 4: Detailed actions. Log aditional information as commands are processed.
|
||||||
// 5: Everything. Log nearly every single action the plugin takes. This may
|
// 5: Everything. Log nearly every single action the plugin takes. This may
|
||||||
// have a detrimental impact on X-Plane performance.
|
// have a detrimental impact on X-Plane performance.
|
||||||
#define LOG_VERBOSITY 2
|
#define LOG_VERBOSITY 3
|
||||||
|
|
||||||
namespace XPC
|
namespace XPC
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -402,18 +402,41 @@ namespace XPC
|
|||||||
|
|
||||||
void MessageHandlers::HandleDref(Message& msg)
|
void MessageHandlers::HandleDref(Message& msg)
|
||||||
{
|
{
|
||||||
const unsigned char* buffer = msg.GetBuffer();
|
#if LOG_VERBOSITY >= 3
|
||||||
unsigned char len = buffer[5];
|
Log::FormatLine("[DREF] Request to set DREF value received (Conn %i)", connection.id);
|
||||||
std::string dref = std::string((char*)buffer + 6, len);
|
|
||||||
|
|
||||||
unsigned char valueCount = buffer[6 + len];
|
|
||||||
float* values = (float*)(buffer + 7 + len);
|
|
||||||
|
|
||||||
#if LOG_VERBOSITY > 1
|
|
||||||
Log::FormatLine("[DREF] Request to set DREF value received (Conn %i): %s", connection.id, dref.c_str());
|
|
||||||
#endif
|
#endif
|
||||||
|
const unsigned char* buffer = msg.GetBuffer();
|
||||||
|
std::size_t size = msg.GetSize();
|
||||||
|
std::size_t pos = 5;
|
||||||
|
while (pos < size)
|
||||||
|
{
|
||||||
|
unsigned char len = buffer[pos++];
|
||||||
|
if (pos + len > size)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
std::string dref = std::string((char*)buffer + pos, len);
|
||||||
|
pos += len;
|
||||||
|
|
||||||
DataManager::Set(dref, values, valueCount);
|
unsigned char valueCount = buffer[pos++];
|
||||||
|
if (pos + 4 * valueCount > size)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
float* values = (float*)(buffer + pos);
|
||||||
|
pos += 4 * valueCount;
|
||||||
|
|
||||||
|
DataManager::Set(dref, values, valueCount);
|
||||||
|
#if LOG_VERBOSITY >= 4
|
||||||
|
Log::FormatLine("[DREF] Set %d values for %s", valueCount, dref.c_str());
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#if LOG_VERBOSITY >= 2
|
||||||
|
if (pos != size)
|
||||||
|
{
|
||||||
|
Log::WriteLine("[DREF] Error: Command did not terminate at the expected position.");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void MessageHandlers::HandleGetD(Message& msg)
|
void MessageHandlers::HandleGetD(Message& msg)
|
||||||
|
|||||||
Reference in New Issue
Block a user