00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 package com.github.rosjava.android_remocons.common_tools.rocon;
00019
00020 import android.os.AsyncTask;
00021 import android.util.Log;
00022
00023 import com.github.rosjava.android_remocons.common_tools.master.MasterId;
00024
00025 import org.ros.address.InetAddressFactory;
00026 import org.ros.android.NodeMainExecutorService;
00027 import org.ros.exception.RosRuntimeException;
00028 import org.ros.exception.ServiceNotFoundException;
00029 import org.ros.internal.node.client.ParameterClient;
00030 import org.ros.internal.node.server.NodeIdentifier;
00031 import org.ros.namespace.GraphName;
00032 import org.ros.node.AbstractNodeMain;
00033 import org.ros.node.ConnectedNode;
00034 import org.ros.node.Node;
00035 import org.ros.node.NodeConfiguration;
00036 import org.ros.node.service.ServiceClient;
00037 import org.ros.node.service.ServiceResponseListener;
00038
00039 import java.net.URI;
00040 import java.net.URISyntaxException;
00041
00042 import rocon_interaction_msgs.GetInteraction;
00043 import rocon_interaction_msgs.GetInteractionRequest;
00044 import rocon_interaction_msgs.GetInteractionResponse;
00045 import rocon_interaction_msgs.GetInteractions;
00046 import rocon_interaction_msgs.GetInteractionsRequest;
00047 import rocon_interaction_msgs.GetInteractionsResponse;
00048 import rocon_interaction_msgs.RequestInteraction;
00049 import rocon_interaction_msgs.RequestInteractionRequest;
00050 import rocon_interaction_msgs.RequestInteractionResponse;
00051
00052 import static com.github.rosjava.android_remocons.common_tools.rocon.Constants.ANDROID_PLATFORM_INFO;
00053
00074 public class InteractionsManager extends AbstractNodeMain {
00075 public interface FailureHandler {
00079 void handleFailure(String reason);
00080 }
00081
00082 public enum Action {
00083 NONE, GET_INTERACTIONS_FOR_ROLE, GET_INTERACTION_INFO, REQUEST_INTERACTION_USE
00084 };
00085
00086 private String role;
00087 private String interactionsNamespace;
00088 private Action action = Action.NONE;
00089 private rocon_interaction_msgs.Interaction app;
00090 private int app_hash;
00091 private String remocon_name;
00092 private ConnectNodeThread connectThread;
00093 private ConnectedNode connectedNode;
00094 private NodeMainExecutorService nodeMainExecutorService;
00095 private FailureHandler failureCallback;
00096 private ServiceResponseListener<RequestInteractionResponse> requestServiceResponseListener;
00097 private ServiceResponseListener<GetInteractionsResponse> getAppsServiceResponseListener;
00098 private ServiceResponseListener<GetInteractionResponse> appInfoServiceResponseListener;
00099
00100
00101 public InteractionsManager(FailureHandler failureCallback) {
00102
00103 this.failureCallback = failureCallback;
00104 }
00105
00113 public void init(String interactionsNamespace) {
00114 this.interactionsNamespace = interactionsNamespace;
00115 }
00116
00117 public void setRemoconName(String remocon_name) {
00118 this.remocon_name = remocon_name;
00119 }
00120
00121
00122 public void setupRequestService(ServiceResponseListener<RequestInteractionResponse> serviceResponseListener) {
00123 this.requestServiceResponseListener = serviceResponseListener;
00124 }
00125
00126 public void setupGetInteractionsService(ServiceResponseListener<GetInteractionsResponse> serviceResponseListener) {
00127 this.getAppsServiceResponseListener = serviceResponseListener;
00128 }
00129
00130 public void setupAppInfoService(ServiceResponseListener<GetInteractionResponse> serviceResponseListener) {
00131 this.appInfoServiceResponseListener = serviceResponseListener;
00132 }
00133
00134 @Override
00135 protected void finalize() throws Throwable {
00136 super.finalize();
00137 shutdown();
00138 }
00139
00140 public void shutdown() {
00141 if (nodeMainExecutorService != null)
00142 nodeMainExecutorService.shutdownNodeMain(this);
00143 else
00144 Log.i("InteractionsMng", "Shutting down an uninitialized apps manager");
00145 }
00146
00147 public void getAppsForRole(final MasterId masterId, final String role) {
00148 this.action = Action.GET_INTERACTIONS_FOR_ROLE;
00149 this.role = role;
00150
00151
00152
00153 if (this.connectedNode == null) {
00154 Log.i("InteractionsMng", "First action requested (" + this.action + "). Starting node...");
00155 new ConnectNodeThread(masterId).start();
00156 }
00157 else {
00158
00159
00160 new AsyncTask<Void, Void, Void>() {
00161 @Override
00162 protected Void doInBackground(Void... params) {
00163 getAppsForRole();
00164 return null;
00165 }
00166 }.execute();
00167 }
00168 }
00169
00170 public void requestAppUse(final MasterId masterId, final String role, final rocon_interaction_msgs.Interaction app) {
00171 this.action = Action.REQUEST_INTERACTION_USE;
00172 this.role = role;
00173 this.app = app;
00174 this.app_hash = app.getHash();
00175
00176
00177
00178 if (this.connectedNode == null) {
00179 Log.i("InteractionsMng", "First action requested (" + this.action + "). Starting node...");
00180 new ConnectNodeThread(masterId).start();
00181 }
00182 else {
00183
00184
00185 new AsyncTask<Void, Void, Void>() {
00186 @Override
00187 protected Void doInBackground(Void... params) {
00188 requestAppUse();
00189 return null;
00190 }
00191 }.execute();
00192 }
00193 }
00194
00203 public void getAppInfo(final MasterId masterId, final int hash) {
00204 this.action = Action.GET_INTERACTION_INFO;
00205 this.app_hash = hash;
00206
00207
00208
00209 if (this.connectedNode == null) {
00210 Log.i("InteractionsMng", "First action requested (" + this.action + "). Starting node...");
00211 new ConnectNodeThread(masterId).start();
00212 }
00213 else {
00214
00215
00216 new AsyncTask<Void, Void, Void>() {
00217 @Override
00218 protected Void doInBackground(Void... params) {
00219 getAppInfo();
00220 return null;
00221 }
00222 }.execute();
00223 }
00224 }
00225
00226 private void getAppsForRole() {
00227
00228 ServiceClient<GetInteractionsRequest, GetInteractionsResponse> srvClient;
00229 String serviceName = this.interactionsNamespace + "/get_interactions";
00230
00231 try {
00232 Log.i("InteractionsMng", "List interactions service client created [" + serviceName + "]");
00233 srvClient = connectedNode.newServiceClient(serviceName, GetInteractions._TYPE);
00234 } catch (ServiceNotFoundException e) {
00235 Log.i("InteractionsMng", "List interactions service not found [" + serviceName + "]");
00236 throw new RosRuntimeException(e);
00237 }
00238 final GetInteractionsRequest request = srvClient.newMessage();
00239
00240 request.getRoles().add(role);
00241 request.setUri(ANDROID_PLATFORM_INFO.getUri());
00242
00243 srvClient.call(request, getAppsServiceResponseListener);
00244 Log.i("InteractionsMng", "List interactions service call done [" + serviceName + "]");
00245 }
00246
00247 private void requestAppUse() {
00248
00249 ServiceClient<RequestInteractionRequest, RequestInteractionResponse> srvClient;
00250 String serviceName = this.interactionsNamespace + "/request_interaction";
00251 try {
00252 Log.i("InteractionsMng", "Request app service client created [" + serviceName + "]");
00253 srvClient = connectedNode.newServiceClient(serviceName, RequestInteraction._TYPE);
00254 } catch (ServiceNotFoundException e) {
00255 Log.i("InteractionsMng", "Request app service not found [" + serviceName + "]");
00256 throw new RosRuntimeException(e);
00257 }
00258 final RequestInteractionRequest request = srvClient.newMessage();
00259
00260 request.setRemocon(this.remocon_name);
00261 request.setHash(this.app.getHash());
00262
00263 srvClient.call(request, requestServiceResponseListener);
00264 Log.i("InteractionsMng", "Request app service call done [" + serviceName + "]");
00265 }
00266
00267 private void getAppInfo() {
00268
00269 ServiceClient<GetInteractionRequest, GetInteractionResponse> srvClient;
00270 String serviceName = this.interactionsNamespace + "/get_interaction";
00271 try {
00272 Log.i("InteractionsMng", "Get app info service client created [" + serviceName + "]");
00273 srvClient = connectedNode.newServiceClient(serviceName, GetInteraction._TYPE);
00274 } catch (ServiceNotFoundException e) {
00275 Log.i("InteractionsMng", "Get app info not found [" + serviceName + "]");
00276 throw new RosRuntimeException(e);
00277 }
00278 final GetInteractionRequest request = srvClient.newMessage();
00279 request.setHash(this.app_hash);
00280
00281 srvClient.call(request, appInfoServiceResponseListener);
00282 Log.i("InteractionsMng", "Get app info service call done [" + serviceName + "]");
00283 }
00284
00289 private class ConnectNodeThread extends Thread {
00290 private MasterId masterId;
00291
00292 public ConnectNodeThread(MasterId masterId) {
00293 this.masterId = masterId;
00294 setDaemon(true);
00295 setUncaughtExceptionHandler(new UncaughtExceptionHandler() {
00296 @Override
00297 public void uncaughtException(Thread thread, Throwable ex) {
00298 failureCallback.handleFailure("exception: " + ex.getMessage());
00299 }
00300 });
00301 }
00302
00303 @Override
00304 public void run() {
00305 try {
00306 URI concertUri = new URI(masterId.getMasterUri());
00307
00308
00309
00310
00311
00312
00313 ParameterClient paramClient = new ParameterClient(
00314 NodeIdentifier.forNameAndUri("/concert_checker", concertUri.toString()), concertUri);
00315 String name = (String) paramClient.getParam(GraphName.of("/rosversion")).getResult();
00316 Log.i("Remocon", "Concert " + name + " found; retrieve additional information");
00317
00318 nodeMainExecutorService = new NodeMainExecutorService();
00319 NodeConfiguration nodeConfiguration = NodeConfiguration.newPublic(
00320 InetAddressFactory.newNonLoopback().getHostAddress(), concertUri);
00321 nodeMainExecutorService.execute(InteractionsManager.this, nodeConfiguration.setNodeName("apps_manager_node"));
00322
00323 } catch (URISyntaxException e) {
00324 Log.i("InteractionsMng", "invalid concert URI [" + masterId.getMasterUri() + "][" + e.toString() + "]");
00325 failureCallback.handleFailure("invalid concert URI");
00326 } catch (RuntimeException e) {
00327
00328 Log.i("InteractionsMng", "could not find concert [" + masterId.getMasterUri() + "][" + e.toString() + "]");
00329 failureCallback.handleFailure(e.toString());
00330 } catch (Throwable e) {
00331 Log.i("InteractionsMng", "exception while creating node in concert checker for URI " + masterId.getMasterUri(), e);
00332 failureCallback.handleFailure(e.toString());
00333 }
00334 }
00335 }
00336
00337 @Override
00338 public GraphName getDefaultNodeName() {
00339 return null;
00340 }
00341
00347 @Override
00348 public void onStart(final ConnectedNode connectedNode) {
00349 if (this.connectedNode != null) {
00350 Log.e("InteractionsMng", "App manager re-started before previous shutdown; ignoring...");
00351 return;
00352 }
00353
00354 this.connectedNode = connectedNode;
00355
00356 Log.i("InteractionsMng", "onStart() - " + action);
00357
00358 switch (action) {
00359 case NONE:
00360 Log.i("InteractionsMng", "Node started without specifying an action");
00361 break;
00362 case REQUEST_INTERACTION_USE:
00363 requestAppUse();
00364 break;
00365 case GET_INTERACTIONS_FOR_ROLE:
00366 getAppsForRole();
00367 break;
00368 case GET_INTERACTION_INFO:
00369 getAppInfo();
00370 break;
00371 default:
00372 Log.i("InteractionsMng", "Unrecognised action requested: " + action);
00373 }
00374
00375 Log.i("InteractionsMng", "Done");
00376 }
00377
00378 @Override
00379 public void onShutdown(Node node) {
00380 Log.i("InteractionsMng", "Shutdown connected node...");
00381 super.onShutdown(node);
00382
00383
00384 this.connectedNode = null;
00385 Log.i("InteractionsMng", "Done; shutdown apps manager node main");
00386 }
00387
00388 @Override
00389 public void onShutdownComplete(Node node) {
00390 super.onShutdownComplete(node);
00391 }
00392
00393 @Override
00394 public void onError(Node node, Throwable throwable) {
00395 super.onError(node, throwable);
00396
00397 Log.e("InteractionsMng", node.getName().toString() + " node error: " + throwable.getMessage());
00398 failureCallback.handleFailure(node.getName().toString() + " node error: " + throwable.toString());
00399 }
00400 }