diff --git a/.gitignore b/.gitignore index fb07e725f0..4fa1d43508 100644 --- a/.gitignore +++ b/.gitignore @@ -116,4 +116,7 @@ build/ /lastRestart.py /.factorypath start.yml +config +src/main/resources/resource/InMoov2 +src/main/resources/resource/ProgramAB *.iml diff --git a/README.md b/README.md index 7602ad92d9..fdc207c71b 100644 --- a/README.md +++ b/README.md @@ -99,7 +99,6 @@ Enjoy the code review, address issues and concern in the code review Reviewer merges pull request to develop. Reviewer deletes branch. - The following config should be useful to work directly on WebGui UI and InMoov2 UI if the repos are submoduled under src/main/resources/resource/InMoov2, diff --git a/pom.xml b/pom.xml index a1507381a2..0900d2149e 100644 --- a/pom.xml +++ b/pom.xml @@ -1,102 +1,102 @@ - - - 4.0.0 - org.myrobotlab - mrl - 0.0.1-SNAPSHOT - MyRobotLab - Open Source Creative Machine Control - - - false - - - - 1.1. - - ${maven.build.timestamp} - yyyyMMddHHmm - ${timestamp} - ${version.prefix}${build.number} - ${git.branch} - ${NODE_NAME} - ${NODE_LABELS} - - - - 11 - 11 - UTF-8 - - - + + + 4.0.0 + org.myrobotlab + mrl + 0.0.1-SNAPSHOT + MyRobotLab + Open Source Creative Machine Control + + + false + + + + 1.1. + + ${maven.build.timestamp} + yyyyMMddHHmm + ${timestamp} + ${version.prefix}${build.number} + ${git.branch} + ${NODE_NAME} + ${NODE_LABELS} + + + + 11 + 11 + UTF-8 + + + @@ -135,9 +135,9 @@ https://m2.dv8tion.net/releases - - - + + + javazoom @@ -163,7 +163,7 @@ - + org.boofcv boofcv-all @@ -1603,6 +1603,34 @@ + + + io.vertx + vertx-core + 4.3.3 + provided + + + io.netty + * + + + + + io.vertx + vertx-web + 4.3.3 + provided + + + io.netty + * + + + + + + @@ -1734,375 +1762,375 @@ - - - org.mockito - mockito-core - 3.12.4 - test - - - - - - - false - src/main/resources - - - false - src/main/java - - ** - - - **/*.java - - - - - - false - src/test/resources - - - false - src/test/java - - ** - - - **/*.java - - - - src/main/resources - ${project.basedir} - - - - - - - - org.codehaus.mojo - properties-maven-plugin - 1.0.0 - - - org.apache.maven.plugins - maven-enforcer-plugin - 3.1.0 - - - - - - - - org.apache.maven.plugins - maven-enforcer-plugin - - - no-duplicate-declared-dependencies - - enforce - - - - - - - - - - - - org.codehaus.mojo - properties-maven-plugin - - - initialize - - read-project-properties - - - - build.properties - - - - - - - - - - org.apache.maven.plugins - maven-shade-plugin - 3.1.0 - - - package - - shade - - - myrobotlab - - true - myrobotlab-full - false - - - - - org.myrobotlab.service.Runtime - ${version} - ${version} - - ${build.number} - ${maven.build.timestamp} - ${agent.name} - ${user.name} - - - ${git.tags} - ${git.branch} - ${git.dirty} - ${git.remote.origin.url} - ${git.commit.id} - ${git.commit.id.abbrev} - ${git.commit.id.full} - ${git.commit.id.describe} - ${git.commit.id.describe-short} - ${git.commit.user.name} - ${git.commit.user.email} - - ${git.commit.time} - ${git.closest.tag.name} - ${git.closest.tag.commit.count} - ${git.build.user.name} - ${git.build.user.email} - ${git.build.time} - ${git.build.version} - - - - - - - *:* - - module-info.class - META-INF/*.SF - META-INF/*.DSA - META-INF/*.RSA - - - - - - - - - - org.apache.maven.plugins - maven-assembly-plugin - - - assembly.xml - - myrobotlab - false - - - - trigger-assembly - package - - single - - - - - - - true - org.apache.maven.plugins - maven-compiler-plugin - 2.3.2 - - 11 - 11 - true - true - -parameters - - - - - org.apache.maven.plugins - maven-resources-plugin - 2.4.3 - - - - pl.project13.maven - git-commit-id-plugin - 4.9.10 - - - initialize - get-the-git-infos - - revision - - - - - ${project.basedir}/.git - git - false - true - ${project.build.outputDirectory}/git.properties - - - false - false - -dirty - - - - - - maven-surefire-plugin - org.apache.maven.plugins - 2.22.2 - - -Djava.library.path=libraries/native -Djna.library.path=libraries/native - - **/*Test.java - - - **/integration/* - - - - - - - - org.apache.maven.plugins - maven-clean-plugin - 2.3 - - - - data/.myrobotlab - false - - - libraries - - ** - - false - - - data - - ** - - - - resource - - ** - - - - src/main/resources/resource/framework - - **/serviceData.json - - false - - - - - - - - - - - - org.apache.maven.plugins - maven-surefire-report-plugin - 2.22.2 - - - org.apache.maven.plugins - maven-javadoc-plugin - 3.0.1 - - - - - myrobotlab - http://myrobotlab.org - - - github - https://github.com/MyRobotLab/myrobotlab/issues - - + + + org.mockito + mockito-core + 3.12.4 + test + + + + + + + false + src/main/resources + + + false + src/main/java + + ** + + + **/*.java + + + + + + false + src/test/resources + + + false + src/test/java + + ** + + + **/*.java + + + + src/main/resources + ${project.basedir} + + + + + + + + org.codehaus.mojo + properties-maven-plugin + 1.0.0 + + + org.apache.maven.plugins + maven-enforcer-plugin + 3.1.0 + + + + + + + + org.apache.maven.plugins + maven-enforcer-plugin + + + no-duplicate-declared-dependencies + + enforce + + + + + + + + + + + + org.codehaus.mojo + properties-maven-plugin + + + initialize + + read-project-properties + + + + build.properties + + + + + + + + + + org.apache.maven.plugins + maven-shade-plugin + 3.1.0 + + + package + + shade + + + myrobotlab + + true + myrobotlab-full + false + + + + + org.myrobotlab.service.Runtime + ${version} + ${version} + + ${build.number} + ${maven.build.timestamp} + ${agent.name} + ${user.name} + + + ${git.tags} + ${git.branch} + ${git.dirty} + ${git.remote.origin.url} + ${git.commit.id} + ${git.commit.id.abbrev} + ${git.commit.id.full} + ${git.commit.id.describe} + ${git.commit.id.describe-short} + ${git.commit.user.name} + ${git.commit.user.email} + + ${git.commit.time} + ${git.closest.tag.name} + ${git.closest.tag.commit.count} + ${git.build.user.name} + ${git.build.user.email} + ${git.build.time} + ${git.build.version} + + + + + + + *:* + + module-info.class + META-INF/*.SF + META-INF/*.DSA + META-INF/*.RSA + + + + + + + + + + org.apache.maven.plugins + maven-assembly-plugin + + + assembly.xml + + myrobotlab + false + + + + trigger-assembly + package + + single + + + + + + + true + org.apache.maven.plugins + maven-compiler-plugin + 2.3.2 + + 11 + 11 + true + true + -parameters + + + + + org.apache.maven.plugins + maven-resources-plugin + 2.4.3 + + + + pl.project13.maven + git-commit-id-plugin + 4.9.10 + + + initialize + get-the-git-infos + + revision + + + + + ${project.basedir}/.git + git + false + true + ${project.build.outputDirectory}/git.properties + + + false + false + -dirty + + + + + + maven-surefire-plugin + org.apache.maven.plugins + 2.22.2 + + -Djava.library.path=libraries/native -Djna.library.path=libraries/native + + **/*Test.java + + + **/integration/* + + + + + + + + org.apache.maven.plugins + maven-clean-plugin + 2.3 + + + + data/.myrobotlab + false + + + libraries + + ** + + false + + + data + + ** + + + + resource + + ** + + + + src/main/resources/resource/framework + + **/serviceData.json + + false + + + + + + + + + + + + org.apache.maven.plugins + maven-surefire-report-plugin + 2.22.2 + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.0.1 + + + + + myrobotlab + http://myrobotlab.org + + + github + https://github.com/MyRobotLab/myrobotlab/issues + + diff --git a/src/main/java/org/myrobotlab/service/ProgramAB.java b/src/main/java/org/myrobotlab/service/ProgramAB.java index 29b8653ad8..db06861aaa 100644 --- a/src/main/java/org/myrobotlab/service/ProgramAB.java +++ b/src/main/java/org/myrobotlab/service/ProgramAB.java @@ -792,7 +792,7 @@ public String addBotPath(String path) { broadcastState(); } else { - error("invalid bot path - a bot must be a directory with a subdirectory named \"aiml\""); + error("invalid bot path %s - a bot must be a directory with a subdirectory named \"aiml\"", path); return null; } return path; diff --git a/src/main/java/org/myrobotlab/service/Vertx.java b/src/main/java/org/myrobotlab/service/Vertx.java new file mode 100644 index 0000000000..f87e9b9e4c --- /dev/null +++ b/src/main/java/org/myrobotlab/service/Vertx.java @@ -0,0 +1,135 @@ +package org.myrobotlab.service; + +import java.util.HashMap; +import java.util.Set; + +import org.myrobotlab.framework.Service; +import org.myrobotlab.logging.Level; +import org.myrobotlab.logging.LoggerFactory; +import org.myrobotlab.logging.LoggingFactory; +import org.myrobotlab.vertx.ApiVerticle; +import org.slf4j.Logger; + +import io.vertx.core.VertxOptions; + +/** + * Vertx gateway - used to support a http and websocket gateway for myrobotlab. + * Write business logic in Verticles. Also, try not to write any logic besides initialization inside start() method. + * + * It currently does not utilize the Vertx event bus - which is pretty much the most important part of Vertx. + * TODO: take advantage of publishing on the event bus + * + * @see https://medium.com/@pvub/https-medium-com-pvub-vert-x-workers-6a8df9b2b9ee + * + * @author greg + * + */ +public class Vertx extends Service { + + private static final long serialVersionUID = 1L; + + private transient io.vertx.core.Vertx vertx = null; + + public final static Logger log = LoggerFactory.getLogger(Vertx.class); + + public Vertx(String n, String id) { + super(n, id); + } + + /** + * deploys a http and websocket verticle on a secure TLS channel with self signed certificate + */ + public void start() { + log.info("starting driver"); + + /** + * FIXME - might have to revisit this This is a block comment, but takes + * advantage of javadoc pre non-formatting in ide to preserve the code + * formatting + * + *
+     * 
+     * final Vertx that = this;
+     * 
+     * java.lang.Runtime.getRuntime().addShutdownHook(new Thread() {
+     *   public void run() {
+     *     System.out.println("Running Shutdown Hook");
+     *     that.stop();
+     *   }
+     * });
+     * 
+     * 
+ */ + + vertx = io.vertx.core.Vertx.vertx(new VertxOptions().setBlockedThreadCheckInterval(100000)); + vertx.deployVerticle(new ApiVerticle(this)); + + } + + @Override + public void startService() { + super.startService(); + start(); + } + + @Override + public void stopService() { + super.stopService(); + stop(); + } + + + /** + * + */ + public void stop() { + log.info("stopping driver"); + Set ids = vertx.deploymentIDs(); + for (String id : ids) { + vertx.undeploy(id, (result) -> { + if (result.succeeded()) { + log.info("succeeded"); + } else { + log.error("failed"); + } + }); + } + } + + public static class Matrix { + public String name; + public HashMap matrix; + + public Matrix() { + }; + } + + public Matrix publishMatrix(Matrix data) { + // log.info("publishMatrix {}", data.name); + return data; + } + + public static void main(String[] args) { + try { + + LoggingFactory.init(Level.INFO); + + Vertx vertx = (Vertx) Runtime.start("vertx", "Vertx"); + vertx.start(); + + InMoov2 i01 = (InMoov2)Runtime.start("i01", "InMoov2"); + // i01.startSimulator(); + JMonkeyEngine jme = (JMonkeyEngine)i01.startPeer("simulator"); +// Runtime.start("python", "Python"); +// + WebGui webgui = (WebGui) Runtime.create("webgui", "WebGui"); + // webgui.setSsl(true); + webgui.autoStartBrowser(false); + webgui.setPort(8888); + webgui.startService(); + + } catch (Exception e) { + log.error("main threw", e); + } + } +} diff --git a/src/main/java/org/myrobotlab/service/WebXR.java b/src/main/java/org/myrobotlab/service/WebXR.java new file mode 100644 index 0000000000..d194df1e4e --- /dev/null +++ b/src/main/java/org/myrobotlab/service/WebXR.java @@ -0,0 +1,89 @@ +package org.myrobotlab.service; + +import java.util.HashMap; +import java.util.Map; + +import org.myrobotlab.framework.Service; +import org.myrobotlab.logging.Level; +import org.myrobotlab.logging.LoggerFactory; +import org.myrobotlab.logging.LoggingFactory; +import org.myrobotlab.math.MapperSimple; +import org.myrobotlab.service.config.WebXRConfig; +import org.myrobotlab.service.data.Pose; +import org.slf4j.Logger; + +public class WebXR extends Service { + + private static final long serialVersionUID = 1L; + + public final static Logger log = LoggerFactory.getLogger(WebXR.class); + + public WebXR(String n, String id) { + super(n, id); + } + + public Pose publishPose(Pose pose) { + log.warn("publishPose {}", pose); + System.out.println(pose.toString()); + + // process mappings config into joint angles + Map map = new HashMap<>(); + + WebXRConfig c = (WebXRConfig)config; + String path = String.format("%s.orientation.roll", pose.name); + if (c.mappings.containsKey(path)) { + Map mapper = c.mappings.get(path); + for (String name: mapper.keySet()) { + map.put(name, mapper.get(name).calcOutput(pose.orientation.roll)); + } + } + + path = String.format("%s.orientation.pitch", pose.name); + if (c.mappings.containsKey(path)) { + Map mapper = c.mappings.get(path); + for (String name: mapper.keySet()) { + map.put(name, mapper.get(name).calcOutput(pose.orientation.pitch)); + } + } + + path = String.format("%s.orientation.yaw", pose.name); + if (c.mappings.containsKey(path)) { + Map mapper = c.mappings.get(path); + for (String name: mapper.keySet()) { + map.put(name, mapper.get(name).calcOutput(pose.orientation.yaw)); + } + } + + invoke("publishJointAngles", map); + + // TODO - publishQuaternion + // invoke("publishQuaternion", map); + + return pose; + } + + + public Map publishJointAngles(Map map){ + return map; + } + + public static void main(String[] args) { + try { + + LoggingFactory.init(Level.INFO); + + Runtime.start("webxr", "WebXr"); + WebGui webgui = (WebGui) Runtime.create("webgui", "WebGui"); + // webgui.setSsl(true); + webgui.autoStartBrowser(false); + webgui.startService(); + Runtime.start("vertx", "Vertx"); + InMoov2 i01 = (InMoov2)Runtime.start("i01", "InMoov2"); + i01.startPeer("simulator"); + + + } catch (Exception e) { + log.error("main threw", e); + } + } +} diff --git a/src/main/java/org/myrobotlab/service/config/VertxConfig.java b/src/main/java/org/myrobotlab/service/config/VertxConfig.java new file mode 100644 index 0000000000..f2119d8ddd --- /dev/null +++ b/src/main/java/org/myrobotlab/service/config/VertxConfig.java @@ -0,0 +1,9 @@ +package org.myrobotlab.service.config; + +public class VertxConfig extends ServiceConfig { + + public Integer port = 8443; + public Integer workerCount = 1; + public boolean ssl = true; + +} diff --git a/src/main/java/org/myrobotlab/service/data/Orientation.java b/src/main/java/org/myrobotlab/service/data/Orientation.java index b2d5d5658e..b7df4102dc 100644 --- a/src/main/java/org/myrobotlab/service/data/Orientation.java +++ b/src/main/java/org/myrobotlab/service/data/Orientation.java @@ -11,6 +11,7 @@ public class Orientation { public Double roll = null; public Double pitch = null; public Double yaw = null; + public String src = null; // default constructor (values will be null until set) public Orientation() { diff --git a/src/main/java/org/myrobotlab/service/data/Pose.java b/src/main/java/org/myrobotlab/service/data/Pose.java new file mode 100644 index 0000000000..767d9be81d --- /dev/null +++ b/src/main/java/org/myrobotlab/service/data/Pose.java @@ -0,0 +1,22 @@ +package org.myrobotlab.service.data; + +public class Pose { + public String name = null; + public Long ts = null; + public Position position = null; + public Orientation orientation = null; + + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append(String.format("name:%s", name)); + if (position != null) { + sb.append(String.format(" x:%.2f y:%.2f z:%.2f", position.x, position.y, position.z)); + } + if (orientation != null) { + sb.append(String.format(" roll:%.2f pitch:%.2f yaw:%.2f", orientation.roll, orientation.pitch, orientation.yaw)); + } + return sb.toString(); + } + + +} diff --git a/src/main/java/org/myrobotlab/service/data/Position.java b/src/main/java/org/myrobotlab/service/data/Position.java new file mode 100644 index 0000000000..83fe574a44 --- /dev/null +++ b/src/main/java/org/myrobotlab/service/data/Position.java @@ -0,0 +1,43 @@ +package org.myrobotlab.service.data; + +public class Position { + + public Double x; + public Double y; + public Double z; + public String src; + + public Position(double x, double y, double z) { + this.x = x; + this.y = y; + this.z = z; + } + + public Position(double x, double y) { + this.x = x; + this.y = y; + } + + public Position(int x, int y, int z) { + this.x = (double) x; + this.y = (double) y; + this.z = (double) z; + } + + public Position(int x, int y) { + this.x = (double) x; + this.y = (double) y; + } + + public Position(float x, float y, float z) { + this.x = (double) x; + this.y = (double) y; + this.z = (double) z; + } + + public Position(float x, float y) { + this.x = (double) x; + this.y = (double) y; + } + +} diff --git a/src/main/java/org/myrobotlab/service/meta/WebXRMeta.java b/src/main/java/org/myrobotlab/service/meta/WebXRMeta.java new file mode 100644 index 0000000000..171959fbf5 --- /dev/null +++ b/src/main/java/org/myrobotlab/service/meta/WebXRMeta.java @@ -0,0 +1,33 @@ +package org.myrobotlab.service.meta; + +import org.myrobotlab.logging.LoggerFactory; +import org.myrobotlab.service.meta.abstracts.MetaData; +import org.slf4j.Logger; + +public class WebXRMeta extends MetaData { + private static final long serialVersionUID = 1L; + public final static Logger log = LoggerFactory.getLogger(WebXRMeta.class); + + /** + * This class is contains all the meta data details of a service. It's peers, + * dependencies, and all other meta data related to the service. + * + */ + public WebXRMeta() { + + // add a cool description + addDescription("WebXr allows hmi devices to add input and get data back from mrl"); + + // false will prevent it being seen in the ui + setAvailable(true); + + // add it to one or many categories + addCategory("remote","control"); + + // add a sponsor to this service + // the person who will do maintenance + // setSponsor("GroG"); + + } + +} diff --git a/src/main/java/org/myrobotlab/vertx/ApiVerticle.java b/src/main/java/org/myrobotlab/vertx/ApiVerticle.java new file mode 100644 index 0000000000..6b3ca595c7 --- /dev/null +++ b/src/main/java/org/myrobotlab/vertx/ApiVerticle.java @@ -0,0 +1,105 @@ +package org.myrobotlab.vertx; + +import java.lang.reflect.Method; + +import org.myrobotlab.codec.CodecUtils; +import org.myrobotlab.framework.MethodCache; +import org.myrobotlab.framework.interfaces.ServiceInterface; +import org.myrobotlab.service.Runtime; +import org.myrobotlab.service.config.VertxConfig; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import io.vertx.core.AbstractVerticle; +import io.vertx.core.Handler; +import io.vertx.core.http.HttpMethod; +import io.vertx.core.http.HttpServer; +import io.vertx.core.http.HttpServerOptions; +import io.vertx.core.http.ServerWebSocket; +import io.vertx.core.net.SelfSignedCertificate; +import io.vertx.ext.web.Router; +import io.vertx.ext.web.handler.CorsHandler; +import io.vertx.ext.web.handler.StaticHandler; + +/** + * verticle to handle api requests + * + * @author GroG + */ +public class ApiVerticle extends AbstractVerticle { + + public final static Logger log = LoggerFactory.getLogger(ApiVerticle.class); + + private Router router; + + transient private org.myrobotlab.service.Vertx service; + + public ApiVerticle(org.myrobotlab.service.Vertx service) { + super(); + this.service = service; + } + + @Override + public void start() throws Exception { + // process configuration and create handlers + log.info("starting api verticle"); + VertxConfig config = (VertxConfig) service.getConfig(); + + // create a router + router = Router.router(vertx); + + // handle cors requests + router.route().handler(CorsHandler.create("*").allowedMethod(HttpMethod.GET).allowedMethod(HttpMethod.OPTIONS).allowedHeader("Accept").allowedHeader("Authorization") + .allowedHeader("Content-Type")); + + // static file routing + + //StaticHandler root = StaticHandler.create("src/main/resources/resource/Vertx/app"); + // StaticHandler root = StaticHandler.create("src/main/resources/resource/Vertx/app"); + StaticHandler root = StaticHandler.create("../robotlab-x-app/build/"); + root.setCachingEnabled(false); + root.setDirectoryListing(true); + root.setIndexPage("index.html"); + // root.setAllowRootFileSystemAccess(true); + // root.setWebRoot(null); + router.route("/*").handler(root); + + + // router.get("/health").handler(this::generateHealth); + // router.get("/api/transaction/:customer/:tid").handler(this::handleTransaction); + + // create the HTTP server and pass the + // "accept" method to the request handler + HttpServerOptions httpOptions = new HttpServerOptions(); + + if (config.ssl) { + SelfSignedCertificate certificate = SelfSignedCertificate.create(); + httpOptions.setSsl(true); + httpOptions.setKeyCertOptions(certificate.keyCertOptions()); + httpOptions.setTrustOptions(certificate.trustOptions()); + } + httpOptions.setPort(config.port); + + + HttpServer server = vertx.createHttpServer(httpOptions); + // TODO - this is where multiple workers would be defined + // .createHttpServer() + + // WebSocketHandler webSocketHandler = new WebSocketHandler(service); + // server.webSocketHandler(webSocketHandler); + + // FIXME - don't do "long" or "common" processing in the start() + // FIXME - how to do this -> server.webSocketHandler(this::handleWebSocket); + server.webSocketHandler(new WebSocketHandler(service)); + server.requestHandler(router); + // start servers + server.listen(); + } + + + @Override + public void stop() throws Exception { + log.info("stopping api verticle"); + } + +} diff --git a/src/main/java/org/myrobotlab/vertx/WebSocketHandler.java b/src/main/java/org/myrobotlab/vertx/WebSocketHandler.java new file mode 100644 index 0000000000..76d0fb8c1f --- /dev/null +++ b/src/main/java/org/myrobotlab/vertx/WebSocketHandler.java @@ -0,0 +1,93 @@ +package org.myrobotlab.vertx; + +import java.lang.reflect.Method; + +import org.myrobotlab.codec.CodecUtils; +import org.myrobotlab.framework.MethodCache; +import org.myrobotlab.framework.interfaces.ServiceInterface; +import org.myrobotlab.logging.LoggerFactory; +import org.myrobotlab.service.Runtime; +import org.slf4j.Logger; + +import io.vertx.core.Handler; +import io.vertx.core.http.ServerWebSocket; + +/** + * + * TODO - what else besides text messages - websocket binary streams ??? text stream ? + * + * @author GroG + * + */ +public class WebSocketHandler implements Handler { + + public final static Logger log = LoggerFactory.getLogger(WebSocketHandler.class); + + transient private org.myrobotlab.service.Vertx service = null; + TextMessageHandler textMessageHandler = null; + + public static class TextMessageHandler implements Handler { + + org.myrobotlab.service.Vertx service = null; + + public TextMessageHandler(org.myrobotlab.service.Vertx service) { + this.service = service; + } + + @Override + public void handle(String json) { + log.info("handling {}", json); + + Method method; + try { + + org.myrobotlab.framework.Message msg = CodecUtils.fromJson(json, org.myrobotlab.framework.Message.class); + + Class clazz = Runtime.getClass(msg.name); + if (clazz == null) { + log.error("cannot derive local type from service {}", msg.name); + return; + } + + MethodCache cache = MethodCache.getInstance(); + Object[] params = cache.getDecodedJsonParameters(clazz, msg.method, msg.data); + + method = cache.getMethod(clazz, msg.method, params); + if (method == null) { + service.error("method cache could not find %s.%s(%s)", clazz.getSimpleName(), msg.method, msg.data); + return; + } + + ServiceInterface si = Runtime.getService(msg.name); + Object ret = method.invoke(si, params); + + // put msg on mrl msg bus :) + // service.in(msg); <- NOT DECODE PARAMS !! + + // if ((new Random()).nextInt(100) == 0) { + // ctx.close(); - will close the websocket !!! + // } else { + // ctx.writeTextMessage("ping"); Useful is writing back + // } + + } catch (Exception e) { + service.error(e); + } + } + } + + public WebSocketHandler(org.myrobotlab.service.Vertx service) { + this.service = service; + this.textMessageHandler = new TextMessageHandler(service); + } + + @Override + public void handle(ServerWebSocket event) { + + // ctx.writeTextMessage("ping"); FIXME - query ? + // FIXME - thread-safe ? how many connections mapped to objects ? + event.textMessageHandler(new TextMessageHandler(service)); + + } + +}