@@ -48,9 +48,6 @@
|
||||
#include <sys/types.h>
|
||||
#include <time.h>
|
||||
|
||||
|
||||
|
||||
|
||||
void printError(char *functionName, char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
@@ -694,3 +691,31 @@ int sendWYPT(XPCSocket sock, WYPT_OP op, float points[], int count)
|
||||
/*****************************************************************************/
|
||||
/**** End Drawing functions ****/
|
||||
/*****************************************************************************/
|
||||
|
||||
/*****************************************************************************/
|
||||
/**** View functions ****/
|
||||
/*****************************************************************************/
|
||||
int sendVIEW(XPCSocket sock, VIEW_TYPE view)
|
||||
{
|
||||
// Validate Input
|
||||
if (view < XPC_VIEW_FORWARDS || view > XPC_VIEW_FULLSCREENNOHUD)
|
||||
{
|
||||
printError("sendVIEW", "Unrecognized view");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Setup Command
|
||||
char buffer[9] = "VIEW";
|
||||
*((int*)(buffer + 5)) = view;
|
||||
|
||||
// Send Command
|
||||
if (sendUDP(sock, buffer, 9) < 0)
|
||||
{
|
||||
printError("sendVIEW", "Failed to send command");
|
||||
return -2;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/*****************************************************************************/
|
||||
/**** End View functions ****/
|
||||
/*****************************************************************************/
|
||||
@@ -61,6 +61,23 @@ typedef enum
|
||||
XPC_WYPT_DEL = 2,
|
||||
XPC_WYPT_CLR = 3
|
||||
} WYPT_OP;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
XPC_VIEW_FORWARDS = 73,
|
||||
XPC_VIEW_DOWN,
|
||||
XPC_VIEW_LEFT,
|
||||
XPC_VIEW_RIGHT,
|
||||
XPC_VIEW_BACK,
|
||||
XPC_VIEW_TOWER,
|
||||
XPC_VIEW_RUNWAY,
|
||||
XPC_VIEW_CHASE,
|
||||
XPC_VIEW_FOLLOW,
|
||||
XPC_VIEW_FOLLOWWITHPANEL,
|
||||
XPC_VIEW_SPOT,
|
||||
XPC_VIEW_FULLSCREENWITHHUD,
|
||||
XPC_VIEW_FULLSCREENNOHUD,
|
||||
} VIEW_TYPE;
|
||||
|
||||
// Low Level UDP Functions
|
||||
|
||||
@@ -214,6 +231,13 @@ int sendCTRL(XPCSocket sock, float values[], int size, char ac);
|
||||
/// \returns 0 if successful, otherwise a negative value.
|
||||
int sendTEXT(XPCSocket sock, char* msg, int x, int y);
|
||||
|
||||
/// Sets the camera view in X-Plane.
|
||||
///
|
||||
/// \param sock The socket to use to send the command.
|
||||
/// \param view The view to use.
|
||||
/// \returns 0 if successful, otherwise a negative value.
|
||||
int sendVIEW(XPCSocket sock, VIEW_TYPE view);
|
||||
|
||||
/// Adds, removes, or clears a set of waypoints. If the command is clear, the points are ignored
|
||||
/// and all points are removed.
|
||||
///
|
||||
|
||||
60
Java/src/ViewType.java
Normal file
60
Java/src/ViewType.java
Normal file
@@ -0,0 +1,60 @@
|
||||
//NOTICES:
|
||||
// Copyright <20> 2013-2015 United States Government as represented by the Administrator of the
|
||||
// National Aeronautics and Space Administration. All Rights Reserved.
|
||||
//
|
||||
// DISCLAIMERS
|
||||
// No Warranty: THE SUBJECT SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY OF ANY KIND,
|
||||
// EITHER EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, ANY WARRANTY THAT THE
|
||||
// SUBJECT SOFTWARE WILL CONFORM TO SPECIFICATIONS, ANY IMPLIED WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE, OR FREEDOM FROM INFRINGEMENT, ANY WARRANTY THAT THE SUBJECT
|
||||
// SOFTWARE WILL BE ERROR FREE, OR ANY WARRANTY THAT DOCUMENTATION, IF PROVIDED, WILL CONFORM TO
|
||||
// THE SUBJECT SOFTWARE. THIS AGREEMENT DOES NOT, IN ANY MANNER, CONSTITUTE AN ENDORSEMENT BY
|
||||
// GOVERNMENT AGENCY OR ANY PRIOR RECIPIENT OF ANY RESULTS, RESULTING DESIGNS, HARDWARE,
|
||||
// SOFTWARE PRODUCTS OR ANY OTHER APPLICATIONS RESULTING FROM USE OF THE SUBJECT SOFTWARE.
|
||||
// FURTHER, GOVERNMENT AGENCY DISCLAIMS ALL WARRANTIES AND LIABILITIES REGARDING THIRD-PARTY
|
||||
// SOFTWARE, IF PRESENT IN THE ORIGINAL SOFTWARE, AND DISTRIBUTES IT "AS IS."
|
||||
//
|
||||
// Waiver and Indemnity: RECIPIENT AGREES TO WAIVE ANY AND ALL CLAIMS AGAINST THE UNITED STATES
|
||||
// GOVERNMENT, ITS CONTRACTORS AND SUBCONTRACTORS, AS WELL AS ANY PRIOR RECIPIENT. IF
|
||||
// RECIPIENT'S USE OF THE SUBJECT SOFTWARE RESULTS IN ANY LIABILITIES, DEMANDS, DAMAGES,
|
||||
// EXPENSES OR LOSSES ARISING FROM SUCH USE, INCLUDING ANY DAMAGES FROM PRODUCTS BASED ON, OR
|
||||
// RESULTING FROM, RECIPIENT'S USE OF THE SUBJECT SOFTWARE, RECIPIENT SHALL INDEMNIFY AND HOLD
|
||||
// HARMLESS THE UNITED STATES GOVERNMENT, ITS CONTRACTORS AND SUBCONTRACTORS, AS WELL AS ANY
|
||||
// PRIOR RECIPIENT, TO THE EXTENT PERMITTED BY LAW. RECIPIENT'S SOLE REMEDY FOR ANY SUCH MATTER
|
||||
// SHALL BE THE IMMEDIATE, UNILATERAL TERMINATION OF THIS AGREEMENT.
|
||||
package gov.nasa.xpc;
|
||||
|
||||
/**
|
||||
* Represents a camera view in X-Plane
|
||||
*
|
||||
* @author Jason Watkins
|
||||
* @version 1.1
|
||||
* @since 2015-05-08
|
||||
*/
|
||||
public enum ViewType
|
||||
{
|
||||
Forwards(73),
|
||||
Down(74),
|
||||
Left(75),
|
||||
Right(76),
|
||||
Back(77),
|
||||
Tower(78),
|
||||
Runway(79),
|
||||
Chase(80),
|
||||
Follow(81),
|
||||
FollowWithPanel(82),
|
||||
Spot(83),
|
||||
FullscreenWithHud(84),
|
||||
FullscreenNoHud(85);
|
||||
|
||||
private final int value;
|
||||
private ViewType(int value)
|
||||
{
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public int getValue()
|
||||
{
|
||||
return value;
|
||||
}
|
||||
}
|
||||
@@ -720,6 +720,26 @@ public class XPlaneConnect implements AutoCloseable
|
||||
sendUDP(os.toByteArray());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the camera view in X-Plane.
|
||||
*
|
||||
* @param view The view to use.
|
||||
* @throws IOException If the command cannot be sent.
|
||||
*/
|
||||
public void sendVIEW(ViewType view) throws IOException
|
||||
{
|
||||
ByteBuffer bb = ByteBuffer.allocate(4);
|
||||
bb.order(ByteOrder.LITTLE_ENDIAN);
|
||||
bb.putInt(view.getValue());
|
||||
|
||||
//Build and send message
|
||||
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
||||
os.write("VIEW".getBytes(StandardCharsets.UTF_8));
|
||||
os.write(0xFF); //Placeholder for message length
|
||||
os.write(bb.array());
|
||||
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.
|
||||
|
||||
Binary file not shown.
35
MATLAB/+XPlaneConnect/sendVIEW.m
Normal file
35
MATLAB/+XPlaneConnect/sendVIEW.m
Normal file
@@ -0,0 +1,35 @@
|
||||
function sendVIEW(view, socket)
|
||||
% sendVIEW Sets the camera
|
||||
%
|
||||
%Inputs
|
||||
% view: The view to use.
|
||||
% socket (optional): The client to use when sending the command.
|
||||
%
|
||||
%Use
|
||||
% 1. import XPlaneConnect.*;
|
||||
% 2. sendView(Forwards);
|
||||
%
|
||||
% 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), '[pauseSim] ERROR: Multiple clients open. You must specify which client to use.');
|
||||
if isempty(clients)
|
||||
socket = openUDP();
|
||||
else
|
||||
socket = clients(1);
|
||||
end
|
||||
end
|
||||
|
||||
%% Validate input
|
||||
|
||||
|
||||
%% Send command
|
||||
socket.sendVIEW(view)
|
||||
|
||||
end
|
||||
|
||||
@@ -326,6 +326,23 @@ class XPlaneConnect(object):
|
||||
buffer = struct.pack("<4sxiiB" + str(msgLen) + "s", "TEXT", x, y, msgLen, msg)
|
||||
self.sendUDP(buffer)
|
||||
|
||||
def sendVIEW(self, view):
|
||||
'''Sets the camera view in X-Plane
|
||||
|
||||
Args:
|
||||
view: The view to use. The ViewType class provides named constants
|
||||
for known views.
|
||||
'''
|
||||
# Preconditions
|
||||
if view < ViewType.Forwards or view > ViewType.FullscreenNoHud:
|
||||
raise ValueError("Unknown view command.")
|
||||
|
||||
# Pack buffer
|
||||
buffer = struct.pack("<4sxi", "VIEW", view)
|
||||
|
||||
# Send message
|
||||
self.sendUDP(buffer)
|
||||
|
||||
def sendWYPT(self, op, points):
|
||||
'''Adds, removes, or clears waypoints. Waypoints are three dimensional points on or
|
||||
above the Earth's surface that are represented visually in the simulator. Each
|
||||
@@ -350,3 +367,18 @@ class XPlaneConnect(object):
|
||||
else:
|
||||
buffer = struct.pack("<4sxBB" + str(len(points)) + "f", "WYPT", op, len(points), *points)
|
||||
self.sendUDP(buffer)
|
||||
|
||||
class ViewType(object):
|
||||
Forwards = 73
|
||||
Down = 74
|
||||
Left = 75
|
||||
Right = 76
|
||||
Back = 77
|
||||
Tower = 78
|
||||
Runway = 79
|
||||
Chase = 80
|
||||
Follow = 81
|
||||
FollowWithPanel = 82
|
||||
Spot = 83
|
||||
FullscreenWithHud = 84
|
||||
FullscreenNoHud = 85
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
<ClInclude Include="..\C Tests\Test.h" />
|
||||
<ClInclude Include="..\C Tests\TextTests.h" />
|
||||
<ClInclude Include="..\C Tests\UDPTests.h" />
|
||||
<ClInclude Include="..\C Tests\ViewTests.h" />
|
||||
<ClInclude Include="..\C Tests\WyptTests.h" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
|
||||
73
TestScripts/C Tests/ViewTests.h
Normal file
73
TestScripts/C Tests/ViewTests.h
Normal file
@@ -0,0 +1,73 @@
|
||||
//Copyright (c) 2013-2015 United States Government as represented by the Administrator of the
|
||||
//National Aeronautics and Space Administration. All Rights Reserved.
|
||||
#ifndef VIEWTESTS_H
|
||||
#define VIEWTESTS_H
|
||||
|
||||
#include "Test.h"
|
||||
#include "xplaneConnect.h"
|
||||
|
||||
typedef enum
|
||||
{
|
||||
XPC_VDREF_FORWARDS = 1000,
|
||||
XPC_VDREF_DOWN4 = 1001,
|
||||
XPC_VDREF_DOWN8 = 1002,
|
||||
XPC_VDREF_LEFT45 = 1004,
|
||||
XPC_VDREF_RIGHT45 = 1005,
|
||||
XPC_VDREF_LEFT90 = 1006,
|
||||
XPC_VDREF_RIGHT90 = 1007,
|
||||
XPC_VDREF_LEFT135 = 1008,
|
||||
XPC_VDREF_RIGHT135 = 1009,
|
||||
XPC_VDREF_BACKWARD = 1010,
|
||||
XPC_VDREF_LEFTUP = 1011,
|
||||
XPC_VDREF_RIGHTUP = 1012,
|
||||
XPC_VDREF_AIRPORTBEACONTOWER = 1014,
|
||||
XPC_VDREF_ONRUNWAY = 1015,
|
||||
XPC_VDREF_CHASE = 1017,
|
||||
XPC_VDREF_FOLLOW = 1018,
|
||||
XPC_VDREF_FOLLOWWITHPANEL = 1019,
|
||||
XPC_VDREF_SPOT = 1020,
|
||||
XPC_VDREF_SPOTMOVING = 1021,
|
||||
XPC_VDREF_FULLSCREENWITHHUD = 1023,
|
||||
XPC_VDREF_FULLSCREENNOHUD = 1024,
|
||||
XPC_VDREF_STRAIGHTDOWN = 1025,
|
||||
XPC_VDREF_3DCOCKPIT = 1026
|
||||
} VIEW_DREF;
|
||||
|
||||
int doViewTest(VIEW_TYPE viewCommand, VIEW_DREF viewResult)
|
||||
{
|
||||
// Setup
|
||||
char* dref = "sim/graphics/view/view_type";
|
||||
float value;
|
||||
int size = 1;
|
||||
|
||||
// Execute command
|
||||
XPCSocket sock = openUDP(IP);
|
||||
int result = sendVIEW(sock, viewCommand);
|
||||
if (result >= 0)
|
||||
{
|
||||
result = getDREF(sock, dref, &value, &size);
|
||||
}
|
||||
closeUDP(sock);
|
||||
if (result < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((int)value != viewResult)
|
||||
{
|
||||
return -2;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int testView()
|
||||
{
|
||||
int result = doViewTest(XPC_VIEW_FORWARDS, XPC_VDREF_FORWARDS);
|
||||
if (result < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return doViewTest(XPC_VIEW_CHASE, XPC_VDREF_CHASE);
|
||||
}
|
||||
#endif
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "PosiTests.h"
|
||||
#include "DataTests.h"
|
||||
#include "TextTests.h"
|
||||
#include "ViewTests.h"
|
||||
#include "WyptTests.h"
|
||||
|
||||
int main(int argc, const char * argv[])
|
||||
@@ -48,10 +49,14 @@ int main(int argc, const char * argv[])
|
||||
runTest(testTEXT, "TEXT");
|
||||
// Waypoints
|
||||
runTest(testWYPT, "WYPT");
|
||||
// View
|
||||
runTest(testView, "VIEW");
|
||||
// setConn
|
||||
runTest(testCONN, "CONN");
|
||||
|
||||
printf( "----------------\nTest Summary\n\tFailed: %i\n\tPassed: %i\n", testFailed, testPassed );
|
||||
printf("Press any key to exit.");
|
||||
getchar();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package gov.nasa.xpc.test;
|
||||
|
||||
import gov.nasa.xpc.ViewType;
|
||||
import gov.nasa.xpc.WaypointOp;
|
||||
import gov.nasa.xpc.XPlaneConnect;
|
||||
|
||||
@@ -677,4 +678,24 @@ public class XPlaneConnectTest
|
||||
fail();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSendView() throws IOException
|
||||
{
|
||||
String dref = "sim/graphics/view/view_type";
|
||||
float fwd = 1000;
|
||||
float chase = 1017;
|
||||
|
||||
try(XPlaneConnect xpc = new XPlaneConnect())
|
||||
{
|
||||
xpc.sendVIEW(ViewType.Forwards);
|
||||
float result = xpc.getDREF(dref)[0];
|
||||
assertEquals(fwd, result, 1e-4);
|
||||
|
||||
xpc.sendVIEW(ViewType.Chase);
|
||||
result = xpc.getDREF(dref)[0];
|
||||
assertEquals(chase, result, 1e-4);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
26
TestScripts/MATLAB Tests/sendVIEWTest.m
Normal file
26
TestScripts/MATLAB Tests/sendVIEWTest.m
Normal file
@@ -0,0 +1,26 @@
|
||||
function sendVIEWTest()
|
||||
%% Setup
|
||||
addpath('../../MATLAB')
|
||||
import XPlaneConnect.*
|
||||
|
||||
if ~exist('gov.nasa.xpc.ViewType', 'class')
|
||||
[folder, ~, ~] = fileparts(which('XPlaneConnect.openUDP'));
|
||||
javaaddpath(fullfile(folder, 'XPlaneConnect.jar'));
|
||||
end
|
||||
|
||||
dref = 'sim/graphics/view/view_type';
|
||||
fwd = 1000;
|
||||
chase = 1017;
|
||||
|
||||
%% Excecute
|
||||
sendVIEW(gov.nasa.xpc.ViewType.Forwards);
|
||||
result = getDREFs(dref);
|
||||
assert(isequal(result, fwd))
|
||||
|
||||
sendVIEW(gov.nasa.xpc.ViewType.Chase);
|
||||
result = getDREFs(dref);
|
||||
assert(isequal(result, chase))
|
||||
|
||||
|
||||
end
|
||||
|
||||
@@ -18,6 +18,7 @@ theTests = {{@openCloseTest, 'Open/Close Test', 0},...
|
||||
{@CTRLTest,'CTRL Test', 0},...
|
||||
{@POSITest,'POSI Test', 0},...
|
||||
{@sendWYPTTest,'WYPT Test', 0},...
|
||||
{@sendVIEWTest,'VIEW Test', 0},...
|
||||
{@pauseTest,'Pause Test', 0},...
|
||||
{@setConnTest, 'setConn Test', 0}};
|
||||
|
||||
|
||||
@@ -319,6 +319,22 @@ class XPCTests(unittest.TestCase):
|
||||
# Cleanup
|
||||
client.close()
|
||||
|
||||
def test_sendView(self):
|
||||
# Setup
|
||||
dref = "sim/graphics/view/view_type"
|
||||
fwd = 1000
|
||||
chase = 1017
|
||||
|
||||
#Execution
|
||||
with xpc.XPlaneConnect() as client:
|
||||
client.sendVIEW(xpc.ViewType.Forwards)
|
||||
result = client.getDREF(dref)
|
||||
self.assertAlmostEqual(fwd, result[0], 1e-4)
|
||||
client.sendVIEW(xpc.ViewType.Chase)
|
||||
result = client.getDREF(dref)
|
||||
self.assertAlmostEqual(chase, result[0], 1e-4)
|
||||
|
||||
|
||||
def test_sendWYPT(self):
|
||||
# Setup
|
||||
client = xpc.XPlaneConnect()
|
||||
|
||||
@@ -1,10 +1,26 @@
|
||||
//Copyright (c) 2013-2015 United States Government as represented by the Administrator of the
|
||||
//National Aeronautics and Space Administration. All Rights Reserved.
|
||||
//
|
||||
//X-Plane API
|
||||
//Copyright(c) 2008, Sandy Barbour and Ben Supnik All rights reserved.
|
||||
//Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
|
||||
//associated documentation files(the "Software"), to deal in the Software without restriction,
|
||||
//including without limitation the rights to use, copy, modify, merge, publish, distribute,
|
||||
//sublicense, and / or sell copies of the Software, and to permit persons to whom the Software is
|
||||
//furnished to do so, subject to the following conditions :
|
||||
// * Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
// * Neither the names of the authors nor that of X - Plane or Laminar Research
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission from the authors or
|
||||
// Laminar Research, respectively.
|
||||
#include "MessageHandlers.h"
|
||||
#include "DataManager.h"
|
||||
#include "Drawing.h"
|
||||
#include "Log.h"
|
||||
|
||||
#include "XPLMUtilities.h"
|
||||
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
|
||||
@@ -36,8 +52,7 @@ namespace XPC
|
||||
handlers.insert(std::make_pair("SIMU", MessageHandlers::HandleSimu));
|
||||
handlers.insert(std::make_pair("TEXT", MessageHandlers::HandleText));
|
||||
handlers.insert(std::make_pair("WYPT", MessageHandlers::HandleWypt));
|
||||
// Not implemented messages
|
||||
handlers.insert(std::make_pair("VIEW", MessageHandlers::HandleUnknown));
|
||||
handlers.insert(std::make_pair("VIEW", MessageHandlers::HandleView));
|
||||
// X-Plane data messages
|
||||
handlers.insert(std::make_pair("DSEL", MessageHandlers::HandleXPlaneData));
|
||||
handlers.insert(std::make_pair("USEL", MessageHandlers::HandleXPlaneData));
|
||||
@@ -623,6 +638,26 @@ namespace XPC
|
||||
}
|
||||
}
|
||||
|
||||
void MessageHandlers::HandleView(Message& msg)
|
||||
{
|
||||
// Update Log
|
||||
#if LOG_VERBOSITY > 0
|
||||
Log::FormatLine("[VIEW] Message Received (Conn %i)", connection.id);
|
||||
#endif
|
||||
|
||||
const std::size_t size = msg.GetSize();
|
||||
if (size != 9)
|
||||
{
|
||||
#if LOG_VERBOSITY > 1
|
||||
Log::FormatLine("[VIEW] Error: Unexpected length. Message was %d bytes, expected 9.", size);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
const unsigned char* buffer = msg.GetBuffer();
|
||||
int type = *((int*)(buffer + 5));
|
||||
XPLMCommandKeyStroke(type);
|
||||
}
|
||||
|
||||
void MessageHandlers::HandleWypt(Message& msg)
|
||||
{
|
||||
// Update Log
|
||||
|
||||
@@ -46,6 +46,7 @@ namespace XPC
|
||||
static void HandleSimu(Message& msg);
|
||||
static void HandleText(Message& msg);
|
||||
static void HandleWypt(Message& msg);
|
||||
static void HandleView(Message& msg);
|
||||
static void HandleXPlaneData(Message& msg);
|
||||
static void HandleUnknown(Message& msg);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user