diff --git a/C/src/xplaneConnect.c b/C/src/xplaneConnect.c index e4e633e..9969a57 100755 --- a/C/src/xplaneConnect.c +++ b/C/src/xplaneConnect.c @@ -521,6 +521,38 @@ int getDREFs(XPCSocket sock, const char* drefs[], float* values[], unsigned char /*****************************************************************************/ /**** POSI functions ****/ /*****************************************************************************/ +int getPOSI(XPCSocket sock, float values[7], char ac) +{ + // Setup send command + unsigned char buffer[6] = "GETP"; + buffer[5] = ac; + + // Send command + if (sendUDP(sock, buffer, 6) < 0) + { + printError("getPOSI", "Failed to send command."); + return -1; + } + + // Get response + unsigned char readBuffer[34]; + int readResult = readUDP(sock, readBuffer, 34); + if (readResult < 0) + { + printError("getPOSI", "Failed to read response."); + return -2; + } + if (readResult != 34) + { + printError("getPOSI", "Unexpected response length."); + return -3; + } + + // Copy response into values + memcpy(values, readBuffer + 6, 7 * sizeof(float)); + return 0; +} + int sendPOSI(XPCSocket sock, float values[], int size, char ac) { // Validate input @@ -565,6 +597,41 @@ int sendPOSI(XPCSocket sock, float values[], int size, char ac) /*****************************************************************************/ /**** CTRL functions ****/ /*****************************************************************************/ +int getCTRL(XPCSocket sock, float values[7], char ac) +{ + // Setup send command + unsigned char buffer[6] = "GETC"; + buffer[5] = ac; + + // Send command + if (sendUDP(sock, buffer, 6) < 0) + { + printError("getCTRL", "Failed to send command."); + return -1; + } + + // Get response + unsigned char readBuffer[31]; + int readResult = readUDP(sock, readBuffer, 31); + if (readResult < 0) + { + printError("getCTRL", "Failed to read response."); + return -2; + } + if (readResult != 31) + { + printError("getCTRL", "Unexpected response length."); + return -3; + } + + // Copy response into values + memcpy(values, readBuffer + 5, 4 * sizeof(float)); + values[4] = readBuffer[21]; + values[5] = *((float*)(readBuffer + 22)); + values[6] = *((float*)(readBuffer + 27)); + return 0; +} + int sendCTRL(XPCSocket sock, float values[], int size, char ac) { // Validate input diff --git a/C/src/xplaneConnect.h b/C/src/xplaneConnect.h index 3827a68..161178a 100644 --- a/C/src/xplaneConnect.h +++ b/C/src/xplaneConnect.h @@ -196,6 +196,14 @@ int getDREFs(XPCSocket sock, const char* drefs[], float* values[], unsigned char // Position +/// Gets the position and orientation of the specified aircraft. +/// +/// \param sock The socket used to send the command and receive the response. +/// \param values An array to store the position information returned by the +/// plugin. The format of values is [Lat, Lon, Alt, Pitch, Roll, Yaw, Gear] +/// \returns 0 if successful, otherwise a negative value. +int getPOSI(XPCSocket sock, float values[7], char ac); + /// Sets the position and orientation of the specified aircraft. /// /// \param sock The socket to use to send the command. @@ -209,6 +217,16 @@ int sendPOSI(XPCSocket sock, float values[], int size, char ac); // Controls +/// Gets the control surface information for the specified aircraft. +/// +/// \param sock The socket used to send the command and receive the response. +/// \param values An array to store the position information returned by the +/// plugin. The format of values is [Elevator, Aileron, Rudder, +/// Throttle, Gear, Flaps, Speed Brakes] +/// \param ac The aircraft to set the control surfaces of. 0 is the main/player aircraft. +/// \returns 0 if successful, otherwise a negative value. +int getCTRL(XPCSocket sock, float values[7], char ac); + /// Sets the control surfaces of the specified aircraft. /// /// \param sock The socket to use to send the command. diff --git a/Java/src/XPlaneConnect.java b/Java/src/XPlaneConnect.java index ba545d5..ad3307e 100644 --- a/Java/src/XPlaneConnect.java +++ b/Java/src/XPlaneConnect.java @@ -398,6 +398,47 @@ public class XPlaneConnect implements AutoCloseable sendUDP(os.toByteArray()); } + /** + * Gets the control surface information for the specified airplane. + * + * @param ac The aircraft to get control surface information for. + * @return An array containing control surface data in the same format as {@code sendCTRL}. + * @throws IOException If the command cannot be sent or a response cannot be read. + */ + public float[] getCTRL(int ac) throws IOException + { + // Send request + ByteArrayOutputStream os = new ByteArrayOutputStream(); + os.write("GETC".getBytes(StandardCharsets.UTF_8)); + os.write(0xFF); //Placeholder for message length + os.write(ac); + sendUDP(os.toByteArray()); + + // Read response + byte[] data = readUDP(); + if(data.length == 0) + { + throw new IOException("No response received."); + } + if(data.length < 31) + { + throw new IOException("Response too short"); + } + + // Parse response + float[] result = new float[7]; + ByteBuffer bb = ByteBuffer.wrap(data); + bb.order(ByteOrder.LITTLE_ENDIAN); + result[0] = bb.getFloat(5); + result[1] = bb.getFloat(9); + result[2] = bb.getFloat(13); + result[3] = bb.getFloat(17); + result[4] = bb.get(21); + result[5] = bb.getFloat(22); + result[6] = bb.getFloat(27); + return result; + } + /** * Sends command to X-Plane setting control surfaces on the player ac. * @@ -409,6 +450,7 @@ public class XPlaneConnect implements AutoCloseable *
  • Throttle [-1, 1]
  • *
  • Gear (0=up, 1=down)
  • *
  • Flaps [0, 1]
  • + *
  • Speedbrakes [-0.5, 1.5]
  • * *

    * If @{code ctrl} is less than 6 elements long, The missing elements will not be changed. To @@ -433,6 +475,7 @@ public class XPlaneConnect implements AutoCloseable *

  • Throttle [-1, 1]
  • *
  • Gear (0=up, 1=down)
  • *
  • Flaps [0, 1]
  • + *
  • Speedbrakes [-0.5, 1.5]
  • * *

    * If @{code ctrl} is less than 6 elements long, The missing elements will not be changed. To @@ -492,6 +535,44 @@ public class XPlaneConnect implements AutoCloseable sendUDP(os.toByteArray()); } + /** + * Gets position information for the specified airplane. + * + * @param ac The aircraft to get position information for. + * @return An array containing control surface data in the same format as {@code sendPOSI}. + * @throws IOException If the command cannot be sent or a response cannot be read. + */ + public float[] getPOSI(int ac) throws IOException + { + // Send request + ByteArrayOutputStream os = new ByteArrayOutputStream(); + os.write("GETP".getBytes(StandardCharsets.UTF_8)); + os.write(0xFF); //Placeholder for message length + os.write(ac); + sendUDP(os.toByteArray()); + + // Read response + byte[] data = readUDP(); + if(data.length == 0) + { + throw new IOException("No response received."); + } + if(data.length < 34) + { + throw new IOException("Response too short"); + } + + // Parse response + float[] result = new float[7]; + ByteBuffer bb = ByteBuffer.wrap(data); + bb.order(ByteOrder.LITTLE_ENDIAN); + for(int i = 0; i < 7; ++i) + { + result[i] = bb.getFloat(6 + 4 * i); + } + return result; + } + /** * Sets the position of the player ac. * diff --git a/MATLAB/+XPlaneConnect/XPlaneConnect.jar b/MATLAB/+XPlaneConnect/XPlaneConnect.jar index c779711..eba5283 100644 Binary files a/MATLAB/+XPlaneConnect/XPlaneConnect.jar and b/MATLAB/+XPlaneConnect/XPlaneConnect.jar differ diff --git a/MATLAB/+XPlaneConnect/getCTRL.m b/MATLAB/+XPlaneConnect/getCTRL.m new file mode 100644 index 0000000..820afca --- /dev/null +++ b/MATLAB/+XPlaneConnect/getCTRL.m @@ -0,0 +1,29 @@ +function ctrl = getCTRL(ac, socket) +% getCTRL Gets control surface information for the specified aircraft +% +% Inputs +% ac: The aircraft number to get control surface data for. +% Outputs +% posi: An array of values matching the the format used by sendCTRL + + +import XPlaneConnect.* + +%% Get client +global clients; +if ~exist('socket', 'var') + assert(isequal(length(clients) < 2, 1), '[getCTRL] ERROR: Multiple clients open. You must specify which client to use.'); + if isempty(clients) + socket = openUDP(); + else + socket = clients(1); + end +end + +%% Validate input +ac = int32(ac); + +%% Send command +ctrl = socket.getCTRL(ac); + +end \ No newline at end of file diff --git a/MATLAB/+XPlaneConnect/getPOSI.m b/MATLAB/+XPlaneConnect/getPOSI.m new file mode 100644 index 0000000..35b8d5a --- /dev/null +++ b/MATLAB/+XPlaneConnect/getPOSI.m @@ -0,0 +1,29 @@ +function posi = getPOSI(ac, socket) +% getPOSI Gets position information for the specified aircraft +% +% Inputs +% ac: The aircraft number to get position data for. +% Outputs +% posi: An array of values matching the the format used by sendPOSI + + +import XPlaneConnect.* + +%% Get client +global clients; +if ~exist('socket', 'var') + assert(isequal(length(clients) < 2, 1), '[getPOSI] ERROR: Multiple clients open. You must specify which client to use.'); + if isempty(clients) + socket = openUDP(); + else + socket = clients(1); + end +end + +%% Validate input +ac = int32(ac); + +%% Send command +posi = socket.getPOSI(ac); + +end \ No newline at end of file diff --git a/Python/src/xpc.py b/Python/src/xpc.py index c19bbdb..e2b5c5e 100644 --- a/Python/src/xpc.py +++ b/Python/src/xpc.py @@ -143,7 +143,29 @@ class XPlaneConnect(object): buffer += struct.pack("= 0) + { + result = getCTRL(sock, actual, ac); + } + closeUDP(sock); + if (result < 0) + { + return -1; + } + + // Test values + for (int i = 0; i < 7; ++i) + { + if (fabs(expected[i] - actual[i]) > 1e-4) + { + return -10 - i; + } + } + return 0; +} + int basicCTRLTest(char** drefs, int ac) { // Set control surfaces to known state. @@ -146,4 +173,16 @@ int testCTRL_Speedbrakes() } return 0; } + +int testGETC() +{ + float CTRL[7] = { 0.0F, 0.0F, 0.0F, 0.8F, 1.0F, 0.5F, -1.5F }; + return doGETCTest(CTRL, 0, CTRL); +} + +int testGETC_NonPlayer() +{ + float CTRL[7] = { 0.0F, 0.0F, 0.0F, 0.8F, 1.0F, 0.5F, -1.5F }; + return doGETCTest(CTRL, 2, CTRL); +} #endif \ No newline at end of file diff --git a/TestScripts/C Tests/PosiTests.h b/TestScripts/C Tests/PosiTests.h index d8b5673..a46ca61 100644 --- a/TestScripts/C Tests/PosiTests.h +++ b/TestScripts/C Tests/PosiTests.h @@ -40,6 +40,33 @@ int doPOSITest(char* drefs[7], float values[], int size, int ac, float expected[ return compareArray(expected, actual, 7); } +int doGETPTest(float values[7], int ac, float expected[7]) +{ + // Execute Test + float actual[7]; + XPCSocket sock = openUDP(IP); + int result = sendPOSI(sock, values, 7, ac); + if (result >= 0) + { + result = getPOSI(sock, actual, ac); + } + closeUDP(sock); + if (result < 0) + { + return -1; + } + + // Test values + for (int i = 0; i < 7; ++i) + { + if (fabs(expected[i] - actual[i]) > 1e-4) + { + return -10 - i; + } + } + return 0; +} + int basicPOSITest(char** drefs, int ac) { // Set psoition and initial orientation @@ -116,6 +143,16 @@ int testPOSI_NonPlayer() return basicPOSITest(drefs, 1); } +int testGetPOSI_Player() +{ + float POSI[7] = { 37.524F, -122.06899F, 2500, 0, 0, 0, 1 }; + doGETPTest(POSI, 0, POSI); +} +int testGetPOSI_NonPlayer() +{ + float POSI[7] = { 37.624F, -122.06899F, 1500, 0, 0, 0, 1 }; + doGETPTest(POSI, 3, POSI); +} #endif \ No newline at end of file diff --git a/TestScripts/C Tests/main.c b/TestScripts/C Tests/main.c index 0f5cdd9..26428eb 100644 --- a/TestScripts/C Tests/main.c +++ b/TestScripts/C Tests/main.c @@ -40,9 +40,13 @@ int main(int argc, const char * argv[]) runTest(testCTRL_Player, "CTRL (player)"); runTest(testCTRL_NonPlayer, "CTRL (non-player)"); runTest(testCTRL_Speedbrakes, "CTRL (speedbrakes)"); + runTest(testGETC, "GETC (player)"); + runTest(testGETC_NonPlayer, "GETC (Non-player)"); // POSI runTest(testPOSI_Player, "POSI (player)"); runTest(testPOSI_NonPlayer, "POSI (non-player)"); + runTest(testGetPOSI_Player, "GETP (player)"); + runTest(testGetPOSI_NonPlayer, "GETP (non-player)"); // Data runTest(testDATA, "DATA"); // Text diff --git a/TestScripts/Java Tests/XPlaneConnectTest.java b/TestScripts/Java Tests/XPlaneConnectTest.java index fc7c76e..2e94bb5 100644 --- a/TestScripts/Java Tests/XPlaneConnectTest.java +++ b/TestScripts/Java Tests/XPlaneConnectTest.java @@ -698,4 +698,31 @@ public class XPlaneConnectTest } } + + @Test + public void testGetPOSI() throws IOException + { + float[] values = { 37.524F, -122.06899F, 2500.0F, 45.0F, -45.0F, 15.0F, 1.0F }; + try(XPlaneConnect xpc = new XPlaneConnect()) + { + xpc.pauseSim(true); + xpc.sendPOSI(values); + float[] actual = xpc.getPOSI(0); + + assertArrayEquals(values, actual, 1e-4F); + } + } + + @Test + public void testGetCTRL() throws IOException + { + float[] values = { 0.0F, 0.0F, 0.0F, 0.8F, 1.0F, 0.5F, -1.5F }; + try(XPlaneConnect xpc = new XPlaneConnect()) + { + xpc.sendCTRL(values); + float[] actual = xpc.getCTRL(0); + + assertArrayEquals(values, actual, 1e-4F); + } + } } \ No newline at end of file diff --git a/TestScripts/MATLAB Tests/getCTRLTest.m b/TestScripts/MATLAB Tests/getCTRLTest.m new file mode 100644 index 0000000..3dc74f8 --- /dev/null +++ b/TestScripts/MATLAB Tests/getCTRLTest.m @@ -0,0 +1,15 @@ +function getCTRLTest() +%GETCTRLTEST Summary of this function goes here +% Detailed explanation goes here +addpath('../../MATLAB') +import XPlaneConnect.* + +values = [10.0, 5.0, -5.0, 0.8, 1.0, 0.5, -1.5]; +sendCTRL(values, 0); +actual = getCTRL(0); + +assert(isequal(length(actual), length(values))); +for i = 1:length(actual) + assert(abs(actual(i) - values(i)) <1e-4) +end +end diff --git a/TestScripts/MATLAB Tests/getPOSITest.m b/TestScripts/MATLAB Tests/getPOSITest.m new file mode 100644 index 0000000..c80b79a --- /dev/null +++ b/TestScripts/MATLAB Tests/getPOSITest.m @@ -0,0 +1,17 @@ +function getPOSITest() +%GETCTRLTEST Summary of this function goes here +% Detailed explanation goes here +addpath('../../MATLAB') +import XPlaneConnect.* + +values = [ 37.524, -122.06899, 2500, 45, -45, 15, 1 ]; +pauseSim(1); +sendPOSI(values, 0); +actual = getPOSI(0); +pauseSim(0); + +assert(isequal(length(actual), length(values))); +for i = 1:length(actual) + assert(abs(actual(i) - values(i)) <1e-4) +end +end diff --git a/TestScripts/MATLAB Tests/CTRLTest.m b/TestScripts/MATLAB Tests/sendCTRLTest.m similarity index 98% rename from TestScripts/MATLAB Tests/CTRLTest.m rename to TestScripts/MATLAB Tests/sendCTRLTest.m index 7b8a9bc..0569917 100644 --- a/TestScripts/MATLAB Tests/CTRLTest.m +++ b/TestScripts/MATLAB Tests/sendCTRLTest.m @@ -1,4 +1,4 @@ -function CTRLTest( ) +function sendCTRLTest( ) %CTRLTest Summary of this function goes here % Detailed explanation goes here %% Test player aircraft diff --git a/TestScripts/MATLAB Tests/POSITest.m b/TestScripts/MATLAB Tests/sendPOSITest.m similarity index 96% rename from TestScripts/MATLAB Tests/POSITest.m rename to TestScripts/MATLAB Tests/sendPOSITest.m index 16b6c8d..42a6e15 100644 --- a/TestScripts/MATLAB Tests/POSITest.m +++ b/TestScripts/MATLAB Tests/sendPOSITest.m @@ -1,4 +1,4 @@ -function POSITest( ) +function sendPOSITest( ) %POSITest Summary of this function goes here % Detailed explanation goes here addpath('../../MATLAB') diff --git a/TestScripts/MATLAB Tests/tests.m b/TestScripts/MATLAB Tests/tests.m index 13e0be4..2ef6d5f 100644 --- a/TestScripts/MATLAB Tests/tests.m +++ b/TestScripts/MATLAB Tests/tests.m @@ -18,8 +18,10 @@ theTests = {{@openCloseTest, 'Open/Close Test', 0},... {@getDREFsTest,'Request DREF Test', 0},... {@sendDREFTest,'Send DREF Test', 0},... {@DATATest,'DATA Test', 0},... - {@CTRLTest,'CTRL Test', 0},... - {@POSITest,'POSI Test', 0},... + {@sendCTRLTest,'sendCTRL Test', 0},... + {@getCTRLTest,'getCTRL Test', 0},... + {@sendPOSITest,'sendPOSI Test', 0},... + {@getPOSITest,'getPOSI Test', 0},... {@sendWYPTTest,'WYPT Test', 0},... {@sendVIEWTest,'VIEW Test', 0},... {@pauseTest,'Pause Test', 0},... diff --git a/TestScripts/Python Tests/Tests.py b/TestScripts/Python Tests/Tests.py index 2cdc825..8a88d32 100644 --- a/TestScripts/Python Tests/Tests.py +++ b/TestScripts/Python Tests/Tests.py @@ -202,6 +202,29 @@ class XPCTests(unittest.TestCase): expected = 0.0 do_test() + def test_getCTRL(self): + values = None + ac = 0 + expected = None + def do_test(): + with xpc.XPlaneConnect() as client: + # Execute + client.sendCTRL(values, ac) + result = client.getCTRL(ac) + + # Test + self.assertEqual(len(result), len(expected)) + for a, e in zip(result, expected): + self.assertAlmostEqual(a, e, 4) + + values = [0.0, 0.0, 0.0, 0.8, 1.0, 0.5, -1.5] + expected = values + ac = 0 + do_test() + + ac = 3 + do_test() + def test_sendCTRL(self): # Setup @@ -270,6 +293,31 @@ class XPCTests(unittest.TestCase): ctrl[6] = 0.0 do_test() + def test_getPOSI(self): + values = None + ac = 0 + expected = None + def do_test(): + with xpc.XPlaneConnect() as client: + # Execute + client.pauseSim(True) + client.sendPOSI(values, ac) + result = client.getPOSI(ac) + client.pauseSim(False) + + # Test + self.assertEqual(len(result), len(expected)) + for a, e in zip(result, expected): + self.assertAlmostEqual(a, e, 4) + + values = [ 37.524, -122.06899, 2500, 45, -45, 15, 1 ] + expected = values + ac = 0 + do_test() + + ac = 3 + do_test() + def test_sendPOSI(self): # Setup drefs = ["sim/flightmodel/position/latitude",\ diff --git a/xpcPlugin/DataManager.cpp b/xpcPlugin/DataManager.cpp index 42048e5..eccb8c2 100644 --- a/xpcPlugin/DataManager.cpp +++ b/xpcPlugin/DataManager.cpp @@ -169,8 +169,8 @@ namespace XPC sprintf(multi, "sim/multiplayer/position/plane%i_gear_deploy", i); mdrefs[i][DREF_GearDeploy] = XPLMFindDataRef(multi); sprintf(multi, "sim/multiplayer/position/plane%i_flap_ratio", i); - mdrefs[i][DREF_FlapSetting] = XPLMFindDataRef(multi); // Can't set the actual flap setting on npc aircraft mdrefs[i][DREF_FlapActual] = XPLMFindDataRef(multi); + mdrefs[i][DREF_FlapSetting] = mdrefs[i][DREF_FlapActual]; // Can't set the actual flap setting on npc aircraft sprintf(multi, "sim/multiplayer/position/plane%i_flap_ratio2", i); mdrefs[i][DREF_FlapActual2] = XPLMFindDataRef(multi); sprintf(multi, "sim/multiplayer/position/plane%i_spoiler_ratio", i); @@ -183,6 +183,7 @@ namespace XPC mdrefs[i][DREF_Sweep] = XPLMFindDataRef(multi); sprintf(multi, "sim/multiplayer/position/plane%i_throttle", i); mdrefs[i][DREF_ThrottleActual] = XPLMFindDataRef(multi); + mdrefs[i][DREF_ThrottleSet] = mdrefs[i][DREF_ThrottleActual]; // No throttle set for multiplayer planes. sprintf(multi, "sim/multiplayer/position/plane%i_yolk_pitch", i); mdrefs[i][DREF_YokePitch] = XPLMFindDataRef(multi); sprintf(multi, "sim/multiplayer/position/plane%i_yolk_roll", i); @@ -729,13 +730,13 @@ namespace XPC // http://ntrs.nasa.gov/archive/nasa/casi.ntrs.nasa.gov/19770024290.pdf float q[4]; float halfRad = 0.00872664625997F; - orient[2] = halfRad * orient[2]; - orient[0] = halfRad * orient[0]; - orient[1] = halfRad * orient[1]; - q[0] = cos(orient[2]) * cos(orient[0]) * cos(orient[1]) + sin(orient[2]) * sin(orient[0]) * sin(orient[1]); - q[1] = cos(orient[2]) * cos(orient[0]) * sin(orient[1]) - sin(orient[2]) * sin(orient[0]) * cos(orient[1]); - q[2] = cos(orient[2]) * sin(orient[0]) * cos(orient[1]) + sin(orient[2]) * cos(orient[0]) * sin(orient[1]); - q[3] = sin(orient[2]) * cos(orient[0]) * cos(orient[1]) - cos(orient[2]) * sin(orient[0]) * sin(orient[1]); + float theta = halfRad * orient[0]; + float phi = halfRad * orient[1]; + float psi = halfRad * orient[2]; + q[0] = cos(phi) * cos(theta) * cos(psi) + sin(phi) * sin(theta) * sin(psi); + q[1] = sin(phi) * cos(theta) * cos(psi) - cos(phi) * sin(theta) * sin(psi); + q[2] = cos(phi) * sin(theta) * cos(psi) + sin(phi) * cos(theta) * sin(psi); + q[3] = cos(phi) * cos(theta) * sin(psi) - sin(phi) * sin(theta) * cos(psi); // If the sim is un-paused, this will overwrite the pitch/roll/yaw // values set above. diff --git a/xpcPlugin/MessageHandlers.cpp b/xpcPlugin/MessageHandlers.cpp index d72b8a8..d94be09 100644 --- a/xpcPlugin/MessageHandlers.cpp +++ b/xpcPlugin/MessageHandlers.cpp @@ -55,6 +55,8 @@ namespace XPC handlers.insert(std::make_pair("TEXT", MessageHandlers::HandleText)); handlers.insert(std::make_pair("WYPT", MessageHandlers::HandleWypt)); handlers.insert(std::make_pair("VIEW", MessageHandlers::HandleView)); + handlers.insert(std::make_pair("GETC", MessageHandlers::HandleGetC)); + handlers.insert(std::make_pair("GETP", MessageHandlers::HandleGetP)); // X-Plane data messages handlers.insert(std::make_pair("DSEL", MessageHandlers::HandleXPlaneData)); handlers.insert(std::make_pair("USEL", MessageHandlers::HandleXPlaneData)); @@ -425,6 +427,43 @@ namespace XPC } } + void MessageHandlers::HandleGetC(const Message& msg) + { + const unsigned char* buffer = msg.GetBuffer(); + std::size_t size = msg.GetSize(); + if (size != 6) + { + Log::FormatLine(LOG_ERROR, "GCTL", "Unexpected message length: %u", size); + return; + } + unsigned char aircraft = buffer[5]; + // TODO(jason-watkins): Get proper printf specifier for unsigned char + Log::FormatLine(LOG_TRACE, "GCTL", "Getting control information for aircraft %u", aircraft); + + float throttle[8]; + unsigned char response[31] = "CTRL"; + *((float*)(response + 5)) = DataManager::GetFloat(DREF_Elevator, aircraft); + *((float*)(response + 9)) = DataManager::GetFloat(DREF_Aileron, aircraft); + *((float*)(response + 13)) = DataManager::GetFloat(DREF_Rudder, aircraft); + DataManager::GetFloatArray(DREF_ThrottleSet, throttle, 8, aircraft); + *((float*)(response + 17)) = throttle[0]; + if (aircraft == 0) + { + response[21] = (char)DataManager::GetInt(DREF_GearHandle, aircraft); + } + else + { + float mpGear[10]; + DataManager::GetFloatArray(DREF_GearDeploy, mpGear, 10, aircraft); + response[21] = mpGear[0] > 0.5 ? 1 : 0; + } + *((float*)(response + 22)) = DataManager::GetFloat(DREF_FlapSetting, aircraft); + response[26] = aircraft; + *((float*)(response + 27)) = DataManager::GetFloat(DREF_SpeedBrakeSet, aircraft); + + sock->SendTo(response, 31, &connection.addr); + } + void MessageHandlers::HandleGetD(const Message& msg) { const unsigned char* buffer = msg.GetBuffer(); @@ -471,6 +510,34 @@ namespace XPC sock->SendTo(response, cur, &connection.addr); } + void MessageHandlers::HandleGetP(const Message& msg) + { + const unsigned char* buffer = msg.GetBuffer(); + std::size_t size = msg.GetSize(); + if (size != 6) + { + Log::FormatLine(LOG_ERROR, "GPOS", "Unexpected message length: %u", size); + return; + } + unsigned char aircraft = buffer[5]; + Log::FormatLine(LOG_TRACE, "GPOS", "Getting position information for aircraft %u", aircraft); + + unsigned char response[34] = "POSI"; + response[5] = (char)DataManager::GetInt(DREF_GearHandle, aircraft); + *((float*)(response + 6)) = (float)DataManager::GetDouble(DREF_Latitude, aircraft); + *((float*)(response + 10)) = (float)DataManager::GetDouble(DREF_Longitude, aircraft); + *((float*)(response + 14)) = (float)DataManager::GetDouble(DREF_Elevation, aircraft); + *((float*)(response + 18)) = DataManager::GetFloat(DREF_Pitch, aircraft); + *((float*)(response + 22)) = DataManager::GetFloat(DREF_Roll, aircraft); + *((float*)(response + 26)) = DataManager::GetFloat(DREF_HeadingTrue, aircraft); + + float gear[10]; + DataManager::GetFloatArray(DREF_GearDeploy, gear, 10, aircraft); + *((float*)(response + 30)) = gear[0]; + + sock->SendTo(response, 34, &connection.addr); + } + void MessageHandlers::HandlePosi(const Message& msg) { // Update log diff --git a/xpcPlugin/MessageHandlers.h b/xpcPlugin/MessageHandlers.h index 13742ee..d7f317d 100644 --- a/xpcPlugin/MessageHandlers.h +++ b/xpcPlugin/MessageHandlers.h @@ -43,7 +43,9 @@ namespace XPC static void HandleCtrl(const Message& msg); static void HandleData(const Message& msg); static void HandleDref(const Message& msg); + static void HandleGetC(const Message& msg); static void HandleGetD(const Message& msg); + static void HandleGetP(const Message& msg); static void HandlePosi(const Message& msg); static void HandleSimu(const Message& msg); static void HandleText(const Message& msg); diff --git a/xpcPlugin/UDPSocket.cpp b/xpcPlugin/UDPSocket.cpp index 349f127..210cc56 100644 --- a/xpcPlugin/UDPSocket.cpp +++ b/xpcPlugin/UDPSocket.cpp @@ -135,7 +135,7 @@ namespace XPC } else { - Log::FormatLine(LOG_INFO, tag, "Send failed. (remote: %s)", GetHost(remote).c_str()); + Log::FormatLine(LOG_INFO, tag, "Send succeeded. (remote: %s)", GetHost(remote).c_str()); } }