Merge pull request #217 from sanderdatema/develop

Add support for sendCOMM method
This commit is contained in:
Jason Watkins
2020-06-27 12:33:37 -07:00
committed by GitHub
10 changed files with 156 additions and 0 deletions

View File

@@ -973,3 +973,40 @@ int sendVIEW(XPCSocket sock, VIEW_TYPE view)
/*****************************************************************************/
/**** End View functions ****/
/*****************************************************************************/
/*****************************************************************************/
/**** Comm functions ****/
/*****************************************************************************/
int sendCOMM(XPCSocket sock, const char* comm) {
// Setup command
// Max size is technically unlimited.
unsigned char buffer[65536] = "COMM";
int pos = 5;
int commLen = strnlen(comm, 256);
if (pos + commLen + 2 > 65536)
{
printError("sendCOMM", "About to overrun the send buffer!");
return -4;
}
if (commLen > 255)
{
printError("sendCOMM", "comm is too long. Must be less than 256 characters.");
return -1;
}
// Copy comm to buffer
buffer[pos++] = (unsigned char)commLen;
memcpy(buffer + pos, comm, commLen);
pos += commLen;
// Send command
if (sendUDP(sock, buffer, pos) < 0)
{
printError("setDREF", "Failed to send command");
return -3;
}
return 0;
}
/*****************************************************************************/
/**** End Comm functions ****/
/*****************************************************************************/

View File

@@ -303,6 +303,13 @@ int sendVIEW(XPCSocket sock, VIEW_TYPE view);
/// \returns 0 if successful, otherwise a negative value.
int sendWYPT(XPCSocket sock, WYPT_OP op, float points[], int count);
/// Sends commands.
///
/// \param sock The socket to use to send the command.
/// \param comm The command string.
/// \returns 0 if successful, otherwise a negative value.
int sendCOMM(XPCSocket sock, const char* comm);
#ifdef __cplusplus
}
#endif

View File

@@ -889,6 +889,42 @@ public class XPlaneConnect implements AutoCloseable
sendUDP(os.toByteArray());
}
/**
* Send a command to X-Plane.
*
* @param comm The name of the X-Plane command to send.
* @throws IOException If the command cannot be sent.
*/
public void sendCOMM(String comm) throws IOException
{
//Preconditions
if(comm == null || comm.length() == 0)
{
throw new IllegalArgumentException(("comm must be non-empty."));
}
ByteArrayOutputStream os = new ByteArrayOutputStream();
os.write("COMM".getBytes(StandardCharsets.UTF_8));
os.write(0xFF); //Placeholder for message length
//Convert comm to bytes.
byte[] commBytes = comm.getBytes(StandardCharsets.UTF_8);
if (commBytes.length == 0)
{
throw new IllegalArgumentException("COMM is an empty string!");
}
if (commBytes.length > 255)
{
throw new IllegalArgumentException("comm must be less than 255 bytes in UTF-8. Are you sure this is a valid comm?");
}
//Build and send message
os.write(commBytes.length);
os.write(commBytes);
sendUDP(os.toByteArray());
}
/**
* Sets the port on which the client will receive data from X-Plane.
*

View File

@@ -416,6 +416,27 @@ class XPlaneConnect(object):
buffer = struct.pack("<4sxBB" + str(len(points)) + "f", "WYPT", op, len(points), *points)
self.sendUDP(buffer)
def sendCOMM(self, comm):
'''Sets the specified datarefs to the specified values.
Args:
drefs: A list of names of the datarefs to set.
values: A list of scalar or vector values to set.
'''
if comm == None:
raise ValueError("comm must be non-empty.")
buffer = struct.pack("<4sx", "COMM")
if len(comm) == 0 or len(comm) > 255:
raise ValueError("comm must be a non-empty string less than 256 characters.")
# Pack message
fmt = "<B{0:d}s".format(len(comm))
buffer += struct.pack(fmt, len(comm), comm)
# Send
self.sendUDP(buffer)
class ViewType(object):
Forwards = 73
Down = 74

View File

@@ -19,6 +19,7 @@
#include "XPLMDataAccess.h"
#include "XPLMGraphics.h"
#include "XPLMUtilities.h"
#include <algorithm>
#include <cmath>
@@ -791,6 +792,21 @@ namespace XPC
Set(DREF_FlapActual, value);
}
void DataManager::Execute(const std::string& comm)
{
Log::FormatLine(LOG_INFO, "DMAN", "Executing command (value:%s)", comm.c_str());
XPLMCommandRef xcref = XPLMFindCommand(comm.c_str());
if (!xcref)
{
// COMM does not exist
Log::FormatLine(LOG_ERROR, "DMAN", "ERROR: invalid COMM %s", comm.c_str());
return;
}
XPLMCommandOnce(xcref);
}
float DataManager::GetDefaultValue()
{
return -998.0F;

View File

@@ -410,6 +410,11 @@ namespace XPC
/// \param value The flaps settings. Should be between 0.0 (no flaps) and 1.0 (full flaps).
static void SetFlaps(float value);
/// Executes a command
///
/// \param comm The name of the command to execute.
static void Execute(const std::string& comm);
/// Gets a default value that indicates that a dataref should not be changed.
static float GetDefaultValue();

View File

@@ -176,6 +176,11 @@ namespace XPC
ss << "Type:" << *((unsigned long*)(buffer + 5));
Log::WriteLine(LOG_DEBUG, "DBUG", ss.str());
}
else if (head == "COMM")
{
ss << "Type:" << *((unsigned long*)(buffer + 5));
Log::WriteLine(LOG_DEBUG, "DBUG", ss.str());
}
else
{
ss << " UNKNOWN HEADER ";

View File

@@ -70,6 +70,7 @@ namespace XPC
handlers.insert(std::make_pair("VIEW", MessageHandlers::HandleView));
handlers.insert(std::make_pair("GETC", MessageHandlers::HandleGetC));
handlers.insert(std::make_pair("GETP", MessageHandlers::HandleGetP));
handlers.insert(std::make_pair("COMM", MessageHandlers::HandleComm));
handlers.insert(std::make_pair("GETT", MessageHandlers::HandleGetT));
// X-Plane data messages
handlers.insert(std::make_pair("DSEL", MessageHandlers::HandleXPlaneData));
@@ -916,6 +917,31 @@ namespace XPC
}
}
void MessageHandlers::HandleComm(const Message& msg)
{
Log::FormatLine(LOG_TRACE, "COMM", "Request to execute COMM command received (Conn %i)", connection.id);
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 comm = std::string((char*)buffer + pos, len);
pos += len;
DataManager::Execute(comm);
Log::FormatLine(LOG_DEBUG, "COMM", "Execute command %s", comm.c_str());
}
if (pos != size)
{
Log::WriteLine(LOG_ERROR, "COMM", "ERROR: Command did not terminate at the expected position.");
}
}
void MessageHandlers::HandleWypt(const Message& msg)
{
// Update Log

View File

@@ -77,6 +77,7 @@ namespace XPC
static void HandleText(const Message& msg);
static void HandleWypt(const Message& msg);
static void HandleView(const Message& msg);
static void HandleComm(const Message& msg);
static void HandleXPlaneData(const Message& msg);
static void HandleUnknown(const Message& msg);

View File

@@ -221,6 +221,7 @@
"APL=1",
"IBM=0",
"LIN=0",
XPLM200,
);
GCC_SYMBOLS_PRIVATE_EXTERN = YES;
GCC_VERSION = "";
@@ -274,6 +275,7 @@
"APL=1",
"IBM=0",
"LIN=0",
XPLM200,
);
GCC_SYMBOLS_PRIVATE_EXTERN = YES;
GCC_VERSION = "";