From 8d9ecdff4b5d55816ad47e347674d63d96a28a6a Mon Sep 17 00:00:00 2001 From: grog Date: Fri, 29 Sep 2023 05:45:04 -0700 Subject: [PATCH] worky vertx --- .../org/myrobotlab/service/JMonkeyEngine.java | 7 +- .../java/org/myrobotlab/service/Vertx.java | 74 ++++++++++++++----- .../service/config/VertXConfig.java | 17 +++++ .../myrobotlab/service/meta/WebXRMeta.java | 2 +- .../org/myrobotlab/vertx/ApiVerticle.java | 3 +- .../myrobotlab/vertx/WebSocketHandler.java | 46 ++++++++---- 6 files changed, 109 insertions(+), 40 deletions(-) create mode 100644 src/main/java/org/myrobotlab/service/config/VertXConfig.java diff --git a/src/main/java/org/myrobotlab/service/JMonkeyEngine.java b/src/main/java/org/myrobotlab/service/JMonkeyEngine.java index 2174ac739b..9ca917a6cf 100644 --- a/src/main/java/org/myrobotlab/service/JMonkeyEngine.java +++ b/src/main/java/org/myrobotlab/service/JMonkeyEngine.java @@ -7,8 +7,6 @@ import java.io.FileOutputStream; import java.io.IOException; import java.nio.FloatBuffer; -import java.nio.file.Path; -import java.nio.file.Paths; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -52,7 +50,6 @@ import org.myrobotlab.net.Connection; import org.myrobotlab.sensor.EncoderData; import org.myrobotlab.sensor.EncoderListener; -import org.myrobotlab.service.abstracts.AbstractComputerVision; import org.myrobotlab.service.config.JMonkeyEngineConfig; import org.myrobotlab.service.config.ServiceConfig; import org.myrobotlab.service.interfaces.Gateway; @@ -405,10 +402,12 @@ public void attach(Attachable attachable) throws Exception { // this is to support future (non-Java) classes that cannot be instantiated // and // are subclassed in a proxy class with getType() overloaded for to identify + /**
 DO NOT NEED THIS UNTIL JMONKEY DISPLAYS VIDEO DATA - SLAM MAPPING
     if (service.getTypeKey().equals("org.myrobotlab.service.OpenCV")) {
       AbstractComputerVision cv = (AbstractComputerVision) service;
       subscribe(service.getName(), "publishCvData");
-    }
+    }
+ */ if (service.getTypeKey().equals("org.myrobotlab.service.Servo")) { // non-batched - "instantaneous" move data subscription diff --git a/src/main/java/org/myrobotlab/service/Vertx.java b/src/main/java/org/myrobotlab/service/Vertx.java index f87e9b9e4c..8665793d37 100644 --- a/src/main/java/org/myrobotlab/service/Vertx.java +++ b/src/main/java/org/myrobotlab/service/Vertx.java @@ -1,16 +1,24 @@ package org.myrobotlab.service; -import java.util.HashMap; +import java.net.URISyntaxException; +import java.util.List; +import java.util.Map; import java.util.Set; +import org.myrobotlab.codec.CodecUtils; +import org.myrobotlab.framework.Message; import org.myrobotlab.framework.Service; import org.myrobotlab.logging.Level; import org.myrobotlab.logging.LoggerFactory; import org.myrobotlab.logging.LoggingFactory; +import org.myrobotlab.net.Connection; +import org.myrobotlab.service.config.VertxConfig; +import org.myrobotlab.service.interfaces.Gateway; import org.myrobotlab.vertx.ApiVerticle; import org.slf4j.Logger; import io.vertx.core.VertxOptions; +import io.vertx.core.http.ServerWebSocket; /** * Vertx gateway - used to support a http and websocket gateway for myrobotlab. @@ -21,10 +29,10 @@ * * @see https://medium.com/@pvub/https-medium-com-pvub-vert-x-workers-6a8df9b2b9ee * - * @author greg + * @author GroG * */ -public class Vertx extends Service { +public class Vertx extends Service implements Gateway { private static final long serialVersionUID = 1L; @@ -78,9 +86,8 @@ public void stopService() { stop(); } - /** - * + * Undeploy the verticle serving http and ws */ public void stop() { log.info("stopping driver"); @@ -88,27 +95,14 @@ public void stop() { for (String id : ids) { vertx.undeploy(id, (result) -> { if (result.succeeded()) { - log.info("succeeded"); + log.info("undeploy succeeded"); } else { - log.error("failed"); + log.error("undeploy 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 { @@ -132,4 +126,44 @@ public static void main(String[] args) { log.error("main threw", e); } } + + // FIXME - refactor for bare minimum + + @Override /* FIXME "Gateway" is server/service oriented not connecting thing - remove this */ + public void connect(String uri) throws URISyntaxException { + // TODO Auto-generated method stub + + } + + @Override /* FIXME not much point of these - as they are all consistently using Runtime's centralized connection info */ + public List getClientIds() { + return Runtime.getInstance().getConnectionUuids(getName()); + } + + @Override /* FIXME not much point of these - as they are all consistently using Runtime's centralized connection info */ + public Map getClients() { + return Runtime.getInstance().getConnections(getName()); + } + + + @Override /* FIXME this is the one and probably "only" relevant method for Gateway - perhaps a handle(Connection c) */ + public void sendRemote(Message msg) throws Exception { + log.info("sendRemote {}", msg.toString()); + msg.addHop(getId()); + Map clients = getClients(); + for(Connection c: clients.values()) { + try { + ServerWebSocket socket = (ServerWebSocket)c.get("websocket"); + String json = CodecUtils.toJsonMsg(msg); + socket.writeTextMessage(json); + } catch(Exception e) { + error(e); + } + } + // broadcastMode - iterate through clients send all + } + + @Override + public boolean isLocal(Message msg) { + return Runtime.getInstance().isLocal(msg); } } 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..6369ef70b5 --- /dev/null +++ b/src/main/java/org/myrobotlab/service/config/VertXConfig.java @@ -0,0 +1,17 @@ +package org.myrobotlab.service.config; + +import java.util.ArrayList; +import java.util.List; + +public class VertXConfig extends ServiceConfig { + + public Integer port = 8443; + public boolean autoStartBrowser = true; + public List resources = new ArrayList<>(); + + public VertXConfig() { + // robot-x-app build directory + // resources.add("./resource/WebGui/app"); + } + +} diff --git a/src/main/java/org/myrobotlab/service/meta/WebXRMeta.java b/src/main/java/org/myrobotlab/service/meta/WebXRMeta.java index 171959fbf5..36efe701ad 100644 --- a/src/main/java/org/myrobotlab/service/meta/WebXRMeta.java +++ b/src/main/java/org/myrobotlab/service/meta/WebXRMeta.java @@ -16,7 +16,7 @@ public class WebXRMeta extends MetaData { public WebXRMeta() { // add a cool description - addDescription("WebXr allows hmi devices to add input and get data back from mrl"); + 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); diff --git a/src/main/java/org/myrobotlab/vertx/ApiVerticle.java b/src/main/java/org/myrobotlab/vertx/ApiVerticle.java index a61bd32a1f..57239bd210 100644 --- a/src/main/java/org/myrobotlab/vertx/ApiVerticle.java +++ b/src/main/java/org/myrobotlab/vertx/ApiVerticle.java @@ -44,7 +44,8 @@ public void start() throws Exception { router.route().handler(CorsHandler.create("*").allowedMethod(HttpMethod.GET).allowedMethod(HttpMethod.OPTIONS).allowedHeader("Accept").allowedHeader("Authorization") .allowedHeader("Content-Type")); - // static file routing + // static file routing - this is from a npm "build" ... but durin gdevelop its far + // easier to use setupProxy.js from a npm start .. but deployment would be easier with a "build" //StaticHandler root = StaticHandler.create("src/main/resources/resource/Vertx/app"); // StaticHandler root = StaticHandler.create("src/main/resources/resource/Vertx/app"); diff --git a/src/main/java/org/myrobotlab/vertx/WebSocketHandler.java b/src/main/java/org/myrobotlab/vertx/WebSocketHandler.java index 46df333391..69b56957f3 100644 --- a/src/main/java/org/myrobotlab/vertx/WebSocketHandler.java +++ b/src/main/java/org/myrobotlab/vertx/WebSocketHandler.java @@ -6,6 +6,7 @@ import org.myrobotlab.framework.MethodCache; import org.myrobotlab.framework.interfaces.ServiceInterface; import org.myrobotlab.logging.LoggerFactory; +import org.myrobotlab.net.Connection; import org.myrobotlab.service.Runtime; import org.slf4j.Logger; @@ -15,29 +16,30 @@ /** * Minimal Handler for all websocket messages coming from the react js client. * - * TODO - what else besides text messages - websocket binary streams ??? text stream ? + * 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); /** * reference to the MRL Vertx service / websocket and http server */ transient private org.myrobotlab.service.Vertx service = null; - + /** * reference to the websocket text message handler */ 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; } @@ -79,7 +81,7 @@ public void handle(String json) { // } else { // ctx.writeTextMessage("ping"); Useful is writing back // } - + // replace with typed parameters msg.data = params; // queue the message @@ -88,21 +90,37 @@ public void handle(String json) { } 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) { + @Override + public void handle(ServerWebSocket socket) { + // FIXME - get "id" from js client - need something unique from the js + // client + // String id = r.getRequest().getParameter("id"); + String id = String.format("vertx-%s", service.getName()); + // String uuid = UUID.randomUUID().toString(); + String uuid = socket.binaryHandlerID(); + Connection connection = new Connection(uuid, id, service.getName()); + connection.put("c-type", service.getSimpleName()); + connection.put("gateway", service.getName()); + connection.putTransient("websocket", socket); + Runtime.getInstance().addConnection(uuid, id, connection); // ctx.writeTextMessage("ping"); FIXME - query ? // FIXME - thread-safe ? how many connections mapped to objects ? - event.textMessageHandler(new TextMessageHandler(service)); - + socket.textMessageHandler(textMessageHandler); + log.info("new ws connection {}", uuid); + + socket.closeHandler(close -> { + log.info("closing {}", socket.binaryHandlerID()); + Runtime.getInstance().removeConnection(socket.binaryHandlerID()); + }); + } }