From d543164383a5941f4f49d5c4c43ae2db26b2702b Mon Sep 17 00:00:00 2001 From: Ricardo Gudwin Date: Fri, 20 May 2022 23:19:41 -0300 Subject: [PATCH] Changes to allow a refresh rate while probing the mind for the REST Server. Also, MemoryGroups and CodeletGroups were included in the returned JSON --- .../br/unicamp/cst/io/rest/CodeletJson.java | 40 ++++- .../br/unicamp/cst/io/rest/MemoryJson.java | 28 +++ .../java/br/unicamp/cst/io/rest/MindJson.java | 48 ++++- .../br/unicamp/cst/io/rest/RESTServer.java | 42 ++++- .../java/br/unicamp/cst/io/rest/TestREST.java | 165 +++++++++++++++++- 5 files changed, 302 insertions(+), 21 deletions(-) diff --git a/src/main/java/br/unicamp/cst/io/rest/CodeletJson.java b/src/main/java/br/unicamp/cst/io/rest/CodeletJson.java index feb17586..73af5eab 100644 --- a/src/main/java/br/unicamp/cst/io/rest/CodeletJson.java +++ b/src/main/java/br/unicamp/cst/io/rest/CodeletJson.java @@ -1,17 +1,27 @@ +/*********************************************************************************************** + * Copyright (c) 2012 DCA-FEEC-UNICAMP + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the GNU Lesser Public License v3 + * which accompanies this distribution, and is available at + * http://www.gnu.org/licenses/lgpl.html + *

+ * Contributors: + * K. Raizer, A. L. O. Paraense, E. M. Froes, R. R. Gudwin - initial API and implementation + * **********************************************************************************************/ package br.unicamp.cst.io.rest; import br.unicamp.cst.core.entities.Codelet; - import java.util.ArrayList; import java.util.List; public class CodeletJson { - public double activation; - public long timestamp; - public String name; - public List broadcast = new ArrayList(); - public List inputs = new ArrayList(); - public List outputs = new ArrayList(); + private double activation; + private long timestamp; + private String name; + private String group; + private List broadcast = new ArrayList(); + private List inputs = new ArrayList(); + private List outputs = new ArrayList(); public CodeletJson(Codelet cod) { this.activation = cod.getActivation(); @@ -27,4 +37,20 @@ public CodeletJson(Codelet cod) { this.outputs.add(new MemoryJson(cod.getOutputs().get(i))); } } + + public CodeletJson(Codelet cod, String group) { + this.activation = cod.getActivation(); + this.timestamp = System.currentTimeMillis(); + this.name = cod.getName(); + this.group = group; + for (int i = 0; i < cod.getBroadcast().size(); i++) { + this.broadcast.add(new MemoryJson(cod.getBroadcast().get(i))); + } + for (int i = 0; i < cod.getInputs().size(); i++) { + this.inputs.add(new MemoryJson(cod.getInputs().get(i))); + } + for (int i = 0; i < cod.getOutputs().size(); i++) { + this.outputs.add(new MemoryJson(cod.getOutputs().get(i))); + } + } } diff --git a/src/main/java/br/unicamp/cst/io/rest/MemoryJson.java b/src/main/java/br/unicamp/cst/io/rest/MemoryJson.java index b98e533f..5a9fe82b 100644 --- a/src/main/java/br/unicamp/cst/io/rest/MemoryJson.java +++ b/src/main/java/br/unicamp/cst/io/rest/MemoryJson.java @@ -1,3 +1,13 @@ +/*********************************************************************************************** + * Copyright (c) 2012 DCA-FEEC-UNICAMP + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the GNU Lesser Public License v3 + * which accompanies this distribution, and is available at + * http://www.gnu.org/licenses/lgpl.html + *

+ * Contributors: + * K. Raizer, A. L. O. Paraense, E. M. Froes, R. R. Gudwin - initial API and implementation + * **********************************************************************************************/ package br.unicamp.cst.io.rest; import br.unicamp.cst.core.entities.Memory; @@ -11,6 +21,7 @@ public class MemoryJson { public volatile Double evaluation; public volatile Object I; public String name; + public String group; public ArrayList memories = new ArrayList(); public MemoryJson(Memory memo) { @@ -27,4 +38,21 @@ public MemoryJson(Memory memo) { } } + + public MemoryJson(Memory memo, String group) { + timestamp = memo.getTimestamp(); + evaluation = memo.getEvaluation(); + I = memo.getI(); + name = memo.getName(); + this.group = group; + if (memo instanceof MemoryContainer) { + MemoryContainer memoAux = (MemoryContainer) memo; + List memoList = memoAux.getAllMemories(); + for (int i = 0; i < memoList.size(); i++) { + this.memories.add(new MemoryJson(memoList.get(i))); + } + } + + } } + diff --git a/src/main/java/br/unicamp/cst/io/rest/MindJson.java b/src/main/java/br/unicamp/cst/io/rest/MindJson.java index 30c2d4ee..2dd012eb 100644 --- a/src/main/java/br/unicamp/cst/io/rest/MindJson.java +++ b/src/main/java/br/unicamp/cst/io/rest/MindJson.java @@ -1,21 +1,59 @@ +/*********************************************************************************************** + * Copyright (c) 2012 DCA-FEEC-UNICAMP + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the GNU Lesser Public License v3 + * which accompanies this distribution, and is available at + * http://www.gnu.org/licenses/lgpl.html + *

+ * Contributors: + * K. Raizer, A. L. O. Paraense, E. M. Froes, R. R. Gudwin - initial API and implementation + * **********************************************************************************************/ package br.unicamp.cst.io.rest; import br.unicamp.cst.core.entities.Codelet; import br.unicamp.cst.core.entities.Memory; +import br.unicamp.cst.core.entities.Mind; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.ConcurrentHashMap; public class MindJson { public List memories = new ArrayList(); public List codelets = new ArrayList(); - public MindJson(List memories, List cods) { - for (int i = 0; i < memories.size(); i++) { - this.memories.add(new MemoryJson(memories.get(i))); + public MindJson(Mind m) { + if (m.getMemoryGroupsNumber() == 0) { + List mems = m.getRawMemory().getAllMemoryObjects(); + + for (int i = 0; i < mems.size(); i++) { + this.memories.add(new MemoryJson(mems.get(i))); + } + } + else { + ConcurrentHashMap mems = m.getMemoryGroups(); + + for (String key : mems.keySet()) { + ArrayList memoList = mems.get(key); + for (int i = 0; i < memoList.size(); i++) { + this.memories.add(new MemoryJson(memoList.get(i), key)); + } + } } - for (int i = 0; i < cods.size(); i++) { - this.codelets.add(new CodeletJson(cods.get(i))); + if (m.getCodeletGroupsNumber() == 0) { + List cods = m.getCodeRack().getAllCodelets(); + for (int i = 0; i < cods.size(); i++) { + this.codelets.add(new CodeletJson(cods.get(i))); + } + } + else { + ConcurrentHashMap cods = m.getCodeletGroups(); + for (String key : cods.keySet()) { + ArrayList codList = cods.get(key); + for (int i = 0; i < codList.size(); i++) { + this.codelets.add(new CodeletJson(codList.get(i), key)); + } + } } } } diff --git a/src/main/java/br/unicamp/cst/io/rest/RESTServer.java b/src/main/java/br/unicamp/cst/io/rest/RESTServer.java index 9af474bd..8d808709 100644 --- a/src/main/java/br/unicamp/cst/io/rest/RESTServer.java +++ b/src/main/java/br/unicamp/cst/io/rest/RESTServer.java @@ -1,8 +1,13 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ +/*********************************************************************************************** + * Copyright (c) 2012 DCA-FEEC-UNICAMP + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the GNU Lesser Public License v3 + * which accompanies this distribution, and is available at + * http://www.gnu.org/licenses/lgpl.html + *

+ * Contributors: + * K. Raizer, A. L. O. Paraense, E. M. Froes, R. R. Gudwin - initial API and implementation + * **********************************************************************************************/ package br.unicamp.cst.io.rest; import br.unicamp.cst.core.entities.Memory; @@ -26,6 +31,10 @@ */ public class RESTServer { + long refresh = 0; // A refresh of 0 means that every call will generate a new probe in mind + long lastaccess = 0; + String lastmessage = ""; + /** * * @param m the mind to observe @@ -53,6 +62,19 @@ public RESTServer(Mind m, int port, boolean pretty) { * @param origin a pattern for users allowed to access the server - use "*" to allow everyone */ public RESTServer(Mind m, int port, boolean pretty, String origin) { + this(m,port,pretty,origin,0L); + } + + /** + * + * @param m the mind to observe + * @param port the port to install the REST server + * @param pretty set this to true to generate pretty printing JSON in the REST server + * @param origin a pattern for users allowed to access the server - use "*" to allow everyone + * @param nrefresh the refresh period in milliseconds + */ + public RESTServer(Mind m, int port, boolean pretty, String origin, long nrefresh) { + refresh = nrefresh; Express app = new Express(); Gson gson; if (pretty) @@ -65,8 +87,14 @@ public RESTServer(Mind m, int port, boolean pretty, String origin) { corsOptions.setOrigin(origin); app.use(Middleware.cors(corsOptions)); app.get("/", (req, res) -> { - MindJson myJson = new MindJson(m.getRawMemory().getAllMemoryObjects(),m.getCodeRack().getAllCodelets()); - res.send(gson.toJson(myJson)); + long currentaccess = System.currentTimeMillis(); + long diff = currentaccess - lastaccess; + if (diff > refresh) { + MindJson myJson = new MindJson(m); + lastmessage = gson.toJson(myJson); + lastaccess = currentaccess; + } + res.send(lastmessage); }); app.listen(port); } diff --git a/src/test/java/br/unicamp/cst/io/rest/TestREST.java b/src/test/java/br/unicamp/cst/io/rest/TestREST.java index 4d1b6cc6..f6418f4f 100644 --- a/src/test/java/br/unicamp/cst/io/rest/TestREST.java +++ b/src/test/java/br/unicamp/cst/io/rest/TestREST.java @@ -39,7 +39,7 @@ public class TestREST { Mind m; public TestREST() { - m = prepareMind(); + } void updateMemoryObject(MemoryObject mo) { @@ -112,14 +112,23 @@ public Mind prepareMind() { m.createCodeletGroup("Behavioral"); m.createCodeletGroup("Motivational"); m.createCodeletGroup("Motor"); + m.createMemoryGroup("Sensory"); + m.createMemoryGroup("Motor"); MemoryObject m1 = m.createMemoryObject("M1", 1.12); + m.registerMemory(m1,"Sensory"); MemoryObject m2 = m.createMemoryObject("M2", 2.32); + m.registerMemory(m2,"Sensory"); MemoryObject m3 = m.createMemoryObject("M3", 3.44); + m.registerMemory(m3,"Sensory"); MemoryObject m4 = m.createMemoryObject("M4", 4.52); + m.registerMemory(m4,"Sensory"); MemoryObject m5 = m.createMemoryObject("M5", 5.12); + m.registerMemory(m5,"Sensory"); MemoryContainer m6 = m.createMemoryContainer("C1"); + m.registerMemory(m6,"Motor"); MemoryContainer m7 = m.createMemoryContainer("C2"); + m.registerMemory(m7,"Motor"); int mc1 = m7.setI(7.55, 0.23); int mc2 = m6.setI(6.33, 0.22); int mc3 = m6.setI(6.12, 0.13); @@ -162,6 +171,58 @@ public Mind prepareMind() { return(m); } + public Mind prepareMindWithoutGroups() { + Mind m = new Mind(); + + MemoryObject m1 = m.createMemoryObject("M1", 1.12); + MemoryObject m2 = m.createMemoryObject("M2", 2.32); + MemoryObject m3 = m.createMemoryObject("M3", 3.44); + MemoryObject m4 = m.createMemoryObject("M4", 4.52); + MemoryObject m5 = m.createMemoryObject("M5", 5.12); + MemoryContainer m6 = m.createMemoryContainer("C1"); + MemoryContainer m7 = m.createMemoryContainer("C2"); + int mc1 = m7.setI(7.55, 0.23); + int mc2 = m6.setI(6.33, 0.22); + int mc3 = m6.setI(6.12, 0.13); + int mc4 = m6.add(m7); + //System.out.println("Memories: "+mc1+" "+mc2+" "+mc3+" "+mc4); + + Codelet c = new TestCodelet("Sensor1"); + c.addInput(m1); + c.addInput(m2); + c.addOutput(m3); + c.addOutput(m4); + c.addBroadcast(m5); + //c.setCodeletProfiler("profile/", "c.json", "Mind 1", 10, null, CodeletsProfiler.FileFormat.JSON); + m.insertCodelet(c); + Codelet c2 = new TestCodelet("Motor1"); + c2.addInput(m4); + c2.addInput(m5); + c2.addOutput(m6); + c2.addOutput(m3); + c2.addBroadcast(m5); + //c2.setCodeletProfiler("profile/", "c2.json", "Mind 1", 10, null, CodeletsProfiler.FileFormat.JSON); + c.setProfiling(true); + m.insertCodelet(c2); + + Codelet mot1 = new TestCodelet("Curiosity"); + mot1.addInput(m7); + mot1.addOutput(m5); + m.insertCodelet(mot1); + Codelet mot2 = new TestCodelet("Fear"); + mot2.addInput(m3); + mot2.addOutput(m4); + try {mot2.setActivation(1.0);} catch(Exception e){} + m.insertCodelet(mot2); + Codelet mot3 = new TestCodelet("Anger"); + mot3.addInput(m1); + mot3.addOutput(m2); + try {mot3.setActivation(0.5);} catch(Exception e){} + m.insertCodelet(mot3); + m.start(); + return(m); + } + private static final String USER_AGENT = "Mozilla/5.0"; private String GET_URL; private static int port; @@ -198,6 +259,33 @@ private String sendGET() throws IOException { } private void processTest() throws IOException { + String mes; + for (int i=0;i<10;i++) { + mes = sendGET(); + Gson gson = new GsonBuilder().registerTypeAdapter(Memory.class, new InterfaceAdapter()) + .registerTypeAdapter(Memory.class, new InterfaceAdapter()) + .setPrettyPrinting().create(); + MindJson mj = gson.fromJson(mes,MindJson.class); + if (mj != null && mj.memories != null) { + assertEquals(mj.memories.size(),7); + MemoryJson c = mj.memories.get(0); + assertEquals(c.name,"C1"); + c = mj.memories.get(1); + assertEquals(c.name,"C2"); + for(int j=2;j<7;j++) { + MemoryJson mm = mj.memories.get(j); + String sname = "M"+(j-1); + assertEquals(mm.name,sname); + } + assertEquals(mj.codelets.size(),5); + String time = TimeStamp.getStringTimeStamp(mj.memories.get(0).timestamp,"dd/MM/YYYY HH:mm:ss.SSS zzz"); + System.out.println("i: "+i+" time: "+time+" memories: "+mj.memories.size()+" codelets: "+mj.codelets.size()); + } + else System.out.println("Problem detected while reading back the information"); + } + } + + private void processTestWithoutGroups() throws IOException { String mes; for (int i=0;i<10;i++) { mes = sendGET(); @@ -225,12 +313,13 @@ private void processTest() throws IOException { } @Test - public void testRest() throws IOException { + public void testRest1() throws IOException { Random r = new Random(); // Finding a random port higher than 5000 port = 5000 + r.nextInt(50000); GET_URL = "http://localhost:"+port+"/"; TestREST tr = new TestREST(); + tr.m = prepareMind(); tr.StartTimer(); System.out.println("Creating a server in port "+port); RESTServer rs = new RESTServer(tr.m,port,true); @@ -244,6 +333,7 @@ public void testRest2() throws IOException { port = 5000 + r.nextInt(50000); GET_URL = "http://localhost:"+port+"/"; TestREST tr = new TestREST(); + tr.m = prepareMind(); tr.StartTimer(); System.out.println("Creating a server in port "+port); RESTServer rs = new RESTServer(tr.m,port); @@ -257,10 +347,81 @@ public void testRest3() throws IOException { port = 5000 + r.nextInt(50000); GET_URL = "http://localhost:"+port+"/"; TestREST tr = new TestREST(); + tr.m = prepareMind(); tr.StartTimer(); System.out.println("Creating a server in port "+port); RESTServer rs = new RESTServer(tr.m,port,true,"*"); processTest(); } + @Test + public void testRest4() throws IOException { + Random r = new Random(); + // Finding a random port higher than 5000 + port = 5000 + r.nextInt(50000); + GET_URL = "http://localhost:"+port+"/"; + TestREST tr = new TestREST(); + tr.m = prepareMindWithoutGroups(); + tr.StartTimer(); + System.out.println("Creating a server in port "+port); + RESTServer rs = new RESTServer(tr.m,port,true); + processTestWithoutGroups(); + } + + @Test + public void testRest5() throws IOException { + Random r = new Random(); + // Finding a random port higher than 5000 + port = 5000 + r.nextInt(50000); + GET_URL = "http://localhost:"+port+"/"; + TestREST tr = new TestREST(); + tr.m = prepareMindWithoutGroups(); + tr.StartTimer(); + System.out.println("Creating a server in port "+port); + RESTServer rs = new RESTServer(tr.m,port); + processTestWithoutGroups(); + } + + @Test + public void testRest6() throws IOException { + Random r = new Random(); + // Finding a random port higher than 5000 + port = 5000 + r.nextInt(50000); + GET_URL = "http://localhost:"+port+"/"; + TestREST tr = new TestREST(); + tr.m = prepareMindWithoutGroups(); + tr.StartTimer(); + System.out.println("Creating a server in port "+port); + RESTServer rs = new RESTServer(tr.m,port,true,"*"); + processTestWithoutGroups(); + } + + @Test + public void testRest7() throws IOException { + Random r = new Random(); + // Finding a random port higher than 5000 + port = 5000 + r.nextInt(50000); + GET_URL = "http://localhost:"+port+"/"; + TestREST tr = new TestREST(); + tr.m = prepareMind(); + tr.StartTimer(); + System.out.println("Creating a server in port "+port); + RESTServer rs = new RESTServer(tr.m,port,true,"*",500L); + processTest(); + } + + @Test + public void testRest8() throws IOException { + Random r = new Random(); + // Finding a random port higher than 5000 + port = 5000 + r.nextInt(50000); + GET_URL = "http://localhost:"+port+"/"; + TestREST tr = new TestREST(); + tr.m = prepareMindWithoutGroups(); + tr.StartTimer(); + System.out.println("Creating a server in port "+port); + RESTServer rs = new RESTServer(tr.m,port,true,"*",500L); + processTestWithoutGroups(); + } + }