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 AppsManager 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 ConnectNodeThread connectThread;
00092 private ConnectedNode connectedNode;
00093 private NodeMainExecutorService nodeMainExecutorService;
00094 private FailureHandler failureCallback;
00095 private ServiceResponseListener<RequestInteractionResponse> requestServiceResponseListener;
00096 private ServiceResponseListener<GetInteractionsResponse> getAppsServiceResponseListener;
00097 private ServiceResponseListener<GetInteractionResponse> appInfoServiceResponseListener;
00098
00099
00100 public AppsManager(FailureHandler failureCallback) {
00101
00102 this.failureCallback = failureCallback;
00103 }
00104
00112 public void init(String interactionsNamespace) {
00113 this.interactionsNamespace = interactionsNamespace;
00114 }
00115
00116 public void setupRequestService(ServiceResponseListener<RequestInteractionResponse> serviceResponseListener) {
00117 this.requestServiceResponseListener = serviceResponseListener;
00118 }
00119
00120 public void setupGetInteractionsService(ServiceResponseListener<GetInteractionsResponse> serviceResponseListener) {
00121 this.getAppsServiceResponseListener = serviceResponseListener;
00122 }
00123
00124 public void setupAppInfoService(ServiceResponseListener<GetInteractionResponse> serviceResponseListener) {
00125 this.appInfoServiceResponseListener = serviceResponseListener;
00126 }
00127
00128 @Override
00129 protected void finalize() throws Throwable {
00130 super.finalize();
00131 shutdown();
00132 }
00133
00134 public void shutdown() {
00135 if (nodeMainExecutorService != null)
00136 nodeMainExecutorService.shutdownNodeMain(this);
00137 else
00138 Log.w("AppsMng", "Shutting down an uninitialized apps manager");
00139 }
00140
00141 public void getAppsForRole(final MasterId masterId, final String role) {
00142 this.action = Action.GET_INTERACTIONS_FOR_ROLE;
00143 this.role = role;
00144
00145
00146
00147 if (this.connectedNode == null) {
00148 Log.d("AppsMng", "First action requested (" + this.action + "). Starting node...");
00149 new ConnectNodeThread(masterId).start();
00150 }
00151 else {
00152
00153
00154 new AsyncTask<Void, Void, Void>() {
00155 @Override
00156 protected Void doInBackground(Void... params) {
00157 getAppsForRole();
00158 return null;
00159 }
00160 }.execute();
00161 }
00162 }
00163
00164 public void requestAppUse(final MasterId masterId, final String role, final rocon_interaction_msgs.Interaction app) {
00165 this.action = Action.REQUEST_INTERACTION_USE;
00166 this.role = role;
00167 this.app = app;
00168 this.app_hash = app.getHash();
00169
00170
00171
00172 if (this.connectedNode == null) {
00173 Log.d("AppsMng", "First action requested (" + this.action + "). Starting node...");
00174 new ConnectNodeThread(masterId).start();
00175 }
00176 else {
00177
00178
00179 new AsyncTask<Void, Void, Void>() {
00180 @Override
00181 protected Void doInBackground(Void... params) {
00182 requestAppUse();
00183 return null;
00184 }
00185 }.execute();
00186 }
00187 }
00188
00197 public void getAppInfo(final MasterId masterId, final int hash) {
00198 this.action = Action.GET_INTERACTION_INFO;
00199 this.app_hash = hash;
00200
00201
00202
00203 if (this.connectedNode == null) {
00204 Log.d("AppsMng", "First action requested (" + this.action + "). Starting node...");
00205 new ConnectNodeThread(masterId).start();
00206 }
00207 else {
00208
00209
00210 new AsyncTask<Void, Void, Void>() {
00211 @Override
00212 protected Void doInBackground(Void... params) {
00213 getAppInfo();
00214 return null;
00215 }
00216 }.execute();
00217 }
00218 }
00219
00220 private void getAppsForRole() {
00221
00222 ServiceClient<GetInteractionsRequest, GetInteractionsResponse> srvClient;
00223 String serviceName = this.interactionsNamespace + "/get_interactions";
00224
00225 try {
00226 Log.d("AppsMng", "List apps service client created [" + serviceName + "]");
00227 srvClient = connectedNode.newServiceClient(serviceName, GetInteractions._TYPE);
00228 } catch (ServiceNotFoundException e) {
00229 Log.w("AppsMng", "List apps service not found [" + serviceName + "]");
00230 throw new RosRuntimeException(e);
00231 }
00232 final GetInteractionsRequest request = srvClient.newMessage();
00233
00234 request.getRoles().add(role);
00235 request.setUri(ANDROID_PLATFORM_INFO.getUri());
00236
00237 srvClient.call(request, getAppsServiceResponseListener);
00238 Log.d("AppsMng", "List apps service call done [" + serviceName + "]");
00239 }
00240
00241 private void requestAppUse() {
00242
00243 ServiceClient<RequestInteractionRequest, RequestInteractionResponse> srvClient;
00244 String serviceName = this.interactionsNamespace + "/request_interaction";
00245 try {
00246 Log.d("AppsMng", "Request app service client created [" + serviceName + "]");
00247 srvClient = connectedNode.newServiceClient(serviceName, RequestInteraction._TYPE);
00248 } catch (ServiceNotFoundException e) {
00249 Log.w("AppsMng", "Request app service not found [" + serviceName + "]");
00250 throw new RosRuntimeException(e);
00251 }
00252 final RequestInteractionRequest request = srvClient.newMessage();
00253
00254 request.setHash(this.app.getHash());
00255
00256 srvClient.call(request, requestServiceResponseListener);
00257 Log.d("AppsMng", "Request app service call done [" + serviceName + "]");
00258 }
00259
00260 private void getAppInfo() {
00261
00262 ServiceClient<GetInteractionRequest, GetInteractionResponse> srvClient;
00263 String serviceName = this.interactionsNamespace + "/get_interaction";
00264 try {
00265 Log.d("AppsMng", "Get app info service client created [" + serviceName + "]");
00266 srvClient = connectedNode.newServiceClient(serviceName, GetInteraction._TYPE);
00267 } catch (ServiceNotFoundException e) {
00268 Log.w("AppsMng", "Get app info not found [" + serviceName + "]");
00269 throw new RosRuntimeException(e);
00270 }
00271 final GetInteractionRequest request = srvClient.newMessage();
00272 request.setHash(this.app_hash);
00273
00274 srvClient.call(request, appInfoServiceResponseListener);
00275 Log.d("AppsMng", "Get app info service call done [" + serviceName + "]");
00276 }
00277
00282 private class ConnectNodeThread extends Thread {
00283 private MasterId masterId;
00284
00285 public ConnectNodeThread(MasterId masterId) {
00286 this.masterId = masterId;
00287 setDaemon(true);
00288 setUncaughtExceptionHandler(new UncaughtExceptionHandler() {
00289 @Override
00290 public void uncaughtException(Thread thread, Throwable ex) {
00291 failureCallback.handleFailure("exception: " + ex.getMessage());
00292 }
00293 });
00294 }
00295
00296 @Override
00297 public void run() {
00298 try {
00299 URI concertUri = new URI(masterId.getMasterUri());
00300
00301
00302
00303
00304
00305
00306 ParameterClient paramClient = new ParameterClient(
00307 NodeIdentifier.forNameAndUri("/concert_checker", concertUri.toString()), concertUri);
00308 String name = (String) paramClient.getParam(GraphName.of("/rosversion")).getResult();
00309 Log.i("Remocon", "Concert " + name + " found; retrieve additional information");
00310
00311 nodeMainExecutorService = new NodeMainExecutorService();
00312 NodeConfiguration nodeConfiguration = NodeConfiguration.newPublic(
00313 InetAddressFactory.newNonLoopback().getHostAddress(), concertUri);
00314 nodeMainExecutorService.execute(AppsManager.this, nodeConfiguration.setNodeName("apps_manager_node"));
00315
00316 } catch (URISyntaxException e) {
00317 Log.w("AppsMng", "invalid concert URI [" + masterId.getMasterUri() + "][" + e.toString() + "]");
00318 failureCallback.handleFailure("invalid concert URI");
00319 } catch (RuntimeException e) {
00320
00321 Log.w("AppsMng", "could not find concert [" + masterId.getMasterUri() + "][" + e.toString() + "]");
00322 failureCallback.handleFailure(e.toString());
00323 } catch (Throwable e) {
00324 Log.w("AppsMng", "exception while creating node in concert checker for URI " + masterId.getMasterUri(), e);
00325 failureCallback.handleFailure(e.toString());
00326 }
00327 }
00328 }
00329
00330 @Override
00331 public GraphName getDefaultNodeName() {
00332 return null;
00333 }
00334
00340 @Override
00341 public void onStart(final ConnectedNode connectedNode) {
00342 if (this.connectedNode != null) {
00343 Log.e("AppsMng", "App manager re-started before previous shutdown; ignoring...");
00344 return;
00345 }
00346
00347 this.connectedNode = connectedNode;
00348
00349 Log.d("AppsMng", "onStart() - " + action);
00350
00351 switch (action) {
00352 case NONE:
00353 Log.w("AppsMng", "Node started without specifying an action");
00354 break;
00355 case REQUEST_INTERACTION_USE:
00356 requestAppUse();
00357 break;
00358 case GET_INTERACTIONS_FOR_ROLE:
00359 getAppsForRole();
00360 break;
00361 case GET_INTERACTION_INFO:
00362 getAppInfo();
00363 break;
00364 default:
00365 Log.w("AppsMng", "Unrecogniced action requested: " + action);
00366 }
00367
00368 Log.d("AppsMng", "Done");
00369 }
00370
00371 @Override
00372 public void onShutdown(Node node) {
00373 Log.d("AppsMng", "Shutdown connected node...");
00374 super.onShutdown(node);
00375
00376
00377 this.connectedNode = null;
00378 Log.d("AppsMng", "Done; shutdown apps manager node main");
00379 }
00380
00381 @Override
00382 public void onShutdownComplete(Node node) {
00383 super.onShutdownComplete(node);
00384 }
00385
00386 @Override
00387 public void onError(Node node, Throwable throwable) {
00388 super.onError(node, throwable);
00389
00390 Log.e("AppsMng", node.getName().toString() + " node error: " + throwable.getMessage());
00391 failureCallback.handleFailure(node.getName().toString() + " node error: " + throwable.toString());
00392 }
00393 }