diff --git a/src/main/java/de/neemann/digital/gui/DigitalRemoteInterface.java b/src/main/java/de/neemann/digital/gui/DigitalRemoteInterface.java index 0a2a3539d..a8b2f7bda 100644 --- a/src/main/java/de/neemann/digital/gui/DigitalRemoteInterface.java +++ b/src/main/java/de/neemann/digital/gui/DigitalRemoteInterface.java @@ -54,4 +54,12 @@ public interface DigitalRemoteInterface { * @throws RemoteException RemoteException */ void stop() throws RemoteException; + + /** + * Used to obtain the models state + * + * @return a JSON string containing the measurement values + * @throws RemoteException RemoteException + */ + String measure() throws RemoteException; } diff --git a/src/main/java/de/neemann/digital/gui/Main.java b/src/main/java/de/neemann/digital/gui/Main.java index ae490c243..00b048e28 100644 --- a/src/main/java/de/neemann/digital/gui/Main.java +++ b/src/main/java/de/neemann/digital/gui/Main.java @@ -1820,7 +1820,10 @@ public final class Main extends JFrame implements ClosingWindowListener.ConfirmS @Override public void start(File romHex) { SwingUtilities.invokeLater(() -> { - runModelState.enter(true, new ProgramMemoryLoader(romHex)); + ProgramMemoryLoader modelModifier = null; + if (romHex != null) + modelModifier = new ProgramMemoryLoader(romHex); + runModelState.enter(true, modelModifier); circuitComponent.graphicHasChanged(); }); } @@ -1885,6 +1888,26 @@ public final class Main extends JFrame implements ClosingWindowListener.ConfirmS public void stop() { SwingUtilities.invokeLater(this::ensureModelIsStopped); } + + @Override + public String measure() throws RemoteException { + if (model != null) { + StringBuilder sb = new StringBuilder("{"); + ArrayList signals = model.getSignalsCopy(); + boolean first = true; + for (Signal s : signals) { + if (first) + first = false; + else + sb.append(','); + sb.append('"').append(s.getName()).append("\":").append(s.getValue().getValue()); + } + sb.append("}"); + return sb.toString(); + } + throw new RemoteException("no model available"); + } + //********************** // remote interface end //********************** diff --git a/src/main/java/de/neemann/digital/gui/remote/DigitalHandler.java b/src/main/java/de/neemann/digital/gui/remote/DigitalHandler.java index 41e2b8099..9989f5a5b 100644 --- a/src/main/java/de/neemann/digital/gui/remote/DigitalHandler.java +++ b/src/main/java/de/neemann/digital/gui/remote/DigitalHandler.java @@ -63,6 +63,8 @@ public class DigitalHandler implements HandlerInterface { case "stop": digitalRemoteInterface.stop(); return null; + case "measure": + return digitalRemoteInterface.measure(); default: throw new RemoteException(Lang.get("msg_remoteUnknownCommand", command)); } diff --git a/src/test/java/de/neemann/digital/integration/TestInGUI.java b/src/test/java/de/neemann/digital/integration/TestInGUI.java index 5a267412b..378ecbdb8 100644 --- a/src/test/java/de/neemann/digital/integration/TestInGUI.java +++ b/src/test/java/de/neemann/digital/integration/TestInGUI.java @@ -27,6 +27,7 @@ import de.neemann.digital.fsm.FSM; import de.neemann.digital.fsm.State; import de.neemann.digital.fsm.Transition; import de.neemann.digital.fsm.gui.FSMFrame; +import de.neemann.digital.gui.DigitalRemoteInterface; import de.neemann.digital.gui.Main; import de.neemann.digital.gui.NumberingWizard; import de.neemann.digital.gui.Settings; @@ -41,6 +42,7 @@ import de.neemann.digital.gui.components.terminal.KeyboardDialog; import de.neemann.digital.gui.components.terminal.Terminal; import de.neemann.digital.gui.components.testing.TestAllDialog; import de.neemann.digital.gui.components.testing.ValueTableDialog; +import de.neemann.digital.gui.remote.RemoteException; import de.neemann.digital.lang.Lang; import de.neemann.digital.testing.TestCaseDescription; import de.neemann.digital.testing.TestCaseElement; @@ -1089,6 +1091,28 @@ public class TestInGUI extends TestCase { .execute(); } + public void testRemoteInterface() throws InterruptedException, RemoteException { + Main m = new Main.MainBuilder() + .setFileToOpen(new File(Resources.getRoot(), "dig/remoteInterface/measure.dig")) + .build(); + + SwingUtilities.invokeLater(() -> m.setVisible(true)); + DigitalRemoteInterface ri = m; + + Thread.sleep(1000); + ri.start(null); + Thread.sleep(1000); + String json = ri.measure(); + assertEquals("{\"Q\":0,\"C\":0}", json); + Thread.sleep(1000); + ri.doSingleStep(); + Thread.sleep(1000); + json = ri.measure(); + assertEquals("{\"Q\":1,\"C\":0}", json); + Thread.sleep(1000); + ri.stop(); + m.dispose(); + } public static class CheckErrorDialog extends GuiTester.WindowCheck { private final String[] expected; diff --git a/src/test/resources/dig/remoteInterface/measure.dig b/src/test/resources/dig/remoteInterface/measure.dig new file mode 100644 index 000000000..8b99438b7 --- /dev/null +++ b/src/test/resources/dig/remoteInterface/measure.dig @@ -0,0 +1,105 @@ + + + 1 + + + + Out + + + Label + Q + + + + + + Clock + + + Label + C + + + + + + JK_FF + + + + + VDD + + + + + ROM + + + isProgramMemory + true + + + + + + Ground + + + Bits + 2 + + + + + + Ground + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file