Updated Java client to conform to new API.
- Now uses a single socket. - Constructor parameter reordered to match C client. - Defaults to an OS assigned port instead of 49008.
This commit is contained in:
@@ -44,8 +44,7 @@ import java.util.Arrays;
|
|||||||
public class XPlaneConnect implements AutoCloseable
|
public class XPlaneConnect implements AutoCloseable
|
||||||
{
|
{
|
||||||
private static int clientNum;
|
private static int clientNum;
|
||||||
private DatagramSocket outSocket;
|
private DatagramSocket socket;
|
||||||
private DatagramSocket inSocket;
|
|
||||||
private InetAddress xplaneAddr;
|
private InetAddress xplaneAddr;
|
||||||
private int xplanePort;
|
private int xplanePort;
|
||||||
|
|
||||||
@@ -54,7 +53,7 @@ public class XPlaneConnect implements AutoCloseable
|
|||||||
*
|
*
|
||||||
* @return The incoming port number.
|
* @return The incoming port number.
|
||||||
*/
|
*/
|
||||||
public int getRecvPort() { return inSocket.getLocalPort(); }
|
public int getRecvPort() { return socket.getLocalPort(); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the port on which the client sends data to X-Plane.
|
* Gets the port on which the client sends data to X-Plane.
|
||||||
@@ -116,46 +115,44 @@ public class XPlaneConnect implements AutoCloseable
|
|||||||
*/
|
*/
|
||||||
public XPlaneConnect(int timeout) throws SocketException
|
public XPlaneConnect(int timeout) throws SocketException
|
||||||
{
|
{
|
||||||
this.inSocket = new DatagramSocket(49008);
|
this.socket = new DatagramSocket(0);
|
||||||
this.outSocket = new DatagramSocket(50000 + ++clientNum);
|
|
||||||
this.xplaneAddr = InetAddress.getLoopbackAddress();
|
this.xplaneAddr = InetAddress.getLoopbackAddress();
|
||||||
this.xplanePort = 49009;
|
this.xplanePort = 49009;
|
||||||
this.inSocket.setSoTimeout(timeout);
|
this.socket.setSoTimeout(timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes a new instance of the {@code XPlaneConnect} class using the specified ports and X-Plane host.
|
* Initializes a new instance of the {@code XPlaneConnect} class using the specified ports and X-Plane host.
|
||||||
*
|
*
|
||||||
* @param port The port on which the X-Plane Connect plugin is sending data.
|
* @param port The port on which the X-Plane Connect plugin is sending data.
|
||||||
* @param xplaneHost The network host on which X-Plane is running.
|
* @param xpHost The network host on which X-Plane is running.
|
||||||
* @param xplanePort The port on which the X-Plane Connect plugin is listening.
|
* @param xpPort The port on which the X-Plane Connect plugin is listening.
|
||||||
* @throws java.net.SocketException If this instance is unable to bind to the specified port.
|
* @throws java.net.SocketException If this instance is unable to bind to the specified port.
|
||||||
* @throws java.net.UnknownHostException If the specified hostname can not be resolved.
|
* @throws java.net.UnknownHostException If the specified hostname can not be resolved.
|
||||||
*/
|
*/
|
||||||
public XPlaneConnect(int port, String xplaneHost, int xplanePort)
|
public XPlaneConnect(String xpHost, int xpPort, int port)
|
||||||
throws java.net.SocketException, java.net.UnknownHostException
|
throws java.net.SocketException, java.net.UnknownHostException
|
||||||
{
|
{
|
||||||
this(port, xplaneHost, xplanePort, 100);
|
this(xpHost, xpPort, port, 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes a new instance of the {@code XPlaneConnect} class using the specified ports, hostname, and timeout.
|
* Initializes a new instance of the {@code XPlaneConnect} class using the specified ports, hostname, and timeout.
|
||||||
*
|
*
|
||||||
* @param port The port on which the X-Plane Connect plugin is sending data.
|
* @param port The port on which the X-Plane Connect plugin is sending data.
|
||||||
* @param xplaneHost The network host on which X-Plane is running.
|
* @param xpHost The network host on which X-Plane is running.
|
||||||
* @param xplanePort The port on which the X-Plane Connect plugin is listening.
|
* @param xpPort The port on which the X-Plane Connect plugin is listening.
|
||||||
* @param timeout The time, in milliseconds, after which read attempts will timeout.
|
* @param timeout The time, in milliseconds, after which read attempts will timeout.
|
||||||
* @throws java.net.SocketException If this instance is unable to bind to the specified port.
|
* @throws java.net.SocketException If this instance is unable to bind to the specified port.
|
||||||
* @throws java.net.UnknownHostException If the specified hostname can not be resolved.
|
* @throws java.net.UnknownHostException If the specified hostname can not be resolved.
|
||||||
*/
|
*/
|
||||||
public XPlaneConnect(int port, String xplaneHost, int xplanePort, int timeout)
|
public XPlaneConnect(String xpHost, int xpPort, int port, int timeout)
|
||||||
throws java.net.SocketException, java.net.UnknownHostException
|
throws java.net.SocketException, java.net.UnknownHostException
|
||||||
{
|
{
|
||||||
this.inSocket = new DatagramSocket(port);
|
this.socket = new DatagramSocket(port);
|
||||||
this.outSocket = new DatagramSocket(50000 + ++clientNum);
|
this.xplaneAddr = InetAddress.getByName(xpHost);
|
||||||
this.xplaneAddr = InetAddress.getByName(xplaneHost);
|
this.xplanePort = xpPort;
|
||||||
this.xplanePort = xplanePort;
|
this.socket.setSoTimeout(timeout);
|
||||||
this.inSocket.setSoTimeout(timeout);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -163,15 +160,10 @@ public class XPlaneConnect implements AutoCloseable
|
|||||||
*/
|
*/
|
||||||
public void close()
|
public void close()
|
||||||
{
|
{
|
||||||
if(inSocket != null)
|
if(socket != null)
|
||||||
{
|
{
|
||||||
inSocket.close();
|
socket.close();
|
||||||
inSocket = null;
|
socket = null;
|
||||||
}
|
|
||||||
if(outSocket != null)
|
|
||||||
{
|
|
||||||
outSocket.close();
|
|
||||||
outSocket = null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -181,13 +173,13 @@ public class XPlaneConnect implements AutoCloseable
|
|||||||
* @return The data send from X-Plane.
|
* @return The data send from X-Plane.
|
||||||
* @throws IOException If the read operation fails
|
* @throws IOException If the read operation fails
|
||||||
*/
|
*/
|
||||||
private byte[] readUDP() throws IOException //TODO: Store data in a class level buffer to account for partial messages
|
private byte[] readUDP() throws IOException
|
||||||
{
|
{
|
||||||
byte[] buffer = new byte[2048];
|
byte[] buffer = new byte[2048];
|
||||||
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
|
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
inSocket.receive(packet);
|
socket.receive(packet);
|
||||||
return Arrays.copyOf(buffer, buffer[4]);
|
return Arrays.copyOf(buffer, buffer[4]);
|
||||||
}
|
}
|
||||||
catch (SocketTimeoutException ex)
|
catch (SocketTimeoutException ex)
|
||||||
@@ -212,7 +204,7 @@ public class XPlaneConnect implements AutoCloseable
|
|||||||
buffer[4] = (byte)buffer.length;
|
buffer[4] = (byte)buffer.length;
|
||||||
|
|
||||||
DatagramPacket packet = new DatagramPacket(buffer, buffer.length, xplaneAddr, xplanePort);
|
DatagramPacket packet = new DatagramPacket(buffer, buffer.length, xplaneAddr, xplanePort);
|
||||||
outSocket.send(packet);
|
socket.send(packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -672,12 +664,12 @@ public class XPlaneConnect implements AutoCloseable
|
|||||||
/**
|
/**
|
||||||
* Sets the port on which the client will receive data from X-Plane.
|
* Sets the port on which the client will receive data from X-Plane.
|
||||||
*
|
*
|
||||||
* @param recvPort The new incoming port number.
|
* @param port The new incoming port number.
|
||||||
* @throws IOException If the command cannnot be sent.
|
* @throws IOException If the command cannnot be sent.
|
||||||
*/
|
*/
|
||||||
public void setCONN(int recvPort) throws IOException
|
public void setCONN(int port) throws IOException
|
||||||
{
|
{
|
||||||
if(recvPort < 0 || recvPort >= 0xFFFF)
|
if(port < 0 || port >= 0xFFFF)
|
||||||
{
|
{
|
||||||
throw new IllegalArgumentException("Invalid port (must be non-negative and less than 65536).");
|
throw new IllegalArgumentException("Invalid port (must be non-negative and less than 65536).");
|
||||||
}
|
}
|
||||||
@@ -685,14 +677,14 @@ public class XPlaneConnect implements AutoCloseable
|
|||||||
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
||||||
os.write("CONN".getBytes(StandardCharsets.UTF_8));
|
os.write("CONN".getBytes(StandardCharsets.UTF_8));
|
||||||
os.write(0xFF); //Placeholder for message length
|
os.write(0xFF); //Placeholder for message length
|
||||||
os.write((byte) recvPort);
|
os.write((byte) port);
|
||||||
os.write((byte) (recvPort >> 8));
|
os.write((byte) (port >> 8));
|
||||||
sendUDP(os.toByteArray());
|
sendUDP(os.toByteArray());
|
||||||
|
|
||||||
int soTimeout = inSocket.getSoTimeout();
|
int soTimeout = socket.getSoTimeout();
|
||||||
inSocket.close();
|
socket.close();
|
||||||
inSocket = new DatagramSocket(recvPort);
|
socket = new DatagramSocket(port);
|
||||||
inSocket.setSoTimeout(soTimeout);
|
socket.setSoTimeout(soTimeout);
|
||||||
readUDP(); // Try to read response
|
readUDP(); // Try to read response
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ public class XPlaneConnectTest
|
|||||||
{
|
{
|
||||||
fail();
|
fail();
|
||||||
}
|
}
|
||||||
try(XPlaneConnect xpc = new XPlaneConnect(49007, "127.0.0.1", 49009))
|
try(XPlaneConnect xpc = new XPlaneConnect("127.0.0.1", 49009, 49007))
|
||||||
{
|
{
|
||||||
assertNotNull(xpc);
|
assertNotNull(xpc);
|
||||||
}
|
}
|
||||||
@@ -39,7 +39,7 @@ public class XPlaneConnectTest
|
|||||||
{
|
{
|
||||||
fail();
|
fail();
|
||||||
}
|
}
|
||||||
try(XPlaneConnect xpc = new XPlaneConnect(49007, "127.0.0.1", 49009, 200))
|
try(XPlaneConnect xpc = new XPlaneConnect("127.0.0.1", 49009, 49007, 200))
|
||||||
{
|
{
|
||||||
assertNotNull(xpc);
|
assertNotNull(xpc);
|
||||||
}
|
}
|
||||||
@@ -50,9 +50,9 @@ public class XPlaneConnectTest
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetRecvPort() throws SocketException
|
public void testGetRecvPort() throws Exception
|
||||||
{
|
{
|
||||||
try(XPlaneConnect xpc = new XPlaneConnect())
|
try(XPlaneConnect xpc = new XPlaneConnect("127.0.0.1", 49009, 49008))
|
||||||
{
|
{
|
||||||
assertEquals(49008, xpc.getRecvPort());
|
assertEquals(49008, xpc.getRecvPort());
|
||||||
}
|
}
|
||||||
@@ -87,11 +87,11 @@ public class XPlaneConnectTest
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void constructorTest_SocketAlreadyBound() throws SocketException
|
public void constructorTest_SocketAlreadyBound() throws Exception
|
||||||
{
|
{
|
||||||
try(XPlaneConnect xpc = new XPlaneConnect())
|
try(XPlaneConnect xpc = new XPlaneConnect("127.0.0.1", 49009, 49008))
|
||||||
{
|
{
|
||||||
try(XPlaneConnect xpc2 = new XPlaneConnect())
|
try(XPlaneConnect xpc2 = new XPlaneConnect("127.0.0.1", 49009, 49008))
|
||||||
{
|
{
|
||||||
fail();
|
fail();
|
||||||
}
|
}
|
||||||
@@ -106,7 +106,7 @@ public class XPlaneConnectTest
|
|||||||
@Test(expected = UnknownHostException.class)
|
@Test(expected = UnknownHostException.class)
|
||||||
public void constructorTest_InvalidHost() throws UnknownHostException
|
public void constructorTest_InvalidHost() throws UnknownHostException
|
||||||
{
|
{
|
||||||
try(XPlaneConnect xpc = new XPlaneConnect(49007, "notarealhost", 49009))
|
try(XPlaneConnect xpc = new XPlaneConnect("notarealhost", 49009, 49007))
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -575,16 +575,10 @@ public class XPlaneConnectTest
|
|||||||
String dref = "sim/cockpit/switches/gear_handle_status";
|
String dref = "sim/cockpit/switches/gear_handle_status";
|
||||||
try(XPlaneConnect xpc = new XPlaneConnect())
|
try(XPlaneConnect xpc = new XPlaneConnect())
|
||||||
{
|
{
|
||||||
int p = xpc.getRecvPort();
|
|
||||||
xpc.setCONN(49055);
|
xpc.setCONN(49055);
|
||||||
assertEquals(49055, xpc.getRecvPort());
|
assertEquals(49055, xpc.getRecvPort());
|
||||||
float[] result = xpc.requestDREF(dref);
|
float[] result = xpc.requestDREF(dref);
|
||||||
assertEquals(1, result.length);
|
assertEquals(1, result.length);
|
||||||
|
|
||||||
xpc.setCONN(p);
|
|
||||||
assertEquals(p, xpc.getRecvPort());
|
|
||||||
result = xpc.requestDREF(dref);
|
|
||||||
assertEquals(1, result.length);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user