package org.squidy.nodes.reactivision.remote.control;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousCloseException;
import java.nio.channels.ServerSocketChannel;
import org.squidy.nodes.ReacTIVision;
import org.squidy.nodes.reactivision.remote.Util;
public class ControlServer implements Runnable{
private ServerSocketChannel serverSocketChannel;
private ControlSocket controlSocket;
private int serverPort;
private boolean connected;
private boolean running = false;
private ReacTIVision reacTIVisionInstance;
public ControlServer(ReacTIVision callingNode, int port) {
reacTIVisionInstance = callingNode;
serverPort = port;
connected = false;
}
public void run() {
running = true;
while (running) {
try {
controlSocket = new ControlSocket(serverSocketChannel.accept());
connected = true;
//set FiducialSet, if necessary
/*
final FiducialSet remoteSet = getFiducialSet();//TODO required restart of ReavTIVision causes problems
if (remoteSet != null && !remoteSet.equals(reacTIVisionInstance.getFiducialSet())) {
setFiducialSet(reacTIVisionInstance.getFiducialSet());
continue;
}
*/
//fix: change value of ReacTIVision node
reacTIVisionInstance.refreshFiducialSet(getFiducialSet());
setAllCameraValues();
} catch (AsynchronousCloseException e) {
//do nothing
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* Returns <code>true</code> if the ControlServer could be initialized and is,
* now waiting for connections on the specified port.
*
* @return
*/
public boolean start() {
// Create a server socket in blocking mode and check for connections
try {
serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.configureBlocking(true);
serverSocketChannel.socket().bind(new InetSocketAddress(serverPort));
} catch (IOException e) {
e.printStackTrace();
return false;
}
//wait for connection attempt
(new Thread(this)).start();
return true;
}
public synchronized float[] getGrid() {
ControlMessage request = new ControlMessage(OpCode.GET_GRID);
if (!sendMessage(request))
return null;
ControlMessage response = receiveMessage();
if (response == null)
return null;
if (!(response.getOpCode().equals(OpCode.SEND_GRID) && response.getPayloadLength() == 7*9*4*2))
return null;
final float[] grid = Util.byteArrayToFloatArray(response.getPayload().array());
return grid;
}
public synchronized boolean setGrid(float[] grid) {
ByteBuffer buffer = ByteBuffer.allocate(grid.length * 4);
for (float f : grid)
buffer.putFloat(f);
ControlMessage message = new ControlMessage(OpCode.SET_GRID, buffer.array());
return sendMessage(message);
}
public synchronized boolean startCameraFeed() {
ControlMessage message = new ControlMessage(OpCode.START_CAMERA_FEED);
return sendMessage(message);
}
public synchronized boolean stopCameraFeed() {
ControlMessage message = new ControlMessage(OpCode.STOP_CAMERA_FEED);
return sendMessage(message);
}
public synchronized CameraSettingsContainer getCameraSettings() {
ControlMessage message = new ControlMessage(OpCode.GET_CAMERA_SETTINGS);
if (!sendMessage(message))
return null;
message = receiveMessage();
if (message == null || message.getOpCode() != OpCode.SEND_CAMERA_SETTINGS)
return null;
else {
final ByteBuffer buffer = message.getPayload();
return CameraSettingsContainer.deserialize(buffer);
}
}
public synchronized boolean setFramerate(float framerate) {
final ControlMessage message = ControlMessage
.createSettingsControlMessage(OpCode.SET_CAMERA_SETTINGS_FRAMERATE, framerate);
return sendMessage(message);
}
public synchronized boolean setExposureTime(float exposureTime) {
final ControlMessage message = ControlMessage
.createSettingsControlMessage(OpCode.SET_CAMERA_SETTINGS_EXPOSURE_TIME, exposureTime);
return sendMessage(message);
}
public synchronized boolean setPixelClock(int pixelClock) {
final ControlMessage message = ControlMessage
.createSettingsControlMessage(OpCode.SET_CAMERA_SETTINGS_PIXEL_CLOCK, pixelClock);
return sendMessage(message);
}
public synchronized boolean setHardwareGain(int hardwareGain) {
final ControlMessage message = ControlMessage
.createSettingsControlMessage(OpCode.SET_CAMERA_SETTINGS_HARDWARE_GAIN, hardwareGain);
return sendMessage(message);
}
public synchronized boolean setEdgeEnhancement(int edgeEnhancement) {
final ControlMessage message = ControlMessage
.createSettingsControlMessage(OpCode.SET_CAMERA_SETTINGS_EDGE_ENHANCEMENT, edgeEnhancement);
return sendMessage(message);
}
public synchronized boolean setGamma(int gamma) {
final ControlMessage message = ControlMessage
.createSettingsControlMessage(OpCode.SET_CAMERA_SETTINGS_GAMMA, gamma);
return sendMessage(message);
}
public synchronized FiducialSet getFiducialSet() {
ControlMessage message = new ControlMessage(OpCode.GET_FIDUCIAL_SET);
if (!sendMessage(message))
return null;
message = receiveMessage();
if (message == null)
return null;
final int fiducialSetID = Util.readFourByteInt(message.getPayload(), 0);
return FiducialSet.valueOf(fiducialSetID);
}
public synchronized boolean setFiducialSet(FiducialSet fiducialSet) {
final ControlMessage message = ControlMessage.createSetFiducialSetControlMessage(fiducialSet);
return sendMessage(message);
}
private void setAllCameraValues() {
//transfer desired values to ReacTIVision program
setPixelClock(reacTIVisionInstance.getPixelClock());
setExposureTime((float)reacTIVisionInstance.getExposureTime());
setFramerate((float)reacTIVisionInstance.getFramerate());
setHardwareGain(reacTIVisionInstance.getHardwareGain());
setEdgeEnhancement(reacTIVisionInstance.getEdgeEnhancement());
setGamma(reacTIVisionInstance.getGamma());
//receive and set actual values
reacTIVisionInstance.refreshCameraSettings();
}
private boolean sendMessage(ControlMessage message) {
if (!connected)
return false;
try {
controlSocket.send(message);
//System.out.println("Sending this ControlMessage:\n " + message.toString());
} catch (IOException e) {
e.printStackTrace();
restart();
return false;
}
return true;
}
private ControlMessage receiveMessage() {
try {
ControlMessage message = controlSocket.receive();
//System.out.println("Receiving this ControlMessage:\n " + message.toString());
return message;
} catch (IOException e) {
e.printStackTrace();
restart();
}
return null;
}
private void restart() {
connected = false;
(new Thread(this)).start();
}
public void stop() {
running = false;
connected = false;
if (controlSocket != null)
controlSocket.close();
if (serverSocketChannel != null)
try {
serverSocketChannel.close();
} catch (IOException e) {}
}
}