q = null;
+ if (!sendQueues.containsKey(key)) {
+ q = new LinkedBlockingQueue<>();
+ sendQueues.put(key, q);
+ } else {
+ q = sendQueues.get(key);
+ }
+
+ q.add(msg);
+ invoke("publishSendMessage", msg);
+ msgs.add(msg);
+
+ if (!remoteServices.containsKey(msg.name)) {
+ error("got remote message from %s - and do not have its client !!!", msg.name);
+ return;
+ }
+ remoteServices.get(msg.name).handle(msg);
+ }
+
+ public void clear() {
+ sendQueues.clear();
+ }
+
+ public int size() {
+ return msgs.size();
+ }
+
+ @Override
+ public boolean isLocal(Message msg) {
+ return Runtime.getInstance().isLocal(msg);
+ }
+
+
+ public void sendWithDelay(String name, String method, Object... data) {
+ Message msg = Message.createMessage(method, name, method, data);
+ addTask(UUID.randomUUID().toString(), true, 0, 0, "send", new Object[] { msg });
+ }
+
+
+ /**
+ * Send an asynchronous message so waiting for a callback can be done easily
+ * with inline code e.g.
+ *
+ *
+ * mock.sendWithDelay(10, "mouth", "speakBlocking");
+ * mock.waitForMsg(100, "mocker", "publishSpeaking");
+ *
+ *
+ *
+ * @param wait
+ * @param name
+ * @param method
+ */
+ public void sendWithDelay(long wait, String name, String method) {
+ sendWithDelay(wait, name, method, (Object[]) null);
+ }
+
+ public void sendWithDelay(long wait, String name, String method, Object... data) {
+ Message msg = Message.createMessage(method, name, method, data);
+ addTask(UUID.randomUUID().toString(), true, wait, wait, "send", new Object[] { msg });
+ }
+
+ // FIXME - must have a radix of names and block on specific publishing methods
+ public Message waitForMsg(String name, String callback, long maxTimeWaitMs) throws TimeoutException {
+ try {
+ String fullName = getFullRemoteName(name);
+
+ String key = String.format("%s.%s", fullName, callback);
+ if (!sendQueues.containsKey(key)) {
+ return null;
+ }
+
+ Message msg = sendQueues.get(key).poll(maxTimeWaitMs, TimeUnit.MILLISECONDS);
+ if (msg == null) {
+ String timeout = String.format("waited %dms for %s.%s", maxTimeWaitMs, name, callback);
+ throw new TimeoutException(timeout);
+ } else {
+ return msg;
+ }
+ } catch (InterruptedException e) {
+ log.info("releasing polling thread {}", Thread.currentThread().getId());
+ }
+ return null;
+ }
+
+ /**
+ * set the current remote id
+ *
+ * @param id
+ */
+ public void setRemoteId(String id) {
+ remoteId = id;
+ }
+
+ /**
+ * get the current remote id
+ *
+ * @return
+ */
+ public String getRemoteId() {
+ return remoteId;
+ }
+
+ @Override
+ public void startService() {
+ super.startService();
+ // add the remote instance over a connection
+ addConnection(remoteId);
+ // add a default remote service
+ ArrayList interfaces = new ArrayList<>();
+ interfaces.add(ServiceInterface.class.getName());
+ registerRemoteService("mocker", interfaces);
+
+ }
+
+ /**
+ * Registers a non Java service with mrl runtime, so it can be added to
+ * listeners and verified in testing
+ *
+ * @param remoteServiceName
+ */
+ public void registerRemoteService(String remoteServiceName) {
+ registerRemoteService(remoteServiceName, null);
+ }
+
+ public String getFullRemoteName(String name) {
+ if (!name.contains("@")) {
+ return String.format("%s@%s", name, remoteId);
+ } else {
+ return name;
+ }
+ }
+
+ /**
+ * Registers a non Java service with mrl runtime, so it can be added to
+ * listeners and verified in testing
+ *
+ * @param remoteServiceName
+ * @param interfaces
+ */
+ public void registerRemoteService(String remoteServiceName, ArrayList interfaces) {
+ String fullName = getFullRemoteName(remoteServiceName);
+ remoteServices.put(fullName, new RemoteService(this, fullName));
+
+ // Runtime.register(remoteId, remoteServiceName, "mock:mock", interfaces);
+ Runtime.register(remoteId, remoteServiceName, "Unknown", interfaces);
+
+
+ }
+
+ /**
+ * Sends an asynchronous message with a slight delay so that testing for a
+ * callback publish can be done inline
+ *
+ * @param name
+ * @param method
+ */
+ public void sendWithDelay(String name, String method) {
+ sendWithDelay(0, name, method);
+ }
+
+ //
+ public String onToString() {
+ return toString();
+ }
+
+ public Message publishSendMessage(Message msg) {
+ return msg;
+ }
+
+ public Message publishReceiveMessage(Message msg) {
+ return msg;
+ }
+
+ public static void main(String[] args) {
+ try {
+
+ LoggingFactory.setLevel("WARN");
+
+ WebGui webgui = (WebGui) Runtime.create("webgui", "WebGui");
+ webgui.autoStartBrowser(false);
+ webgui.startService();
+
+ // starts a mocking gateway with default id instance
+ MockGateway gateway = (MockGateway) Runtime.start("gateway", "MockGateway");
+
+ Clock clock = (Clock) Runtime.start("clock", "Clock");
+
+ clock.addListener("publishTime", "mocker");
+
+ // mocker.send("clock", "startClock");
+ // first click is after 1 second
+
+ // mocker.send("clock", "StartClock");
+ // gateway.sendWithDelay("clock", "startClock");
+ // gateway.sendWithDelay(0, "clock", "startClock");
+ Message msg = gateway.waitForMsg("mocker@mockid", "onTime", 1100);
+ log.info("message {}", msg);
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/org/myrobotlab/service/Runtime.java b/src/main/java/org/myrobotlab/service/Runtime.java
index e17cd987b9..7cf25153ef 100644
--- a/src/main/java/org/myrobotlab/service/Runtime.java
+++ b/src/main/java/org/myrobotlab/service/Runtime.java
@@ -1740,10 +1740,10 @@ public static synchronized Registration register(Registration registration) {
return registration;
}
- if (!ForeignProcessUtils.isValidTypeKey(registration.getTypeKey())) {
- log.error("Invalid type key being registered: " + registration.getTypeKey());
- return null;
- }
+// if (!ForeignProcessUtils.isValidTypeKey(registration.getTypeKey())) {
+// log.error("Invalid type key being registered: " + registration.getTypeKey());
+// return null;
+// }
log.info("{}@{} registering at {} of type {}", registration.getName(), registration.getId(), Platform.getLocalInstance().getId(), registration.getTypeKey());
diff --git a/src/main/java/org/myrobotlab/service/config/MockGatewayConfig.java b/src/main/java/org/myrobotlab/service/config/MockGatewayConfig.java
new file mode 100644
index 0000000000..481abecdac
--- /dev/null
+++ b/src/main/java/org/myrobotlab/service/config/MockGatewayConfig.java
@@ -0,0 +1,6 @@
+package org.myrobotlab.service.config;
+
+
+public class MockGatewayConfig extends ServiceConfig {
+
+}
diff --git a/src/main/java/org/myrobotlab/service/meta/MockGatewayMeta.java b/src/main/java/org/myrobotlab/service/meta/MockGatewayMeta.java
new file mode 100644
index 0000000000..e3bb9b1306
--- /dev/null
+++ b/src/main/java/org/myrobotlab/service/meta/MockGatewayMeta.java
@@ -0,0 +1,16 @@
+package org.myrobotlab.service.meta;
+
+import org.myrobotlab.logging.LoggerFactory;
+import org.myrobotlab.service.meta.abstracts.MetaData;
+import org.slf4j.Logger;
+
+public class MockGatewayMeta extends MetaData {
+ private static final long serialVersionUID = 1L;
+ public final static Logger log = LoggerFactory.getLogger(MockGatewayMeta.class);
+
+ public MockGatewayMeta() {
+ addDescription("Service for testing.");
+ addCategory("testing");
+ }
+
+}
diff --git a/src/main/resources/resource/MockGateway.png b/src/main/resources/resource/MockGateway.png
new file mode 100644
index 0000000000..fb74a154a4
Binary files /dev/null and b/src/main/resources/resource/MockGateway.png differ
diff --git a/src/main/resources/resource/Unknown.png b/src/main/resources/resource/Unknown.png
new file mode 100644
index 0000000000..2a65350ca7
Binary files /dev/null and b/src/main/resources/resource/Unknown.png differ
diff --git a/src/main/resources/resource/WebGui/app/service/js/MockGatewayGui.js b/src/main/resources/resource/WebGui/app/service/js/MockGatewayGui.js
new file mode 100644
index 0000000000..33bada7cf1
--- /dev/null
+++ b/src/main/resources/resource/WebGui/app/service/js/MockGatewayGui.js
@@ -0,0 +1,36 @@
+angular.module("mrlapp.service.MockGatewayGui", []).controller("MockGatewayGuiCtrl", [
+ "$scope",
+ "mrl",
+ function ($scope, mrl) {
+ console.info("MockGatewayGuiCtrl")
+ var _self = this
+ var msg = this.msg
+
+ // GOOD TEMPLATE TO FOLLOW
+ this.updateState = function (service) {
+ $scope.service = service
+ }
+
+
+ this.onMsg = function (inMsg) {
+ let data = inMsg.data[0]
+ switch (inMsg.method) {
+ case "onState":
+ _self.updateState(data)
+ $scope.$apply()
+ break
+ case "onSendMessage":
+ const date = new Date(data)
+ $scope.onTime = date.toLocaleString()
+ $scope.$apply()
+ break
+ default:
+ console.error("ERROR - unhandled method " + $scope.name + " " + inMsg.method)
+ break
+ }
+ }
+
+ // msg.subscribe("publishSendMessage")
+ msg.subscribe(this)
+ },
+])
diff --git a/src/main/resources/resource/WebGui/app/service/js/UnknownGui.js b/src/main/resources/resource/WebGui/app/service/js/UnknownGui.js
new file mode 100644
index 0000000000..410edd27d9
--- /dev/null
+++ b/src/main/resources/resource/WebGui/app/service/js/UnknownGui.js
@@ -0,0 +1,33 @@
+angular.module("mrlapp.service.UnknownGui", []).controller("UnknownGuiCtrl", [
+ "$scope",
+ "mrl",
+ function ($scope, mrl) {
+ console.info("UnknownGuiCtrl")
+ var _self = this
+ var msg = this.msg
+
+ // GOOD TEMPLATE TO FOLLOW
+ this.updateState = function (service) {
+ $scope.service = service
+ }
+
+ // init scope variables
+ $scope.onTime = null
+ $scope.onEpoch = null
+
+ this.onMsg = function (inMsg) {
+ let data = inMsg.data[0]
+ switch (inMsg.method) {
+ case "onState":
+ _self.updateState(data)
+ $scope.$apply()
+ break
+ default:
+ console.error("ERROR - unhandled method " + $scope.name + " " + inMsg.method)
+ break
+ }
+ }
+
+ msg.subscribe(this)
+ },
+])
diff --git a/src/main/resources/resource/WebGui/app/service/views/MockGatewayGui.html b/src/main/resources/resource/WebGui/app/service/views/MockGatewayGui.html
new file mode 100644
index 0000000000..f4f7f52fd7
--- /dev/null
+++ b/src/main/resources/resource/WebGui/app/service/views/MockGatewayGui.html
@@ -0,0 +1,24 @@
+
+
+
+
+
+ ts |
+ sender |
+ name |
+ method |
+ data |
+
+
+
+
+
+ {{msg.msgId}} |
+ {{msg.sender}} |
+ {{msg.name}} |
+ [{{msg.method}}] |
+ {{msg.data}} |
+
+
+
+
diff --git a/src/main/resources/resource/WebGui/app/service/views/UnknownGui.html b/src/main/resources/resource/WebGui/app/service/views/UnknownGui.html
new file mode 100644
index 0000000000..c026231c57
--- /dev/null
+++ b/src/main/resources/resource/WebGui/app/service/views/UnknownGui.html
@@ -0,0 +1,3 @@
+
+
unknown type
+