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
- 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
+ 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));
+
+ }
+
+}