diff --git a/case-study-sorting-pkg/src/main/java/de/tudresden/inf/st/sorting/Main.java b/case-study-sorting-pkg/src/main/java/de/tudresden/inf/st/sorting/Main.java index f25ada35978894e76e896cefa42038b8667e22a8..d01d46ca3e1ee4cd1254f345aa914364b35b754d 100644 --- a/case-study-sorting-pkg/src/main/java/de/tudresden/inf/st/sorting/Main.java +++ b/case-study-sorting-pkg/src/main/java/de/tudresden/inf/st/sorting/Main.java @@ -1,9 +1,6 @@ package de.tudresden.inf.st.sorting; -import de.tudresden.inf.st.sorting.fake.FakeServerNode; -import org.ros.node.DefaultNodeMainExecutor; import org.ros.node.NodeConfiguration; -import org.ros.node.NodeMainExecutor; import java.net.URI; @@ -13,15 +10,9 @@ public class Main { private static final String ROS_MASTER_URI = "http://localhost:11311"; private static final NodeConfiguration nodeConfiguration = NodeConfiguration.newPublic(ROS_HOST); - private static final NodeMainExecutor nodeMainExecutor = DefaultNodeMainExecutor.newDefault(); public static void main(java.lang.String[] args) { nodeConfiguration.setMasterUri(URI.create(ROS_MASTER_URI)); - - // FAKE NODES FOR TESTING - new Thread(() -> nodeMainExecutor.execute(new FakeServerNode("pickService", "PickServiceNode"), nodeConfiguration)) {{start();}}; - new Thread(() -> nodeMainExecutor.execute(new FakeServerNode("placeService", "PlaceServiceNode"), nodeConfiguration)) {{start();}}; - } } diff --git a/case-study-sorting-pkg/src/main/java/de/tudresden/inf/st/sorting/constants/TokenConstants.java b/case-study-sorting-pkg/src/main/java/de/tudresden/inf/st/sorting/constants/TokenConstants.java index 7be0979f026f5b70bef5cf67e54e0f0a259d6673..c267821398239d39c748a1b663018196bdd607bb 100644 --- a/case-study-sorting-pkg/src/main/java/de/tudresden/inf/st/sorting/constants/TokenConstants.java +++ b/case-study-sorting-pkg/src/main/java/de/tudresden/inf/st/sorting/constants/TokenConstants.java @@ -10,5 +10,7 @@ public final class TokenConstants { public static final String NAME = "name"; public static final String TRACE = "trace"; public static final String LOCKED = "locked"; + public static final String ROBOT = "robot"; + public static final String TIME_PICK = "pickTime"; } diff --git a/case-study-sorting-pkg/src/main/java/de/tudresden/inf/st/sorting/fake/FakeServerNode.java b/case-study-sorting-pkg/src/main/java/de/tudresden/inf/st/sorting/fake/FakeServerNode.java deleted file mode 100644 index c4308b044ece22f6d9415823be11c496691ecbf9..0000000000000000000000000000000000000000 --- a/case-study-sorting-pkg/src/main/java/de/tudresden/inf/st/sorting/fake/FakeServerNode.java +++ /dev/null @@ -1,44 +0,0 @@ -package de.tudresden.inf.st.sorting.fake; - -import org.ros.namespace.GraphName; -import org.ros.node.AbstractNodeMain; -import org.ros.node.ConnectedNode; -import org.ros.node.service.ServiceResponseBuilder; -import rosjava_srv.StringService; -import rosjava_srv.StringServiceRequest; -import rosjava_srv.StringServiceResponse; - -public class FakeServerNode extends AbstractNodeMain { - - private final String serviceName; - private final String nodeName; - - public FakeServerNode(String serviceName, String nodeName) { - this.serviceName = serviceName; - this.nodeName = nodeName; - } - - @Override - public GraphName getDefaultNodeName() { - return GraphName.of(nodeName); - } - - @Override - public void onStart(final ConnectedNode connectedNode) { - - System.out.println("[" + nodeName + "] Starting node."); - - connectedNode.newServiceServer(serviceName, StringService._TYPE, - (ServiceResponseBuilder<StringServiceRequest, StringServiceResponse>) (request, response) -> { - - System.out.println("[" + nodeName + "] Service Input: \"" + request.getInput() + "\""); - try { - Thread.sleep(4000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - System.out.println("[" + nodeName + "] Finished sleep."); - response.setOutput(request.getInput()); - }); - } -} diff --git a/case-study-sorting-pkg/src/main/java/de/tudresden/inf/st/sorting/handlers/ControlEndHandler.java b/case-study-sorting-pkg/src/main/java/de/tudresden/inf/st/sorting/handlers/ControlEndHandler.java index c9f912c745f5df8fe23a9ce185e0a0a358af2581..f5d72ef5408ebcb04b091ce46474e4afc73a007b 100644 --- a/case-study-sorting-pkg/src/main/java/de/tudresden/inf/st/sorting/handlers/ControlEndHandler.java +++ b/case-study-sorting-pkg/src/main/java/de/tudresden/inf/st/sorting/handlers/ControlEndHandler.java @@ -3,6 +3,8 @@ package de.tudresden.inf.st.sorting.handlers; import de.tudresden.inf.st.pnml.engine.execution.TransitionHandler; import de.tudresden.inf.st.sorting.constants.TokenConstants; +import java.util.ArrayList; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.function.Function; @@ -20,7 +22,21 @@ public class ControlEndHandler extends TransitionHandler { } } - return maps; + // TASK 1.2 START // + List<Map<String, Object>> out = new ArrayList<>(); + + for(Map<String, Object> m : maps) { + for (Map.Entry<String, Object> entry : m.entrySet()) { + if (entry.getKey().equals(TokenConstants.TRACE)) { + if(String.valueOf(entry.getValue()).endsWith("pickSuccess")){ + out.add(m); + } + } + } + } + + return out.isEmpty() ? maps : out; + // TASK 1.2 END // }; public ControlEndHandler(int priority) { diff --git a/case-study-sorting-pkg/src/main/java/de/tudresden/inf/st/sorting/handlers/PickHandler.java b/case-study-sorting-pkg/src/main/java/de/tudresden/inf/st/sorting/handlers/PickHandler.java index a826857e554413d749b8d1cb838b25f6df5bc907..f3a144a2d248479b822bbf2bc7690bb12d0db7a0 100644 --- a/case-study-sorting-pkg/src/main/java/de/tudresden/inf/st/sorting/handlers/PickHandler.java +++ b/case-study-sorting-pkg/src/main/java/de/tudresden/inf/st/sorting/handlers/PickHandler.java @@ -28,6 +28,10 @@ public class PickHandler extends TransitionHandler { m.replace(TokenConstants.TRACE, oldTrace + "-pickToSafety"); res.add(m); } + + // TASK 1.2 START // + m.replace(TokenConstants.TIME_PICK, Long.toString(System.currentTimeMillis())); + // TASK 1.3 END // } return res; diff --git a/case-study-sorting-pkg/src/main/java/de/tudresden/inf/st/sorting/handlers/PickSuccessHandler.java b/case-study-sorting-pkg/src/main/java/de/tudresden/inf/st/sorting/handlers/PickSuccessHandler.java index 3f246ecfebae374617e136c707c86b70e1672cd0..f1f4df6674a19f93b798f1c58a0840ed84384f2a 100644 --- a/case-study-sorting-pkg/src/main/java/de/tudresden/inf/st/sorting/handlers/PickSuccessHandler.java +++ b/case-study-sorting-pkg/src/main/java/de/tudresden/inf/st/sorting/handlers/PickSuccessHandler.java @@ -14,6 +14,23 @@ public class PickSuccessHandler extends TransitionHandler { for (Map<String, Object> m : maps) { m.replace(TokenConstants.PICK_SUCCESS, "success"); + + + // TASK 1.2 START // + long l1 = Long.parseLong(m.get(TokenConstants.TIME_PICK).toString()); + long l2 = System.currentTimeMillis(); + long diff = l2 - l1; + m.replace(TokenConstants.TIME_PICK, String.valueOf(diff)); + + for (Map.Entry<String, Object> entry : m.entrySet()) { + if (entry.getKey().equals(TokenConstants.TRACE)) { + String oldTrace = String.valueOf(entry.getValue()); + String newTrace = oldTrace + "-" + "pickSuccess"; + m.replace(TokenConstants.TRACE, newTrace); + } + } + + // TASK 1.3 END // } return maps; diff --git a/case-study-sorting-pkg/src/main/java/de/tudresden/inf/st/sorting/handlers/SensorDataProcessingHandler.java b/case-study-sorting-pkg/src/main/java/de/tudresden/inf/st/sorting/handlers/SensorDataProcessingHandler.java index 137f0e566fab3d318389426e842a751b256fa8f7..7ee7c316285e7c38f843c281738de93e69638014 100644 --- a/case-study-sorting-pkg/src/main/java/de/tudresden/inf/st/sorting/handlers/SensorDataProcessingHandler.java +++ b/case-study-sorting-pkg/src/main/java/de/tudresden/inf/st/sorting/handlers/SensorDataProcessingHandler.java @@ -4,14 +4,15 @@ import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.reflect.TypeToken; import de.tudresden.inf.st.pnml.engine.execution.TransitionHandler; -import de.tudresden.inf.st.pnml.jastadd.model.PnmlParser; import de.tudresden.inf.st.sorting.constants.TokenConstants; +import de.tudresden.inf.st.sorting.mqtt.MessageListener; -import java.io.IOException; import java.lang.reflect.Type; -import java.nio.file.Files; import java.util.List; import java.util.Map; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; import java.util.function.Function; public class SensorDataProcessingHandler extends TransitionHandler { @@ -19,15 +20,35 @@ public class SensorDataProcessingHandler extends TransitionHandler { final static Function<List<Map<String, Object>>, List<Map<String, Object>>> PROCESS_DATA_HANDLING_FUNCTION = maps -> { System.out.println("Executing GET_DATA_HANDLING_FUNCTION."); - try { - Map<String, Object> fakeRes = parse( - Files.readString(PnmlParser.toTempPath("/docs/FakeConfig.json"))); + MessageListener listener = new MessageListener(); + ExecutorService executor = Executors.newSingleThreadExecutor(); + executor.submit(() -> { + listener.listen(message -> { + System.out.println("Received message: " + message); + + for (Map<String, Object> m : maps) { + if (Long.parseLong(message) < 4) { + m.replace(TokenConstants.HUMAN_DETECTED, "true"); + } else { + m.replace(TokenConstants.HUMAN_DETECTED, "false"); + } + } + listener.stop(); + }); + }); - for(Map<String, Object> m : maps){ - m.replace(TokenConstants.HUMAN_DETECTED, fakeRes.get("sensor")); + // Wait for a maximum of 2 seconds + try { + if (!listener.awaitStop(2, TimeUnit.SECONDS)) { + System.out.println("Timeout reached, no message received."); + for (Map<String, Object> m : maps) { + m.replace(TokenConstants.HUMAN_DETECTED, "true"); + } } - } catch (IOException e) { - e.printStackTrace(); + } catch (InterruptedException e) { + System.err.println("Thread interrupted while waiting: " + e.getMessage()); + } finally { + executor.shutdown(); } return maps; @@ -39,7 +60,8 @@ public class SensorDataProcessingHandler extends TransitionHandler { private static Map<String, Object> parse(java.lang.String s) { Gson gson = new GsonBuilder().create(); - Type mapType = new TypeToken<Map<String, Object>>(){}.getType(); + Type mapType = new TypeToken<Map<String, Object>>() { + }.getType(); return gson.fromJson(s, mapType); } } \ No newline at end of file diff --git a/case-study-sorting-pkg/src/main/java/de/tudresden/inf/st/sorting/handlers/ShowResultHandler.java b/case-study-sorting-pkg/src/main/java/de/tudresden/inf/st/sorting/handlers/ShowResultHandler.java index 273e9bc2c3c7aed151d5af658c8482701d6ebaf4..5c775fb5de9a4fd3a54d89bfbfd7c66ef6ac06ef 100644 --- a/case-study-sorting-pkg/src/main/java/de/tudresden/inf/st/sorting/handlers/ShowResultHandler.java +++ b/case-study-sorting-pkg/src/main/java/de/tudresden/inf/st/sorting/handlers/ShowResultHandler.java @@ -17,6 +17,11 @@ public class ShowResultHandler extends TransitionHandler { + "\n -color " + m.get(TokenConstants.COLOR) + "\n -pick " + m.get(TokenConstants.PICK_SUCCESS) + "\n -place " + m.get(TokenConstants.PLACE_SUCCESS)); + // TASK 1.2 START // + System.out.println("Picking Information" + + "\n -robot " + m.get(TokenConstants.ROBOT) + + "\n -pickTime " + m.get(TokenConstants.TIME_PICK)); + // TASK 1.2 END // } return maps; }; diff --git a/case-study-sorting-pkg/src/main/java/de/tudresden/inf/st/sorting/handlers/SortColorHandler.java b/case-study-sorting-pkg/src/main/java/de/tudresden/inf/st/sorting/handlers/SortColorHandler.java index 1cee2098a3802654186ff5ab408e93b1b9440635..47065f2ac51db03eea2a33bf8804defbe7b7c5b7 100644 --- a/case-study-sorting-pkg/src/main/java/de/tudresden/inf/st/sorting/handlers/SortColorHandler.java +++ b/case-study-sorting-pkg/src/main/java/de/tudresden/inf/st/sorting/handlers/SortColorHandler.java @@ -2,6 +2,7 @@ package de.tudresden.inf.st.sorting.handlers; import de.tudresden.inf.st.pnml.engine.execution.TransitionHandler; import de.tudresden.inf.st.sorting.constants.TokenConstants; +import org.jetbrains.annotations.NotNull; import java.util.List; import java.util.Map; @@ -11,18 +12,47 @@ public class SortColorHandler extends TransitionHandler { final static Function<List<Map<String, Object>>, List<Map<String, Object>>> SORT_HANDLING_FUNCTION = maps -> { System.out.println("Executing SORT_HANDLING_FUNCTION."); + for(Map<String, Object> m : maps){ + for (Map.Entry<String, Object> entry : m.entrySet()) { if(entry.getKey().equals(TokenConstants.TRACE)){ String oldTrace = String.valueOf(entry.getValue()); String newTrace = oldTrace + "-" + "SortColor"; m.replace(TokenConstants.TRACE, newTrace); } + + // TASK 1.1 START // + + if(entry.getKey().equals(TokenConstants.ROBOT)){ + if(getColor(m).equals("green")){ + m.replace(TokenConstants.TRACE, "right"); + } else { + m.replace(TokenConstants.TRACE, "left"); + } + } + + // TASK 1.1 END // } } return maps; }; + // TASK 1.1 START // + + private static @NotNull String getColor(Map<String, Object> m) { + String color = ""; + + for (Map.Entry<String, Object> e : m.entrySet()) { + if(e.getKey().equals(TokenConstants.COLOR)){ + color = e.getKey(); + } + } + return color; + } + + // TASK 1.1 END // + public SortColorHandler(int priority) { super(priority, SORT_HANDLING_FUNCTION); } diff --git a/case-study-sorting-pkg/src/main/java/de/tudresden/inf/st/sorting/mqtt/MessageCallback.java b/case-study-sorting-pkg/src/main/java/de/tudresden/inf/st/sorting/mqtt/MessageCallback.java new file mode 100644 index 0000000000000000000000000000000000000000..8b297596c46932795ddf74ae6e838933514e0af8 --- /dev/null +++ b/case-study-sorting-pkg/src/main/java/de/tudresden/inf/st/sorting/mqtt/MessageCallback.java @@ -0,0 +1,7 @@ +package de.tudresden.inf.st.sorting.mqtt; + +// Callback Interface +@FunctionalInterface +public interface MessageCallback { + void onMessage(String message); +} diff --git a/case-study-sorting-pkg/src/main/java/de/tudresden/inf/st/sorting/mqtt/MessageListener.java b/case-study-sorting-pkg/src/main/java/de/tudresden/inf/st/sorting/mqtt/MessageListener.java new file mode 100644 index 0000000000000000000000000000000000000000..db011df270088198b8234446fbb682669f1a993f --- /dev/null +++ b/case-study-sorting-pkg/src/main/java/de/tudresden/inf/st/sorting/mqtt/MessageListener.java @@ -0,0 +1,37 @@ +package de.tudresden.inf.st.sorting.mqtt; + +import java.util.concurrent.TimeUnit; +// TASK 2 START // +public class MessageListener { + + private volatile boolean running = true; + + // Simulate listening for a message + public void listen(MessageCallback callback) { + try { + // Simulate receiving a message after 1 second + Thread.sleep(1000); + if (running) { + callback.onMessage("Hello, this is a test message!"); + } + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + System.err.println("Listener interrupted: " + e.getMessage()); + } + } + + // Stop the listener + public void stop() { + running = false; + } + + // Await until the listener stops or timeout is reached + public boolean awaitStop(long timeout, TimeUnit unit) throws InterruptedException { + long startTime = System.nanoTime(); + while (running && (System.nanoTime() - startTime) < unit.toNanos(timeout)) { + Thread.sleep(100); // Check every 100ms + } + return !running; + } +} + diff --git a/case-study-sorting-pkg/src/main/resources/nets/SelectorNode.pnml b/case-study-sorting-pkg/src/main/resources/nets/SelectorNode.pnml index c914a69407a531fba657afc87fba6788533f9cd6..6e92f6684ae175bd678d3606c51b53981241bbff 100644 --- a/case-study-sorting-pkg/src/main/resources/nets/SelectorNode.pnml +++ b/case-study-sorting-pkg/src/main/resources/nets/SelectorNode.pnml @@ -19,7 +19,8 @@ <balloonMarking> <tokens> <token>{"color" : "green", "name" : "green1", "pickSuccess" : "false", "placeSuccess" : "false", - "humanDetected" : "false", "sensorData" : "", "trace" : "", "locked" : "false" } </token> + "humanDetected" : "false", "sensorData" : "", "trace" : "", + "locked" : "false", "robot" : "", "pickTime" : ""} </token> </tokens> </balloonMarking> </toolspecific> @@ -51,7 +52,8 @@ <balloonMarking> <tokens> <token>{"color" : "blue", "name" : "blue1", "pickSuccess" : "false", "placeSuccess" : "false", - "humanDetected" : "false", "sensorData" : "", "trace" : "", "locked" : "false" } </token> + "humanDetected" : "false", "sensorData" : "", "trace" : "", + "locked" : "false", "robot" : "", "pickTime" : ""} </token> </tokens> </balloonMarking> </toolspecific> @@ -71,7 +73,8 @@ <balloonMarking> <tokens> <token>{"color" : "red", "name" : "red1", "pickSuccess" : "false", "placeSuccess" : "false", - "humanDetected" : "false", "sensorData" : "", "trace" : "", "locked" : "false" } </token> + "humanDetected" : "false", "sensorData" : "", "trace" : "", + "locked" : "false", "robot" : "", "pickTime" : ""} </token> </tokens> </balloonMarking> </toolspecific>