package org.signalml.app.worker.monitor;
import static org.signalml.app.util.i18n.SvarogI18n._;
import static org.signalml.app.util.i18n.SvarogI18n._R;
import java.awt.Container;
import java.net.InetSocketAddress;
import java.util.StringTokenizer;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import multiplexer.jmx.client.JmxClient;
import org.apache.log4j.Logger;
import org.jboss.netty.channel.ChannelFuture;
import org.signalml.app.model.document.opensignal.ExperimentDescriptor;
import org.signalml.app.model.document.opensignal.elements.ExperimentStatus;
import org.signalml.app.worker.SwingWorkerWithBusyDialog;
import org.signalml.app.worker.monitor.exceptions.OpenbciCommunicationException;
import org.signalml.app.worker.monitor.messages.GetExperimentContactRequest;
import org.signalml.app.worker.monitor.messages.GetExperimentContactResponse;
import org.signalml.app.worker.monitor.messages.JoinExperimentRequest;
import org.signalml.app.worker.monitor.messages.MessageType;
import org.signalml.app.worker.monitor.messages.RequestErrorResponse;
import org.signalml.app.worker.monitor.messages.RequestOKResponse;
import org.signalml.app.worker.monitor.messages.StartEEGSignalRequest;
import org.signalml.app.worker.monitor.messages.StartEEGSignalResponse;
import org.signalml.app.worker.monitor.messages.parsing.MessageParser;
import org.signalml.multiplexer.protocol.SvarogConstants;
public class ConnectToExperimentWorker extends SwingWorkerWithBusyDialog<Void, Void> {
public static final int TIMEOUT_MILIS = 500;
public static final int TRYOUT_COUNT = 20;
private static Logger logger = Logger.getLogger(ConnectToExperimentWorker.class);
private ExperimentDescriptor experimentDescriptor;
private String multiplexerAddress;
private int multiplexerPort;
private InetSocketAddress multiplexerSocket;
public ConnectToExperimentWorker(Container parentContainer, ExperimentDescriptor experimentDescriptor) {
super(parentContainer);
this.experimentDescriptor = experimentDescriptor;
getBusyDialog().setText(_("Connecting to the experiment"));
getBusyDialog().setCancellable(false);
}
public ExperimentDescriptor getExperimentDescriptor() {
return experimentDescriptor;
}
@Override
protected Void doInBackground() throws Exception {
showBusyDialog();
if (experimentDescriptor.getStatus() == ExperimentStatus.NEW) {
startNewExperiment();
}
sendJoinExperimentRequest();
connectToMultiplexer();
experimentDescriptor.setConnected(true);
return null;
}
protected void startNewExperiment() throws OpenbciCommunicationException {
StartEEGSignalRequest request = new StartEEGSignalRequest(experimentDescriptor);
StartEEGSignalResponse response = (StartEEGSignalResponse) Helper.sendRequestAndParseResponse(request,
Helper.getOpenBCIIpAddress(),
Helper.getOpenbciPort(),
MessageType.START_EEG_SIGNAL_RESPONSE);
experimentDescriptor.setId(response.getSender());
getExperimentContact();
}
protected void getExperimentContact() throws OpenbciCommunicationException {
GetExperimentContactRequest request = new GetExperimentContactRequest(experimentDescriptor.getId());
GetExperimentContactResponse response = (GetExperimentContactResponse) Helper.sendRequestAndParseResponse(
request,
Helper.getOpenBCIIpAddress(),
Helper.getOpenbciPort(),
MessageType.GET_EXPERIMENT_CONTACT_RESPONSE);
experimentDescriptor.setExperimentIPAddress(response.getExperimentIPAddress());
experimentDescriptor.setExperimentPort(response.getExperimentPort());
}
protected void sendJoinExperimentRequest() throws OpenbciCommunicationException {
JoinExperimentRequest request = new JoinExperimentRequest(experimentDescriptor);
RequestOKResponse response = null;
MessageType responseType = null;
String responseString = null;
for (int i = 0; i < TRYOUT_COUNT; i++) {
responseString = Helper.sendRequest(request,
experimentDescriptor.getExperimentIPAddress(),
experimentDescriptor.getExperimentPort(),
Helper.DEFAULT_RECEIVE_TIMEOUT);
responseType = MessageType.parseMessageTypeFromResponse(responseString);
if (responseType != MessageType.REQUEST_ERROR_RESPONSE) {
response = (RequestOKResponse) MessageParser.parseMessageFromJSON(responseString, MessageType.REQUEST_OK_RESPONSE);
break;
} else {
logger.warn("Error while connecting to experiment, retrying");
try {
Thread.sleep(TIMEOUT_MILIS);
} catch (InterruptedException e) {
logger.error("", e);
}
}
}
if (response == null) {
throw new OpenbciCommunicationException(_R("There was an error while joinging to the experiment."));
} else if (responseType == MessageType.REQUEST_ERROR_RESPONSE) {
RequestErrorResponse errorResponse = (RequestErrorResponse) MessageParser.parseMessageFromJSON(responseString, MessageType.REQUEST_OK_RESPONSE);
throw new OpenbciCommunicationException(_R("There was an error while joinging to the experiment ({0}).", errorResponse.getErrorCode()));
}
String mxAddr = (String) response.getParams().get("mx_addr");
StringTokenizer tokenizer = new StringTokenizer(mxAddr, ":");
multiplexerAddress = tokenizer.nextToken();
multiplexerPort = Integer.parseInt(tokenizer.nextToken());
}
protected void connectToMultiplexer() {
JmxClient jmxClient = new JmxClient(SvarogConstants.PeerTypes.STREAM_RECEIVER);
experimentDescriptor.setJmxClient(jmxClient);
multiplexerSocket = new InetSocketAddress(multiplexerAddress, multiplexerPort);
ChannelFuture connectFuture = null;
connectFuture = jmxClient.asyncConnect(multiplexerSocket);
logger.debug("Connecting to JMX");
int i = 0;
while (!isCancelled() && i < TRYOUT_COUNT) {
i++;
try {
Thread.sleep(TIMEOUT_MILIS);
} catch (InterruptedException e1) {
}
if ((connectFuture.isDone())) {
break;
} else
logger.debug("Connection to JMX failed, retrying");
}
}
@Override
protected void done() {
super.done();
boolean shouldDisconnect = false;
try {
get();
} catch (CancellationException e) {
shouldDisconnect = true;
logger.debug("Connecting to experiment cancelled");
} catch (InterruptedException e) {
shouldDisconnect = true;
logger.error("", e);
} catch (ExecutionException e) {
shouldDisconnect = true;
if (e.getCause() instanceof OpenbciCommunicationException) {
OpenbciCommunicationException exception = (OpenbciCommunicationException) e.getCause();
exception.showErrorDialog(_("An error occurred while connecting to experiment"));
}
else {
logger.error("", e);
}
}
if (shouldDisconnect) {
DisconnectFromExperimentWorker worker = new DisconnectFromExperimentWorker(experimentDescriptor);
worker.execute();
}
}
}