From 4f47f23275d54647cd335e00a6448d57f32fef04 Mon Sep 17 00:00:00 2001 From: grog Date: Sat, 21 Oct 2023 15:22:45 -0700 Subject: [PATCH] Peer config utilities --- pom.xml | 3 + .../org/myrobotlab/framework/Service.java | 254 ++++++++++++------ .../java/org/myrobotlab/service/InMoov2.java | 60 +++-- .../java/org/myrobotlab/service/OpenCV.java | 15 ++ .../java/org/myrobotlab/service/Runtime.java | 30 ++- .../service/config/InMoov2Config.java | 4 +- .../service/config/OpenCVConfig.java | 4 + .../resources/resource/WebGui/app/peer.js | 16 +- .../WebGui/app/service/js/RuntimeGui.js | 6 + .../resource/framework/pom.xml.template | 3 + 10 files changed, 270 insertions(+), 125 deletions(-) diff --git a/pom.xml b/pom.xml index a00bd0db4f..6e8fdf4829 100644 --- a/pom.xml +++ b/pom.xml @@ -13,6 +13,9 @@ # fast build mvn -DskipTests package -o + # execute + mvn exec:java -Dexec.mainClass=org.myrobotlab.service.Runtime -Dexec.args="-s webgui WebGui intro Intro python Python" + # specific test mvn test -Dtest="org.myrobotlab.service.WebGuiTest#postTest" diff --git a/src/main/java/org/myrobotlab/framework/Service.java b/src/main/java/org/myrobotlab/framework/Service.java index 08534f2081..d9290b1527 100644 --- a/src/main/java/org/myrobotlab/framework/Service.java +++ b/src/main/java/org/myrobotlab/framework/Service.java @@ -101,11 +101,11 @@ public abstract class Service implements Runnable, Seri protected MetaData serviceType; /** - * Config member - configuration of type {ServiceType}Config - * Runtime applys either the default config or a saved config during service creation + * Config member - configuration of type {ServiceType}Config Runtime applys + * either the default config or a saved config during service creation */ protected T config; - + private static final long serialVersionUID = 1L; transient public final static Logger log = LoggerFactory.getLogger(Service.class); @@ -190,8 +190,8 @@ public abstract class Service implements Runnable, Seri /** * This is the map of interfaces - its really "static" information, since its - * a definition. However, since serialization will not process statics - we are making - * it a member variable + * a definition. However, since serialization will not process statics - we + * are making it a member variable */ // FIXME - this should be a map protected Map interfaceSet; @@ -279,11 +279,7 @@ public static Object copyShallowFrom(Object target, Object source) { * ){ log.info("here"); } */ - if (Modifier.isPrivate(modifiers) - || fname.equals("log") - || Modifier.isTransient(modifiers) - || Modifier.isStatic(modifiers) - || Modifier.isFinal(modifiers)) { + if (Modifier.isPrivate(modifiers) || fname.equals("log") || Modifier.isTransient(modifiers) || Modifier.isStatic(modifiers) || Modifier.isFinal(modifiers)) { log.debug("skipping {}", field.getName()); continue; } else { @@ -472,18 +468,17 @@ static public String getResourceDir(Class clazz, String additionalPath) { * to glue together * @return the full resolved path * - * FIXME - DO NOT USE STATIC !!!! - * all instances of services should be able to get the resource directory - * If its static and "configurable" then it needs an instance of Runtime - * which is not available. + * FIXME - DO NOT USE STATIC !!!! all instances of services should be + * able to get the resource directory If its static and "configurable" + * then it needs an instance of Runtime which is not available. * */ @Deprecated /* this should not be static - remove it */ static public String getResourceDir(String serviceType, String additionalPath) { - // setting resource directory + // setting resource directory String resourceDir = null; - + // stupid solution to get past static problem if (!"Runtime".equals(serviceType)) { resourceDir = Runtime.getInstance().getConfig().resource + fs + serviceType; @@ -495,6 +490,7 @@ static public String getResourceDir(String serviceType, String additionalPath) { } return resourceDir; } + /** * non static get resource path return the path to a resource - since the root * can change depending if in debug or runtime - it gets the appropriate root @@ -1015,47 +1011,49 @@ public String[] getMethodNames() { public Method[] getMethods() { return this.getClass().getMethods(); } - + /** - * Returns a map containing all interface names from the class hierarchy and the interface hierarchy of the - * current class. + * Returns a map containing all interface names from the class hierarchy and + * the interface hierarchy of the current class. * * @return A map containing all interface names. */ public Map getInterfaceSet() { - Map ret = new TreeMap<>(); - Set> visitedClasses = new HashSet<>(); - getAllInterfacesHelper(getClass(), ret, visitedClasses); - return ret; + Map ret = new TreeMap<>(); + Set> visitedClasses = new HashSet<>(); + getAllInterfacesHelper(getClass(), ret, visitedClasses); + return ret; } /** - * Recursively traverses the class hierarchy and the interface hierarchy to add all interface names to the - * specified map. + * Recursively traverses the class hierarchy and the interface hierarchy to + * add all interface names to the specified map. * - * @param c The class to start the traversal from. - * @param ret The map to store the interface names. - * @param visitedClasses A set to keep track of visited classes to avoid infinite loops. + * @param c + * The class to start the traversal from. + * @param ret + * The map to store the interface names. + * @param visitedClasses + * A set to keep track of visited classes to avoid infinite loops. */ private void getAllInterfacesHelper(Class c, Map ret, Set> visitedClasses) { - if (c != null && !visitedClasses.contains(c)) { - // Add interfaces from the current class - Class[] interfaces = c.getInterfaces(); - for (Class interfaze : interfaces) { - ret.put(interfaze.getName(), interfaze.getName()); - } - - // Add interfaces from interfaces implemented by the current class - for (Class interfaze : interfaces) { - getAllInterfacesHelper(interfaze, ret, visitedClasses); - } + if (c != null && !visitedClasses.contains(c)) { + // Add interfaces from the current class + Class[] interfaces = c.getInterfaces(); + for (Class interfaze : interfaces) { + ret.put(interfaze.getName(), interfaze.getName()); + } - // Recursively traverse the superclass hierarchy - visitedClasses.add(c); - getAllInterfacesHelper(c.getSuperclass(), ret, visitedClasses); + // Add interfaces from interfaces implemented by the current class + for (Class interfaze : interfaces) { + getAllInterfacesHelper(interfaze, ret, visitedClasses); } + + // Recursively traverse the superclass hierarchy + visitedClasses.add(c); + getAllInterfacesHelper(c.getSuperclass(), ret, visitedClasses); + } } - public Message getMsg() throws InterruptedException { return inbox.getMsg(); @@ -1314,12 +1312,11 @@ final public Object invokeOn(boolean blockLocally, Object obj, String methodName if (blockLocally) { Outbox outbox = null; if (obj instanceof ServiceInterface) { - outbox = ((ServiceInterface)obj).getOutbox(); + outbox = ((ServiceInterface) obj).getOutbox(); } else { return retobj; } - - + List subList = outbox.notifyList.get(methodName); // correct? get local (default?) gateway Runtime runtime = Runtime.getInstance(); @@ -1399,27 +1396,88 @@ public boolean isRunning() { /** * getConfig returns current config of the service. This default super method - * will also filter webgui subscriptions out, in addition for any local subscriptions it - * will remove the instance "id" from any service. The reason it removes the webgui - * subscriptions is to avoid overwelming the user when modifying config. UI subscriptions - * tend to be very numerous and not very useful to the user. The reason it removes the - * instance id from local subscriptions is to allow the config to be used with any instance. - * Unless the user is controlling instance id, its random every restart. + * will also filter webgui subscriptions out, in addition for any local + * subscriptions it will remove the instance "id" from any service. The reason + * it removes the webgui subscriptions is to avoid overwelming the user when + * modifying config. UI subscriptions tend to be very numerous and not very + * useful to the user. The reason it removes the instance id from local + * subscriptions is to allow the config to be used with any instance. Unless + * the user is controlling instance id, its random every restart. */ public T getConfig() { return config; } /** - * Super class apply using template type. The default assigns config of the templated type, and also - * add listeners from subscriptions found on the base class ServiceConfig.listeners + * Get a service's peer's configuration. This method is used to get the + * configuration of a peer service regarless if it is currently running or + * not. If the peer is running the configuration is pulled from the active + * peer service, if it is not currently running the configuration is read from + * the current config set's service configuration file, if that does not exist + * the default configuration for this peer is used. + * + * @param peerKey + * - key of the peer service. e.g. "opencv" in the case of + * i01."opencv" + * @return */ - public T apply(T c) { - config = c; - addConfigListeners(c); - return config; + public ServiceConfig getPeerConfig(String peerKey) { + String peerName = getPeerName(peerKey); + if (peerName == null) { + error("peer name not found for peer key %s", peerKey); + return null; + } + + ServiceInterface si = Runtime.getService(peerName); + if (si != null) { + // peer is currently running - get its config + return si.getConfig(); + } + + // peer is not currently running attempt to read from config + Runtime runtime = Runtime.getInstance(); + // read current service config for this peer service + ServiceConfig sc = runtime.readServiceConfig(peerName); + if (sc == null) { + error("peer service %s is defined, but %s.yml not available on filesystem", peerKey, peerName); + return null; + } + return sc; + } + + public void setPeerConfigValue(String peerKey, String fieldname, Object value) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException { + ServiceConfig sc = getPeerConfig(peerKey); + if (sc == null) { + error("invalid config for peer key %s field name %s", peerKey, fieldname); + return; + } + Field field = sc.getClass().getDeclaredField(fieldname); + field.set(sc, value); + savePeerConfig(peerKey, sc); + String peerName = getPeerName(peerKey); + ConfigurableService cs = (ConfigurableService) Runtime.getService(peerName); + if (cs != null) { + cs.apply(sc); // TODO - look for applies if its read from the file system + // it needs to update Runtime.plan + } + + // broadcast change + invoke("getPeerConfig", peerKey); + Runtime.getPlan().put(peerName, sc); + Runtime runtime = Runtime.getInstance(); + runtime.broadcastState(); } + /** + * Super class apply using template type. The default assigns config of the + * templated type, and also add listeners from subscriptions found on the base + * class ServiceConfig.listeners + */ + public T apply(T c) { + config = c; + addConfigListeners(c); + return config; + } /** * The basic ServiceConfig has a list of listeners. These are definitions of @@ -1436,7 +1494,8 @@ public ServiceConfig addConfigListeners(ServiceConfig config) { } /** - * Default filtered config, used when saving, can be overriden by concrete class + * Default filtered config, used when saving, can be overriden by concrete + * class */ @Override public ServiceConfig getFilteredConfig() { @@ -1467,7 +1526,6 @@ public ServiceConfig getFilteredConfig() { return sc; } - @Override public void setConfigValue(String fieldname, Object value) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException { log.info("setting field name fieldname {} to {}", fieldname, value); @@ -1475,6 +1533,7 @@ public void setConfigValue(String fieldname, Object value) throws IllegalArgumen Field field = getConfig().getClass().getDeclaredField(fieldname); // field.setAccessible(true); should not need this - it "should" be public field.set(getConfig(), value); + save(); } @Override @@ -1579,11 +1638,12 @@ public void removeListener(String outMethod, String serviceName, String inMethod return true; } - // Previously we were not checking inMethod, which meant if a service had multiple - // subscriptions to the same topic (one to many mapping), the first in the list would be removed + // Previously we were not checking inMethod, which meant if a service + // had multiple + // subscriptions to the same topic (one to many mapping), the first in + // the list would be removed // instead of the requested one. - if (listener.callbackMethod.equals(inMethod) - && CodecUtils.checkServiceNameEquality(listener.callbackName, fullName)) { + if (listener.callbackMethod.equals(inMethod) && CodecUtils.checkServiceNameEquality(listener.callbackName, fullName)) { log.info("removeListener requested {}.{} to be removed", fullName, outMethod); return true; } @@ -1659,6 +1719,24 @@ public boolean save() { return runtime.saveService(runtime.getConfigName(), getName(), null); } + /** + * Save a service's peer's config to current config set + * + * @param peerKey + */ + public void savePeerConfig(String peerKey, ServiceConfig config) { + try { + Runtime runtime = Runtime.getInstance(); + String peerName = getPeerName(peerKey); + String data = CodecUtils.toYaml(config); + String ymlFileName = runtime.getConfigPath() + fs + CodecUtils.getShortName(peerName) + ".yml"; + FileIO.toFile(ymlFileName, data.getBytes()); + info("saved %s", ymlFileName); + } catch (Exception e) { + error(e); + } + } + public ServiceInterface getPeer(String peerKey) { String actualName = getPeerName(peerKey); return Runtime.getService(actualName); @@ -2009,7 +2087,7 @@ public void subscribe(String topicName, String topicMethod) { String callbackMethod = CodecUtils.getCallbackTopicName(topicMethod); subscribe(topicName, topicMethod, getFullName(), callbackMethod); } - + @Override public void subscribe(String service, String method, String callback) { subscribe(service, method, getFullName(), callback); @@ -2068,7 +2146,7 @@ public void unsubscribe(String topicName, String topicMethod) { String callbackMethod = CodecUtils.getCallbackTopicName(topicMethod); unsubscribe(topicName, topicMethod, getFullName(), callbackMethod); } - + @Override public void unsubscribe(String topicName, String topicMethod, String callback) { unsubscribe(topicName, topicMethod, getFullName(), callback); @@ -2097,12 +2175,7 @@ public Status error(Exception e) { @Override public Status error(String format, Object... args) { Status ret; - ret = Status.error( - String.format( - Objects.requireNonNullElse(format, ""), - args - ) - ); + ret = Status.error(String.format(Objects.requireNonNullElse(format, ""), args)); ret.name = getName(); log.error(ret.toString()); lastError = ret; @@ -2584,7 +2657,10 @@ public String localize(String key, Object... args) { } @Override - @Deprecated /* this system should be removed in favor of a ProgramAB instance with ability to translate */ + @Deprecated /* + * this system should be removed in favor of a ProgramAB instance + * with ability to translate + */ public void loadLocalizations() { if (defaultLocalization == null) { @@ -2756,16 +2832,36 @@ public void apply() { Runtime runtime = Runtime.getInstance(); String configName = runtime.getConfigName(); ServiceConfig sc = runtime.readServiceConfig(configName, name); - + if (sc == null) { error("config file %s not found", Runtime.getConfigRoot() + fs + configName + fs + name + ".yml"); return; } - - // updating plan + + // updating plan - FIXME remove plan Runtime.getPlan().put(getName(), sc); + // applying config to self - apply((T)sc); + apply((T) sc); + } + + /** + * Apply the config to a peer, regardless if the peer is currently running or + * not + * + * @param peerKey + * @param config + */ + public void applyPeerConfig(String peerKey, ServiceConfig config) { + String peerName = getPeerName(peerKey); + + Runtime.getPlan().put(peerName, config); + + // meh - templating is not very helpful here + ConfigurableService si = (ConfigurableService) Runtime.getService(peerName); + if (si != null) { + si.apply(config); + } } /** @@ -2786,11 +2882,11 @@ public void setPeerName(String key, String fullName) { // should we also make or update a config file - if the config path is set? info("updated %s name to %s", oldName, peer.name); } - + /** * get all the subscriptions to this service */ - public Map> getNotifyList(){ + public Map> getNotifyList() { return getOutbox().getNotifyList(); } diff --git a/src/main/java/org/myrobotlab/service/InMoov2.java b/src/main/java/org/myrobotlab/service/InMoov2.java index 03035b6d2f..e9fa9d975e 100644 --- a/src/main/java/org/myrobotlab/service/InMoov2.java +++ b/src/main/java/org/myrobotlab/service/InMoov2.java @@ -140,11 +140,11 @@ public static boolean loadFile(String file) { protected String voiceSelected; - public InMoov2(String n, String id) { super(n, id); } + // should be removed in favor of general listeners public void addTextListener(TextListener service) { // CORRECT WAY ! - no direct reference - just use the name in a subscription addListener("publishText", service.getName()); @@ -407,7 +407,7 @@ public String execGesture(String gesture) { subscribe("python", "publishStatus", this.getName(), "onGestureStatus"); startedGesture(gesture); lastGestureExecuted = gesture; - Python python = (Python)Runtime.getService("python"); + Python python = (Python) Runtime.getService("python"); if (python == null) { error("python service not started"); return null; @@ -773,19 +773,19 @@ public void moveHead(Integer neck, Integer rothead, Integer rollNeck) { moveHead((double) neck, (double) rothead, null, null, null, (double) rollNeck); } - public void moveHeadBlocking(Double neck, Double rothead) { + public void moveHeadBlocking(Double neck, Double rothead) { moveHeadBlocking(neck, rothead, null); } - public void moveHeadBlocking(Double neck, Double rothead, Double rollNeck) { + public void moveHeadBlocking(Double neck, Double rothead, Double rollNeck) { moveHeadBlocking(neck, rothead, null, null, null, rollNeck); } - public void moveHeadBlocking(Double neck, Double rothead, Double eyeX, Double eyeY, Double jaw) { + public void moveHeadBlocking(Double neck, Double rothead, Double eyeX, Double eyeY, Double jaw) { moveHeadBlocking(neck, rothead, eyeX, eyeY, jaw, null); } - public void moveHeadBlocking(Double neck, Double rothead, Double eyeX, Double eyeY, Double jaw, Double rollNeck) { + public void moveHeadBlocking(Double neck, Double rothead, Double eyeX, Double eyeY, Double jaw, Double rollNeck) { try { sendBlocking(getPeerName("head"), "moveToBlocking", neck, rothead, eyeX, eyeY, jaw, rollNeck); } catch (Exception e) { @@ -866,7 +866,7 @@ public void onGestureStatus(Status status) { error("I cannot execute %s, please check logs", lastGestureExecuted); } finishedGesture(lastGestureExecuted); - + unsubscribe("python", "publishStatus", this.getName(), "onGestureStatus"); } @@ -994,10 +994,10 @@ public void onStarted(String name) { Runtime runtime = Runtime.getInstance(); log.info("onStarted {}", name); -// BAD IDEA - better to ask for a system report or an error report -// if (runtime.isProcessingConfig()) { -// invoke("publishEvent", "CONFIG STARTED"); -// } + // BAD IDEA - better to ask for a system report or an error report + // if (runtime.isProcessingConfig()) { + // invoke("publishEvent", "CONFIG STARTED"); + // } String peerKey = getPeerKey(name); if (peerKey == null) { @@ -1229,8 +1229,8 @@ public String publishHeartbeat() { } /** - * A more extensible interface point than publishEvent - * FIXME - create interface for this + * A more extensible interface point than publishEvent FIXME - create + * interface for this * * @param msg * @return @@ -1561,7 +1561,7 @@ public void setTorsoSpeed(Integer topStom, Integer midStom, Integer lowStom) { setTorsoSpeed((double) topStom, (double) midStom, (double) lowStom); } - @Deprecated + @Deprecated /* use setTorsoSpeed */ public void setTorsoVelocity(Double topStom, Double midStom, Double lowStom) { setTorsoSpeed(topStom, midStom, lowStom); } @@ -1814,8 +1814,7 @@ public void startService() { subscribe("runtime", "shutdown"); // power up loopback subscription addListener(getName(), "powerUp"); - - + subscribe("runtime", "publishConfigList"); if (runtime.isProcessingConfig()) { invoke("publishEvent", "configStarted"); @@ -1923,7 +1922,6 @@ public void waitTargetPos() { sendToPeer("torso", "waitTargetPos"); } - public static void main(String[] args) { try { @@ -1934,20 +1932,26 @@ public static void main(String[] args) { // Runtime.startConfig("pr-1213-1"); - Runtime.main(new String[] {"--log-level", "info", "-s", "webgui", "WebGui", "intro", "Intro", "python", "Python"}); + WebGui webgui = (WebGui) Runtime.create("webgui", "WebGui"); + // webgui.setSsl(true); + webgui.autoStartBrowser(false); + // webgui.setPort(8888); + webgui.startService(); + + InMoov2 i01 = (InMoov2)Runtime.start("i01","InMoov2"); + i01.setPeerConfigValue("opencv", "flip", true); + // i01.savePeerConfig("", null); + // Runtime.startConfig("default"); + + // Runtime.main(new String[] { "--log-level", "info", "-s", "webgui", "WebGui", "intro", "Intro", "python", "Python" }); + boolean done = true; if (done) { return; } - WebGui webgui = (WebGui) Runtime.create("webgui", "WebGui"); - // webgui.setSsl(true); - webgui.autoStartBrowser(false); - // webgui.setPort(8888); - webgui.startService(); - Runtime.start("python", "Python"); // Runtime.start("ros", "Ros"); Runtime.start("intro", "Intro"); @@ -1959,7 +1963,6 @@ public static void main(String[] args) { // Polly polly = (Polly)Runtime.start("i01.mouth", "Polly"); // i01 = (InMoov2) Runtime.start("i01", "InMoov2"); - // polly.speakBlocking("Hi, to be or not to be that is the question, // wheather to take arms against a see of trouble, and by aposing them end // them, to sleep, to die"); @@ -1999,9 +2002,9 @@ public static void main(String[] args) { random.save(); -// i01.startChatBot(); -// -// i01.startAll("COM3", "COM4"); + // i01.startChatBot(); + // + // i01.startAll("COM3", "COM4"); Runtime.start("python", "Python"); } catch (Exception e) { @@ -2009,4 +2012,5 @@ public static void main(String[] args) { } } + } diff --git a/src/main/java/org/myrobotlab/service/OpenCV.java b/src/main/java/org/myrobotlab/service/OpenCV.java index 7abc45de8b..ff093721bd 100644 --- a/src/main/java/org/myrobotlab/service/OpenCV.java +++ b/src/main/java/org/myrobotlab/service/OpenCV.java @@ -1967,6 +1967,19 @@ public void enableFilter(String name) { } } + /** + * flip the video display vertically + * @param toFlip + */ + public void flip(boolean toFlip) { + config.flip = toFlip; + if (config.flip) { + addFilter("Flip"); + } else { + removeFilter("Flip"); + } + } + @Override public void disableFilter(String name) { OpenCVFilter f = filters.get(name); @@ -2062,6 +2075,8 @@ public OpenCVConfig apply(OpenCVConfig c) { // TODO: better configuration of the filter when it's added. } } + + flip(c.flip); if (c.capturing) { capture(); diff --git a/src/main/java/org/myrobotlab/service/Runtime.java b/src/main/java/org/myrobotlab/service/Runtime.java index 3d8a92f2cc..8f2035fbd6 100644 --- a/src/main/java/org/myrobotlab/service/Runtime.java +++ b/src/main/java/org/myrobotlab/service/Runtime.java @@ -141,7 +141,7 @@ public class Runtime extends Service implements MessageListener, * all these requests. */ @Deprecated /* use the filesystem only no memory plan */ - transient final Plan masterPlan = new Plan("runtime"); + protected final Plan masterPlan = new Plan("runtime"); /** * thread for non-blocking install of services @@ -2661,6 +2661,7 @@ synchronized static public ServiceInterface start(String name, String type) { } Runtime.load(name, type); + Runtime.savePlan(null); // FIXME - does some order need to be maintained Map services = createServicesFromPlan(Runtime.getPlan(), null, name); @@ -4805,6 +4806,16 @@ synchronized private Plan loadService(Plan plan, String name, String type, boole return plan; } + + /** + * read a service's configuration, in the context + * of current config set name or default + * @param name + * @return + */ + public ServiceConfig readServiceConfig(String name) { + return readServiceConfig(null, name); + } /** * @@ -4845,19 +4856,6 @@ public String publishConfigLoaded(String name) { return name; } - // @Override - // public ServiceConfig getConfig() { - // RuntimeConfig config = (RuntimeConfig)super.getConfig(); - // List listeners = new - // ArrayList - // for (org.myrobotlab.service.config.ServiceConfig.Listener listener: - // config.listeners) { - // if (listener.equals("stopped") || listener.equals("created")|| - // listener.equals("registered")|| listener.equals("released")) { - // - // } - // } - // } public String setAllIds(String id) { Platform.getLocalInstance().setId(id); @@ -5154,6 +5152,10 @@ private void savePlanInternal(String configName) { for (String s : masterPlan.keySet()) { String filename = CONFIG_ROOT + fs + configName + fs + s + ".yml"; + File check = new File(filename); + if (check.exists()) { + continue; + } String data = CodecUtils.toYaml(masterPlan.get(s)); try { FileIO.toFile(filename, data.getBytes()); diff --git a/src/main/java/org/myrobotlab/service/config/InMoov2Config.java b/src/main/java/org/myrobotlab/service/config/InMoov2Config.java index af16e23a04..9ebecf8262 100644 --- a/src/main/java/org/myrobotlab/service/config/InMoov2Config.java +++ b/src/main/java/org/myrobotlab/service/config/InMoov2Config.java @@ -52,9 +52,7 @@ public class InMoov2Config extends ServiceConfig { public boolean neoPixelFlashWhenSpeaking = true; public boolean openCVFaceRecognizerActivated=true; - - public boolean openCVFlipPicture=false; - + public boolean pirEnableTracking = false; /** diff --git a/src/main/java/org/myrobotlab/service/config/OpenCVConfig.java b/src/main/java/org/myrobotlab/service/config/OpenCVConfig.java index 2c786aa648..2087539836 100644 --- a/src/main/java/org/myrobotlab/service/config/OpenCVConfig.java +++ b/src/main/java/org/myrobotlab/service/config/OpenCVConfig.java @@ -15,5 +15,9 @@ public class OpenCVConfig extends ServiceConfig { public boolean webViewer = false; public boolean capturing = false; public Map filters = new LinkedHashMap<>(); + /** + * flip the video vertically + */ + public boolean flip = false; } diff --git a/src/main/resources/resource/WebGui/app/peer.js b/src/main/resources/resource/WebGui/app/peer.js index 78c15f5da3..e033693b52 100644 --- a/src/main/resources/resource/WebGui/app/peer.js +++ b/src/main/resources/resource/WebGui/app/peer.js @@ -4,7 +4,7 @@ console.info('peer') -angular.module('peer', []).service('peer', function( mrl /*$rootScope, $log*/ +angular.module('peer', []).service('peer', function( mrl ) { service = {}; @@ -40,6 +40,20 @@ angular.module('peer', []).service('peer', function( mrl /*$rootScope, $log*/ return null } + service.getPeerConfig = function(service, key) { + try { + if (service && service.config && service.config.peers && service.config.peers[key]){ + return mrl.getService('runtime').masterPlan['config'][service.config.peers[key].name] + // return mrl.getService(service.config.peers[key].name).config + } else { + // if peer is not started - return the filesystem config + } + } catch (error) { + console.error(error); + } + return null + } + service.changePeerTab = function(service, key) { try { diff --git a/src/main/resources/resource/WebGui/app/service/js/RuntimeGui.js b/src/main/resources/resource/WebGui/app/service/js/RuntimeGui.js index 09eab9b6f6..4f452e9834 100644 --- a/src/main/resources/resource/WebGui/app/service/js/RuntimeGui.js +++ b/src/main/resources/resource/WebGui/app/service/js/RuntimeGui.js @@ -132,6 +132,10 @@ angular.module('mrlapp.service.RuntimeGui', []).controller('RuntimeGuiCtrl', ['$ _self.updateState(data) $scope.$apply() break + case 'onPlan': + $scope.plan = data + $scope.$apply() + break case 'onLocalServices': $scope.registry = data // $scope.$apply() @@ -408,6 +412,7 @@ angular.module('mrlapp.service.RuntimeGui', []).controller('RuntimeGuiCtrl', ['$ msg.subscribe("publishStatus") msg.subscribe('publishConfigList') msg.subscribe('publishInterfaceToNames') + // msg.subscribe("getPlan") //msg.send("getLocalServices") msg.send("getStartYml") @@ -417,6 +422,7 @@ angular.module('mrlapp.service.RuntimeGui', []).controller('RuntimeGuiCtrl', ['$ msg.send("getLocales") msg.send("publishInterfaceToNames") msg.send("getConfigName") + // msg.send("getPlan") // msg.send("getHosts") msg.subscribe(this) diff --git a/src/main/resources/resource/framework/pom.xml.template b/src/main/resources/resource/framework/pom.xml.template index ce45f6285a..f0ae2b4183 100644 --- a/src/main/resources/resource/framework/pom.xml.template +++ b/src/main/resources/resource/framework/pom.xml.template @@ -13,6 +13,9 @@ # fast build mvn -DskipTests package -o + # execute + mvn exec:java -Dexec.mainClass=org.myrobotlab.service.Runtime -Dexec.args="-s webgui WebGui intro Intro python Python" + # specific test mvn test -Dtest="org.myrobotlab.service.WebGuiTest#postTest"