Service discovery works. TCP streams established.

This commit is contained in:
2013-11-26 17:57:01 -04:30
parent 47ace0cc11
commit c1916a667e
8 changed files with 249 additions and 1 deletions

View File

@@ -1,5 +1,13 @@
package ve.ucv.ciens.ccg.nxtar; package ve.ucv.ciens.ccg.nxtar;
import ve.ucv.ciens.ccg.nxtar.interfaces.MulticastEnabler;
import ve.ucv.ciens.ccg.nxtar.interfaces.NetworkConnectionListener;
import ve.ucv.ciens.ccg.nxtar.interfaces.Toaster;
import ve.ucv.ciens.ccg.nxtar.network.RobotControlThread;
import ve.ucv.ciens.ccg.nxtar.network.ServiceDiscoveryThread;
import ve.ucv.ciens.ccg.nxtar.network.VideoStreamingThread;
import com.badlogic.gdx.Application;
import com.badlogic.gdx.ApplicationListener; import com.badlogic.gdx.ApplicationListener;
import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL10; import com.badlogic.gdx.graphics.GL10;
@@ -10,17 +18,36 @@ import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.graphics.g2d.SpriteBatch; import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.TextureRegion; import com.badlogic.gdx.graphics.g2d.TextureRegion;
public class Main implements ApplicationListener { public class Main implements ApplicationListener, NetworkConnectionListener {
private static final String TAG = "NXTAR_CORE_MAIN";
private static final String CLASS_NAME = Main.class.getSimpleName();
private OrthographicCamera camera; private OrthographicCamera camera;
private SpriteBatch batch; private SpriteBatch batch;
private Texture texture; private Texture texture;
private Sprite sprite; private Sprite sprite;
private Toaster toaster;
private MulticastEnabler mcastEnabler;
private int connections;
private ServiceDiscoveryThread udpThread;
private VideoStreamingThread videoThread;
private RobotControlThread robotThread;
public Main(Toaster toaster, MulticastEnabler mcastEnabler){
super();
this.toaster = toaster;
this.mcastEnabler = mcastEnabler;
connections = 0;
}
@Override @Override
public void create() { public void create() {
float w = Gdx.graphics.getWidth(); float w = Gdx.graphics.getWidth();
float h = Gdx.graphics.getHeight(); float h = Gdx.graphics.getHeight();
Gdx.app.setLogLevel(Application.LOG_DEBUG);
camera = new OrthographicCamera(1, h/w); camera = new OrthographicCamera(1, h/w);
batch = new SpriteBatch(); batch = new SpriteBatch();
@@ -33,6 +60,16 @@ public class Main implements ApplicationListener {
sprite.setSize(0.9f, 0.9f * sprite.getHeight() / sprite.getWidth()); sprite.setSize(0.9f, 0.9f * sprite.getHeight() / sprite.getWidth());
sprite.setOrigin(sprite.getWidth()/2, sprite.getHeight()/2); sprite.setOrigin(sprite.getWidth()/2, sprite.getHeight()/2);
sprite.setPosition(-sprite.getWidth()/2, -sprite.getHeight()/2); sprite.setPosition(-sprite.getWidth()/2, -sprite.getHeight()/2);
Gdx.app.debug(TAG, CLASS_NAME + ".create() :: Creating network threads");
mcastEnabler.enableMulticast();
udpThread = new ServiceDiscoveryThread();
videoThread = new VideoStreamingThread(toaster);
robotThread = new RobotControlThread(toaster);
udpThread.start();
videoThread.start();
robotThread.start();
} }
@Override @Override
@@ -63,4 +100,15 @@ public class Main implements ApplicationListener {
@Override @Override
public void resume() { public void resume() {
} }
@Override
public synchronized void interfaceConnected(String iface) {
if(iface.compareTo(VideoStreamingThread.THREAD_NAME) == 0 || iface.compareTo(RobotControlThread.THREAD_NAME) == 0)
connections += 1;
if(connections >= 2){
Gdx.app.debug(TAG, CLASS_NAME + ".interfaceConnected() :: Stopping service broadcast.");
udpThread.finish();
mcastEnabler.disableMulticast();
}
}
} }

View File

@@ -0,0 +1,6 @@
package ve.ucv.ciens.ccg.nxtar.interfaces;
public interface MulticastEnabler {
public void enableMulticast();
public void disableMulticast();
}

View File

@@ -0,0 +1,5 @@
package ve.ucv.ciens.ccg.nxtar.interfaces;
public interface NetworkConnectionListener {
public void interfaceConnected(String iface);
}

View File

@@ -0,0 +1,6 @@
package ve.ucv.ciens.ccg.nxtar.interfaces;
public interface Toaster {
public void showShortToast(String msg);
public void showLongToast(String msg);
}

View File

@@ -0,0 +1,52 @@
package ve.ucv.ciens.ccg.nxtar.network;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import ve.ucv.ciens.ccg.nxtar.interfaces.NetworkConnectionListener;
import ve.ucv.ciens.ccg.nxtar.interfaces.Toaster;
import ve.ucv.ciens.ccg.nxtar.utils.ProjectConstants;
import com.badlogic.gdx.Gdx;
public class RobotControlThread extends Thread {
public static final String THREAD_NAME = "RobotControlThread";
private static final String TAG = "NXTAR_CORE_ROBOTTHREAD";
private static final String CLASS_NAME = RobotControlThread.class.getSimpleName();
private NetworkConnectionListener netListener;
private ServerSocket server;
private Socket client;
private Toaster toaster;
public RobotControlThread(Toaster toaster){
super(THREAD_NAME);
this.toaster = toaster;
netListener = null;
try{
server = new ServerSocket(ProjectConstants.SERVER_TCP_PORT_2);
}catch(IOException io){
Gdx.app.error(TAG, CLASS_NAME + ".RobotControlThread() :: Error creating server: " + io.getMessage(), io);
}
}
public void addNetworkConnectionListener(NetworkConnectionListener listener){
netListener = listener;
}
@Override
public void run(){
try{
client = server.accept();
if(netListener != null)
netListener.interfaceConnected(THREAD_NAME);
toaster.showShortToast("Client connected to RobotControlThread");
client.close();
}catch(IOException io){
Gdx.app.error(TAG, CLASS_NAME + ".run() :: Error accepting client: " + io.getMessage(), io);
}
}
}

View File

@@ -0,0 +1,69 @@
package ve.ucv.ciens.ccg.nxtar.network;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.UnknownHostException;
import ve.ucv.ciens.ccg.nxtar.utils.ProjectConstants;
import com.badlogic.gdx.Gdx;
public class ServiceDiscoveryThread extends Thread {
public static final String THREAD_NAME = "ServiceDiscoveryThread";
private static final String TAG = "NXTAR_CORE_UDPTHREAD";
private static final String CLASS_NAME = ServiceDiscoveryThread.class.getSimpleName();
private Object semaphore;
private boolean done;
private DatagramSocket udpServer;
private InetAddress group;
public ServiceDiscoveryThread(){
super(THREAD_NAME);
done = false;
semaphore = new Object();
try{
group = InetAddress.getByName(ProjectConstants.MULTICAST_ADDRESS);
}catch(UnknownHostException uh){ }
Gdx.app.debug(TAG, CLASS_NAME + ".ServiceDiscoveryThread() :: Creating multicast server.");
try{
udpServer = new DatagramSocket(ProjectConstants.SERVER_UDP_PORT);
}catch(IOException io){
Gdx.app.error(TAG, CLASS_NAME + ".ServiceDiscoveryThread() :: Error creating UDP socket: " + io.getMessage(), io);
}
Gdx.app.debug(TAG, CLASS_NAME + ".ServiceDiscoveryThread() :: Multicast server created.");
}
@Override
public void run(){
byte[] buffer = (new String("NxtAR server here!")).getBytes();
try{
while(true){
synchronized(semaphore){
if(done){
udpServer.close();
break;
}
}
//Gdx.app.debug(TAG, CLASS_NAME + ".ServiceDiscoveryThread() :: Resending packet");
DatagramPacket packet = new DatagramPacket(buffer, buffer.length, group, ProjectConstants.SERVER_UDP_PORT);
udpServer.send(packet);
//Gdx.app.debug(TAG, CLASS_NAME + ".ServiceDiscoveryThread() :: Packet sent");
try{ sleep(250L); }catch(InterruptedException ie){ }
}
}catch(IOException io){
Gdx.app.debug(TAG, CLASS_NAME + ".ServiceDiscoveryThread() :: Error sending packet: " + io.getMessage(), io);
}
}
public void finish(){
synchronized(semaphore){
done = true;
}
}
}

View File

@@ -0,0 +1,52 @@
package ve.ucv.ciens.ccg.nxtar.network;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import ve.ucv.ciens.ccg.nxtar.interfaces.NetworkConnectionListener;
import ve.ucv.ciens.ccg.nxtar.interfaces.Toaster;
import ve.ucv.ciens.ccg.nxtar.utils.ProjectConstants;
import com.badlogic.gdx.Gdx;
public class VideoStreamingThread extends Thread {
public static final String THREAD_NAME = "VideoStreamingThread";
private static final String TAG = "NXTAR_CORE_VIDEOTHREAD";
private static final String CLASS_NAME = VideoStreamingThread.class.getSimpleName();
private NetworkConnectionListener netListener;
private ServerSocket server;
private Socket client;
private Toaster toaster;
public VideoStreamingThread(Toaster toaster){
super(THREAD_NAME);
this.toaster = toaster;
netListener = null;
try{
server = new ServerSocket(ProjectConstants.SERVER_TCP_PORT_1);
}catch(IOException io){
Gdx.app.error(TAG, CLASS_NAME + ".VideoStreamingThread() :: Error creating server: " + io.getMessage(), io);
}
}
public void addNetworkConnectionListener(NetworkConnectionListener listener){
netListener = listener;
}
@Override
public void run(){
try{
client = server.accept();
if(netListener != null)
netListener.interfaceConnected(THREAD_NAME);
toaster.showShortToast("Client connected to VideoStreamingThread");
client.close();
}catch(IOException io){
Gdx.app.error(TAG, CLASS_NAME + ".run() :: Error accepting client: " + io.getMessage(), io);
}
}
}

View File

@@ -0,0 +1,10 @@
package ve.ucv.ciens.ccg.nxtar.utils;
public abstract class ProjectConstants {
public static final int SERVER_UDP_PORT = 8889;
public static final int SERVER_TCP_PORT_1 = 9989;
public static final int SERVER_TCP_PORT_2 = 9990;
public static final String MULTICAST_ADDRESS = "230.0.0.1";
public static final boolean DEBUG = true;
}