adds a "measure" command to the remote interface, closes #478

This commit is contained in:
hneemann 2020-06-20 19:53:06 +02:00
parent 626fe7f718
commit 16de89df10
5 changed files with 163 additions and 1 deletions

View File

@ -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;
}

View File

@ -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<Signal> 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
//**********************

View File

@ -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));
}

View File

@ -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<ErrorMessage.ErrorDialog> {
private final String[] expected;

View File

@ -0,0 +1,105 @@
<?xml version="1.0" encoding="utf-8"?>
<circuit>
<version>1</version>
<attributes/>
<visualElements>
<visualElement>
<elementName>Out</elementName>
<elementAttributes>
<entry>
<string>Label</string>
<string>Q</string>
</entry>
</elementAttributes>
<pos x="460" y="140"/>
</visualElement>
<visualElement>
<elementName>Clock</elementName>
<elementAttributes>
<entry>
<string>Label</string>
<string>C</string>
</entry>
</elementAttributes>
<pos x="340" y="160"/>
</visualElement>
<visualElement>
<elementName>JK_FF</elementName>
<elementAttributes/>
<pos x="380" y="140"/>
</visualElement>
<visualElement>
<elementName>VDD</elementName>
<elementAttributes/>
<pos x="360" y="120"/>
</visualElement>
<visualElement>
<elementName>ROM</elementName>
<elementAttributes>
<entry>
<string>isProgramMemory</string>
<boolean>true</boolean>
</entry>
</elementAttributes>
<pos x="380" y="240"/>
</visualElement>
<visualElement>
<elementName>Ground</elementName>
<elementAttributes>
<entry>
<string>Bits</string>
<int>2</int>
</entry>
</elementAttributes>
<pos x="360" y="260"/>
</visualElement>
<visualElement>
<elementName>Ground</elementName>
<elementAttributes/>
<pos x="360" y="300"/>
</visualElement>
</visualElements>
<wires>
<wire>
<p1 x="340" y="160"/>
<p2 x="380" y="160"/>
</wire>
<wire>
<p1 x="360" y="240"/>
<p2 x="380" y="240"/>
</wire>
<wire>
<p1 x="360" y="180"/>
<p2 x="380" y="180"/>
</wire>
<wire>
<p1 x="360" y="280"/>
<p2 x="380" y="280"/>
</wire>
<wire>
<p1 x="440" y="140"/>
<p2 x="460" y="140"/>
</wire>
<wire>
<p1 x="360" y="140"/>
<p2 x="380" y="140"/>
</wire>
<wire>
<p1 x="360" y="120"/>
<p2 x="360" y="140"/>
</wire>
<wire>
<p1 x="360" y="240"/>
<p2 x="360" y="260"/>
</wire>
<wire>
<p1 x="360" y="280"/>
<p2 x="360" y="300"/>
</wire>
<wire>
<p1 x="360" y="140"/>
<p2 x="360" y="180"/>
</wire>
</wires>
<measurementOrdering/>
</circuit>