Version 1.3-rc.1 (#138)
* Minor improvements to the handling of landing gear by the SetGear and HandlePOSI functions * sendPOSI command change (double for lat/lon/h) (#111) * Updated POSI to use doubles for lat/lon/alt, as step size for floats was unacceptably large at high longitudes. * Updated Java library for MATLAB, updated Java project, and updated Windows plugin binaries * Rolled back Java version to 1.7 for MATLAB compatibility * Update MessageHandlers.cpp * Update DataManager.cpp * Added pause functionality for individual a/c Adds new cases such that: 0: Unpauses all a/c 1: Pauses all a/c 2: Switches case for all a/c 100:119: Pauses a/c 0:19 200:219: Unpauses a/c 0:19 Updates log messages. Keeps the 0,1,2 arguments as they previously were. * Finished individual pause functionality * Update DataManager.cpp * Updated flags to allow for individual pause commands * Individual pause command documentation * Updated flags to allow for individual pause commands * Adding individual pause to documentation * Updated flags to allow for individual pause commands * Requested changes, cleaning * Update CMakeLists.txt Include "-fno-stack-protector" for linking and compiling for systems that do not have this have this flag as a default. * Enabling AI after setting position (#118) Previously, the code enabled the AI before setting the position of a/c, which negated its purpose. * Updated XPlane SDK to version 2.1.3 * Resolve function ambiguity for std::abs on mac Fixes #126 * Update copyright notice * Update Windows binaries * Update Linux binaries * Update version numbers * fix osx abs ambiguity (#142) * fix indexing error (#143) * Runway camera location control (#144) * update ignore * basics working * set cam pos remotely * log cam position * keep default behaviour, if short view message is received Compatibility with existing software * all to tabs * rename variable * option to use camera direction fields * Added UDP multicast for plugin discovery (#153) * Added Timer * Added UDPSocket::GetAddr * Added MessageHandlers::SendBeacon() * PoC of starting a timer on PluginEnable * C++11 * Added Timer to xcode project * C++11 in cmake * added Timer to cmake * use function pointer in Timer * moved Timer to namespace + wait for thread to join when stopping the timer * Windows: changed uint to unisgned short * Windows: Added Timer.h/cpp to project * GetAddr static * Send xplane and plugin version with BECN * SendBeacon with params * fixed file copyrights * Include functional to fix Linux compile error * review fixes * Send plugin receive port in BECN * review fixes * Fixed tabs vs spaces indentations (#157) * Java client BECN implementation (#155) * Added MS Azure Dev Ops CI integration (#162) * Do not build for i386 on macOS Use ARCHS_STANDARD to avoid the error “The i386 architecture is deprecated. You should update your ARCHS build setting to remove the i386 architecture.” * Fixed missing include The Visual Studio solution was not compiling * Fixed isnan ambigious refernce Ambigious reference when compiling on travis https://stackoverflow.com/questions/33770374/why-is-isnan-ambiguous-and-how-to-avoid-it * Set MSVC warning level to 3 Too many warnings were generated when building a Release build making Travis job to fail because of too much output * Use default toolset for Visual Studio AppVeyor recommends to set the default toolset * #include <cstdint> * Use MSVC ToolsVersion="14.0" # Conflicts: # xpcPlugin/xpcPlugin/xpcPlugin.vcxproj * Removed binaries from repository # Conflicts: # xpcPlugin/XPlaneConnect/64/win.xpl # xpcPlugin/XPlaneConnect/win.xpl * Added ms azure ci xcode linux linux + macos linux + macos removed branch filter win tests win tests Test all platfroms artifacts tests * output all binaries to ‘XPlaneConnect’ All platforms produce a binary in xpcPlugin/XPlaneConnect/ xpcPlugin/XPlaneConnect/64/ * Added ms azure GH deploy deploy stage GH release test trigger tags * Clean up yml file - Added variables - Added job decriptions * Ignore script to ignore .exp files + fixed output path * Renamed ms azure GH connection * Update service connection for azure pipeline * Added Python3 compatible xpc client. (#156) * Update Azure Pipelines service connection
This commit is contained in:
15
Java/.idea/misc.xml
generated
15
Java/.idea/misc.xml
generated
@@ -1,19 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="EntryPointsManager">
|
||||
<entry_points version="2.0" />
|
||||
</component>
|
||||
<component name="ProjectLevelVcsManager" settingsEditedManually="false">
|
||||
<OptionsSetting value="true" id="Add" />
|
||||
<OptionsSetting value="true" id="Remove" />
|
||||
<OptionsSetting value="true" id="Checkout" />
|
||||
<OptionsSetting value="true" id="Update" />
|
||||
<OptionsSetting value="true" id="Status" />
|
||||
<OptionsSetting value="true" id="Edit" />
|
||||
<ConfirmationsSetting value="0" id="Add" />
|
||||
<ConfirmationsSetting value="0" id="Remove" />
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" default="true" assert-keyword="true" jdk-15="true" project-jdk-name="1.7" project-jdk-type="JavaSDK">
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="false" project-jdk-name="11" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
</component>
|
||||
</project>
|
||||
1
Java/.idea/modules.xml
generated
1
Java/.idea/modules.xml
generated
@@ -2,6 +2,7 @@
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/Examples/DiscoveryExample/DiscoveryExample.iml" filepath="$PROJECT_DIR$/Examples/DiscoveryExample/DiscoveryExample.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/XPlaneConnect.iml" filepath="$PROJECT_DIR$/XPlaneConnect.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package gov.nasa.xpc.ex;
|
||||
|
||||
import gov.nasa.xpc.XPlaneConnect;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.SocketException;
|
||||
import java.util.Arrays;
|
||||
@@ -25,11 +24,11 @@ public class Main
|
||||
xpc.getDREF("sim/test/test_float");
|
||||
|
||||
System.out.println("Setting player aircraft position");
|
||||
float[] posi = new float[] {37.524F, -122.06899F, 2500, 0, 0, 0, 1};
|
||||
double[] posi = new double[] {37.524, -122.06899, 2500, 0, 0, 0, 1};
|
||||
xpc.sendPOSI(posi);
|
||||
|
||||
System.out.println("Setting another aircraft position");
|
||||
posi[0] = 37.52465F;
|
||||
posi[0] = 37.52465;
|
||||
posi[4] = 20;
|
||||
xpc.sendPOSI(posi, 1);
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ public class Main
|
||||
int aircraft = 0;
|
||||
while(true)
|
||||
{
|
||||
float[] posi = xpc.getPOSI(aircraft);
|
||||
float[] posi = xpc.getPOSI(aircraft); // FIXME: change this to 64-bit double
|
||||
float[] ctrl = xpc.getCTRL(aircraft);
|
||||
|
||||
System.out.format("Loc: (%4f, %4f, %4f) Aileron:%2f Elevator:%2f Rudder:%2f\n",
|
||||
|
||||
12
Java/Examples/DiscoveryExample/DiscoveryExample.iml
Normal file
12
Java/Examples/DiscoveryExample/DiscoveryExample.iml
Normal file
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" packagePrefix="gov.nasa.xpc.ex" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="module" module-name="XPlaneConnect" />
|
||||
</component>
|
||||
</module>
|
||||
@@ -0,0 +1,35 @@
|
||||
package gov.nasa.xpc.ex;
|
||||
|
||||
import gov.nasa.xpc.XPlaneConnect;
|
||||
import gov.nasa.xpc.discovery.XPlaneConnectDiscovery;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.SocketException;
|
||||
|
||||
|
||||
|
||||
public class DiscoveryConnectionExample {
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
|
||||
XPlaneConnectDiscovery discovery = new XPlaneConnectDiscovery();
|
||||
discovery.start(xpc -> {
|
||||
|
||||
sendDref(xpc);
|
||||
});
|
||||
System.out.println("Example done");
|
||||
}
|
||||
|
||||
static void sendDref(XPlaneConnect xpc) {
|
||||
System.out.println("Sending DREF");
|
||||
try {
|
||||
xpc.getDREF("sim/test/test_float");
|
||||
|
||||
} catch (SocketException e) {
|
||||
System.out.println("Unable to set up the connection. (Error message was '" + e.getMessage() + "'.)");
|
||||
} catch (IOException e) {
|
||||
System.out.println("Something went wrong with one of the commands. (Error message was '" + e.getMessage() + "'.)");
|
||||
}
|
||||
System.out.println("Sending DREF done");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package gov.nasa.xpc.ex;
|
||||
|
||||
import gov.nasa.xpc.discovery.XPlaneConnectDiscovery;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
|
||||
/**
|
||||
* XPlaneConnect discovery example that prints continuously each BECN packet
|
||||
*/
|
||||
public class SimpleDiscoveryExample {
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
XPlaneConnectDiscovery discovery = new XPlaneConnectDiscovery();
|
||||
discovery.onBeaconReceived(beacon -> {
|
||||
System.out.println("Discovered XPlaneConnect plugin:");
|
||||
System.out.println("Plugin version: " + beacon.getPluginVersion());
|
||||
System.out.println("X-Plane version: " + beacon.getXplaneVersion());
|
||||
System.out.println("Address: " + beacon.getXplaneAddress().getHostAddress() + ":" + beacon.getPluginPort());
|
||||
});
|
||||
discovery.start();
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,7 @@ public class Main
|
||||
{
|
||||
String[] mainOpts = new String[] { "Record X-Plane", "Playback File", "Exit" };
|
||||
|
||||
System.out.println("X-Plane Connect Playback Example [Version 1.2.0.0]");
|
||||
System.out.println("X-Plane Connect Playback Example [Version 1.3-rc.1]");
|
||||
System.out.println("(c) 2013-2015 United States Government as represented by the Administrator");
|
||||
System.out.println("of the National Aeronautics and Space Administration. All Rights Reserved.");
|
||||
while(true)
|
||||
@@ -99,7 +99,7 @@ public class Main
|
||||
{
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
float[] posi = xpc.getPOSI(0);
|
||||
float[] posi = xpc.getPOSI(0); // FIXME: change this to 64-bit double
|
||||
writer.write(String.format("%1$f, %2$f, %3$f, %4$f, %5$f, %6$f, %7$f\n",
|
||||
posi[0], posi[1], posi[2], posi[3], posi[4], posi[5], posi[6]));
|
||||
try
|
||||
@@ -125,11 +125,11 @@ public class Main
|
||||
{
|
||||
while(reader.hasNextLine())
|
||||
{
|
||||
float[] posi = new float[7];
|
||||
double[] posi = new double[7];
|
||||
for (int i = 0; i < 7; ++i)
|
||||
{
|
||||
String s = reader.next();
|
||||
posi[i] = Float.parseFloat(s);
|
||||
posi[i] = Double.parseDouble(s);
|
||||
}
|
||||
reader.nextLine();
|
||||
xpc.sendPOSI(posi);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" packagePrefix="gov.nasa.xpc" />
|
||||
@@ -10,6 +10,15 @@
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="library" name="junit-4.11" level="project" />
|
||||
<orderEntry type="module-library" scope="TEST">
|
||||
<library name="JUnit4">
|
||||
<CLASSES>
|
||||
<root url="jar://$MODULE_DIR$/lib/junit-4.12.jar!/" />
|
||||
<root url="jar://$MODULE_DIR$/lib/hamcrest-core-1.3.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
</orderEntry>
|
||||
</component>
|
||||
</module>
|
||||
BIN
Java/lib/hamcrest-core-1.3.jar
Normal file
BIN
Java/lib/hamcrest-core-1.3.jar
Normal file
Binary file not shown.
BIN
Java/lib/junit-4.12.jar
Normal file
BIN
Java/lib/junit-4.12.jar
Normal file
Binary file not shown.
@@ -1,5 +1,5 @@
|
||||
//NOTICES:
|
||||
// Copyright (c) 2013-2016 United States Government as represented by the Administrator of the
|
||||
// Copyright (c) 2013-2018 United States Government as represented by the Administrator of the
|
||||
// National Aeronautics and Space Administration. All Rights Reserved.
|
||||
//
|
||||
// DISCLAIMERS
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//NOTICES:
|
||||
// Copyright (c) 2013-2016 United States Government as represented by the Administrator of the
|
||||
// Copyright (c) 2013-2018 United States Government as represented by the Administrator of the
|
||||
// National Aeronautics and Space Administration. All Rights Reserved.
|
||||
//
|
||||
// DISCLAIMERS
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//NOTICES:
|
||||
// Copyright (c) 2013-2016 United States Government as represented by the Administrator of the
|
||||
// Copyright (c) 2013-2018 United States Government as represented by the Administrator of the
|
||||
// National Aeronautics and Space Administration. All Rights Reserved.
|
||||
//
|
||||
// DISCLAIMERS
|
||||
@@ -25,6 +25,8 @@
|
||||
|
||||
package gov.nasa.xpc;
|
||||
|
||||
import gov.nasa.xpc.discovery.Beacon;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.lang.AutoCloseable;
|
||||
@@ -136,6 +138,19 @@ public class XPlaneConnect implements AutoCloseable
|
||||
this(xpHost, xpPort, port, 100);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Initializes a new instance of the {@code XPlaneConnect} class from a received discovery Beacon
|
||||
* @param beacon The beacon received from {@code XPlaneConnectDiscovery}
|
||||
* @throws SocketException If this instance is unable to bind to the specified port.
|
||||
*/
|
||||
public XPlaneConnect(Beacon beacon) throws SocketException {
|
||||
this.socket = new DatagramSocket(0);
|
||||
this.xplaneAddr = beacon.getXplaneAddress();
|
||||
this.xplanePort = beacon.getPluginPort();
|
||||
this.socket.setSoTimeout(100);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes a new instance of the {@code XPlaneConnect} class using the specified ports, hostname, and timeout.
|
||||
*
|
||||
@@ -223,9 +238,9 @@ public class XPlaneConnect implements AutoCloseable
|
||||
*/
|
||||
public void pauseSim(int pause) throws IOException
|
||||
{
|
||||
if(pause < 0 || pause > 2)
|
||||
if(pause < 0 || (pause > 2 && pause < 100) || (pause > 119 && pause < 200) || pause > 219)
|
||||
{
|
||||
throw new IllegalArgumentException("pause must be a value in the range [0, 2].");
|
||||
throw new IllegalArgumentException("pause must be a value in the range [0, 2], [100, 119], or [200, 219].");
|
||||
}
|
||||
|
||||
// S I M U LEN VAL
|
||||
@@ -549,7 +564,7 @@ public class XPlaneConnect implements AutoCloseable
|
||||
* @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
|
||||
public double[] getPOSI(int ac) throws IOException
|
||||
{
|
||||
// Send request
|
||||
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
||||
@@ -570,7 +585,7 @@ public class XPlaneConnect implements AutoCloseable
|
||||
}
|
||||
|
||||
// Parse response
|
||||
float[] result = new float[7];
|
||||
double[] result = new double[7];
|
||||
ByteBuffer bb = ByteBuffer.wrap(data);
|
||||
bb.order(ByteOrder.LITTLE_ENDIAN);
|
||||
for(int i = 0; i < 7; ++i)
|
||||
@@ -600,13 +615,13 @@ public class XPlaneConnect implements AutoCloseable
|
||||
* </p>
|
||||
* @throws IOException If the command can not be sent.
|
||||
*/
|
||||
public void sendPOSI(float[] values) throws IOException
|
||||
public void sendPOSI(double[] values) throws IOException
|
||||
{
|
||||
sendPOSI(values, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the position of the specified ac.
|
||||
* Sets the position of the specified ac with double precision coordinates.
|
||||
*
|
||||
* @param values <p>An array containing position elements as follows:</p>
|
||||
* <ol>
|
||||
@@ -626,7 +641,7 @@ public class XPlaneConnect implements AutoCloseable
|
||||
* @param ac The ac to set. 0 for the player ac.
|
||||
* @throws IOException If the command can not be sent.
|
||||
*/
|
||||
public void sendPOSI(float[] values, int ac) throws IOException
|
||||
public void sendPOSI(double[] values, int ac) throws IOException
|
||||
{
|
||||
//Preconditions
|
||||
if(values == null)
|
||||
@@ -644,15 +659,22 @@ public class XPlaneConnect implements AutoCloseable
|
||||
|
||||
//Pad command values and convert to bytes
|
||||
int i;
|
||||
ByteBuffer bb = ByteBuffer.allocate(28);
|
||||
ByteBuffer bb = ByteBuffer.allocate(40);
|
||||
bb.order(ByteOrder.LITTLE_ENDIAN);
|
||||
for(i = 0; i < values.length; ++i)
|
||||
{
|
||||
bb.putFloat(i * 4, values[i]);
|
||||
if(i<3) /* lat/lon/height as double */
|
||||
{
|
||||
bb.putDouble(values[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
bb.putFloat((float)values[i]);
|
||||
}
|
||||
}
|
||||
for(; i < 7; ++i)
|
||||
{
|
||||
bb.putFloat(i * 4, -998);
|
||||
bb.putFloat(-998);
|
||||
}
|
||||
|
||||
//Build and send message
|
||||
|
||||
45
Java/src/discovery/Beacon.java
Normal file
45
Java/src/discovery/Beacon.java
Normal file
@@ -0,0 +1,45 @@
|
||||
package gov.nasa.xpc.discovery;
|
||||
|
||||
import java.net.InetAddress;
|
||||
|
||||
|
||||
public class Beacon {
|
||||
|
||||
private InetAddress xplaneAddress;
|
||||
private int pluginPort;
|
||||
private String pluginVersion;
|
||||
private int xPlaneVersion;
|
||||
|
||||
|
||||
public Beacon(InetAddress xplaneAddress, int pluginPort, String pluginVersion, int xPlaneVersion) {
|
||||
this.xplaneAddress = xplaneAddress;
|
||||
this.pluginPort = pluginPort;
|
||||
this.pluginVersion = pluginVersion;
|
||||
this.xPlaneVersion = xPlaneVersion;
|
||||
}
|
||||
|
||||
public String getHost() {
|
||||
return xplaneAddress.getHostAddress();
|
||||
}
|
||||
|
||||
public String getPluginVersion() {
|
||||
return pluginVersion;
|
||||
}
|
||||
|
||||
public String getXplaneVersion() {
|
||||
return String.format("%.2f", xPlaneVersion / 100.0);
|
||||
}
|
||||
|
||||
public int getPluginPort() {
|
||||
return pluginPort;
|
||||
}
|
||||
|
||||
public InetAddress getXplaneAddress() {
|
||||
return xplaneAddress;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "host: " + getHost() + ":" + getPluginPort() +" version: " + getPluginVersion() + " X-Plane Version: " + getXplaneVersion();
|
||||
}
|
||||
}
|
||||
54
Java/src/discovery/BeaconParser.java
Normal file
54
Java/src/discovery/BeaconParser.java
Normal file
@@ -0,0 +1,54 @@
|
||||
package gov.nasa.xpc.discovery;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.DatagramPacket;
|
||||
import java.net.InetAddress;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
|
||||
/**
|
||||
* Parser class that parses the UDP discovery BECN packet. The format of the packet is
|
||||
* - 4 bytes: BECN
|
||||
* - 1 byte: 0
|
||||
* - 2 bytes: XPlaneConnect server port e.g. '49009'
|
||||
* - 4 bytes: X-Plane version e.g. '11260'
|
||||
* - null terminated string: XPlaneConnect plugin version e.g. '1.3-rc.1'
|
||||
*/
|
||||
public class BeaconParser {
|
||||
|
||||
private static String BECN = "BECN";
|
||||
|
||||
private static int XPC_PORT_OFFSET = BECN.length() + 1;
|
||||
private static int XPC_PORT_LEN = 2;
|
||||
private static int XPC_VERSION_OFFSET = XPC_PORT_OFFSET + XPC_PORT_LEN;
|
||||
private static int XPC_VERSION_LEN = 4;
|
||||
private static int XPC_PLUGIN_VERSION_OFFSET = XPC_VERSION_OFFSET + XPC_VERSION_LEN;
|
||||
|
||||
|
||||
public Beacon readBCN(DatagramPacket packet) throws IOException {
|
||||
if (packet.getLength() < BECN.length()) {
|
||||
throw new IOException("BECN response too short");
|
||||
}
|
||||
|
||||
byte[] data = packet.getData();
|
||||
|
||||
String command = new String(data, 0, BECN.length());
|
||||
if (!command.equals(BECN)) {
|
||||
throw new IOException("Expected " + BECN + " got '" + command + "'");
|
||||
}
|
||||
|
||||
InetAddress address = packet.getAddress();
|
||||
ByteBuffer bb = ByteBuffer.wrap(data);
|
||||
bb.order(ByteOrder.LITTLE_ENDIAN);
|
||||
// 2 bytes: port as short + converted to an int
|
||||
int port = bb.getShort(XPC_PORT_OFFSET) & 0xffff;
|
||||
|
||||
// 4 bytes: x plane version as int
|
||||
int version = bb.getInt(XPC_VERSION_OFFSET);
|
||||
|
||||
// plugin version
|
||||
String pluginVersion = new String(data, XPC_PLUGIN_VERSION_OFFSET, packet.getLength() - XPC_PLUGIN_VERSION_OFFSET);
|
||||
|
||||
return new Beacon(address, port, pluginVersion.trim(), version);
|
||||
}
|
||||
}
|
||||
10
Java/src/discovery/BeaconReceivedListener.java
Normal file
10
Java/src/discovery/BeaconReceivedListener.java
Normal file
@@ -0,0 +1,10 @@
|
||||
package gov.nasa.xpc.discovery;
|
||||
|
||||
public interface BeaconReceivedListener {
|
||||
|
||||
/**
|
||||
* Called every time a BECN packet is received
|
||||
* @param beacon The parsed beacon
|
||||
*/
|
||||
void onBeaconReceived(Beacon beacon);
|
||||
}
|
||||
14
Java/src/discovery/DiscoveryConnectionCallback.java
Normal file
14
Java/src/discovery/DiscoveryConnectionCallback.java
Normal file
@@ -0,0 +1,14 @@
|
||||
package gov.nasa.xpc.discovery;
|
||||
|
||||
import gov.nasa.xpc.XPlaneConnect;
|
||||
|
||||
public interface DiscoveryConnectionCallback {
|
||||
|
||||
/**
|
||||
* Helper callback called when a 1st XPlanePlugin is discovered. When the 1st packet is received, an XPlaneConnect
|
||||
* instance is created and the discovery is stopped.
|
||||
*
|
||||
* @param xpc The XPlaneConnect instance configured with the discovered
|
||||
*/
|
||||
void onConnectionEstablished(XPlaneConnect xpc);
|
||||
}
|
||||
94
Java/src/discovery/XPlaneConnectDiscovery.java
Normal file
94
Java/src/discovery/XPlaneConnectDiscovery.java
Normal file
@@ -0,0 +1,94 @@
|
||||
package gov.nasa.xpc.discovery;
|
||||
|
||||
import gov.nasa.xpc.XPlaneConnect;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.DatagramPacket;
|
||||
import java.net.InetAddress;
|
||||
import java.net.MulticastSocket;
|
||||
import java.net.SocketException;
|
||||
|
||||
|
||||
/**
|
||||
* The XPlaneConnectDiscovery joins a UDP multi cast group and listens for BECN packets published by
|
||||
* XPlaneConnect server plugin. It allows to clients to discover XPlane instances and be sure that the XPlanePlugin is
|
||||
* installed.
|
||||
*/
|
||||
public class XPlaneConnectDiscovery implements AutoCloseable {
|
||||
|
||||
private static int DEFAULT_PORT = 49710;
|
||||
private static String DEFAULT_ADDRESS = "239.255.1.1";
|
||||
|
||||
private BeaconReceivedListener mListener;
|
||||
|
||||
private MulticastSocket socket = null;
|
||||
private byte[] buf = new byte[256];
|
||||
|
||||
private int mPort;
|
||||
private String mAddress;
|
||||
private BeaconParser parser = new BeaconParser();
|
||||
|
||||
private XPlaneConnectDiscovery(int port, String address) {
|
||||
mPort = port;
|
||||
mAddress = address;
|
||||
}
|
||||
|
||||
public XPlaneConnectDiscovery() {
|
||||
this(DEFAULT_PORT, DEFAULT_ADDRESS);
|
||||
}
|
||||
|
||||
public void start(DiscoveryConnectionCallback callback) throws IOException {
|
||||
onBeaconReceived(beacon -> {
|
||||
this.close();
|
||||
|
||||
try {
|
||||
XPlaneConnect xpc = new XPlaneConnect(beacon);
|
||||
callback.onConnectionEstablished(xpc);
|
||||
} catch (SocketException e) {
|
||||
System.err.println("Could not connect to a discovered XplaneConnect " +beacon+ ": " + e.getMessage());
|
||||
}
|
||||
});
|
||||
start();
|
||||
|
||||
}
|
||||
|
||||
public void start() throws IOException {
|
||||
System.out.println("Starting XPlane Connect discovery");
|
||||
socket = new MulticastSocket(mPort);
|
||||
InetAddress group = InetAddress.getByName(mAddress);
|
||||
socket.joinGroup(group);
|
||||
while (socket != null) {
|
||||
DatagramPacket packet = new DatagramPacket(buf, buf.length);
|
||||
socket.receive(packet);
|
||||
if (mListener == null) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
Beacon beacon = parser.readBCN(packet);
|
||||
mListener.onBeaconReceived(beacon);
|
||||
} catch (IOException ex) {
|
||||
System.err.println("Received packet on discovery group but could not parse it: " + ex);
|
||||
}
|
||||
}
|
||||
|
||||
close();
|
||||
System.out.println("XPlane Connect discovery ended");
|
||||
}
|
||||
|
||||
|
||||
public void onBeaconReceived(BeaconReceivedListener mListener) {
|
||||
this.mListener = mListener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
if (socket != null) {
|
||||
socket.close();
|
||||
socket = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
close();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user