diff --git a/numass-control/msp/src/main/java/inr/numass/control/msp/MspDevice.java b/numass-control/msp/src/main/java/inr/numass/control/msp/MspDevice.java index 2eb1e472..e45928f2 100644 --- a/numass-control/msp/src/main/java/inr/numass/control/msp/MspDevice.java +++ b/numass-control/msp/src/main/java/inr/numass/control/msp/MspDevice.java @@ -16,9 +16,9 @@ package inr.numass.control.msp; import hep.dataforge.context.Context; +import hep.dataforge.control.NamedValueListener; import hep.dataforge.control.RoleDef; import hep.dataforge.control.collectors.RegularPointCollector; -import hep.dataforge.control.collectors.ValueCollector; import hep.dataforge.control.connections.Roles; import hep.dataforge.control.connections.StorageConnection; import hep.dataforge.control.devices.Device; @@ -26,9 +26,9 @@ import hep.dataforge.control.devices.PortSensor; import hep.dataforge.control.devices.SingleMeasurementDevice; import hep.dataforge.control.devices.StateDef; import hep.dataforge.control.measurements.AbstractMeasurement; -import hep.dataforge.control.measurements.Measurement; import hep.dataforge.control.ports.PortHandler; import hep.dataforge.control.ports.TcpPortHandler; +import hep.dataforge.events.EventBuilder; import hep.dataforge.exceptions.ControlException; import hep.dataforge.exceptions.MeasurementException; import hep.dataforge.exceptions.PortException; @@ -47,7 +47,6 @@ import inr.numass.control.StorageHelper; import java.time.Duration; import java.time.Instant; import java.util.*; -import java.util.function.Consumer; /** * @author Alexander Nozik @@ -58,15 +57,12 @@ import java.util.function.Consumer; @StateDef(name = "storing", writable = true, info = "Define if this device is currently writes to storage") @StateDef(name = "filamentOn", writable = true, info = "Mass-spectrometer filament on") @StateDef(name = "filamentStatus", info = "Filament status") -public class MspDevice extends SingleMeasurementDevice implements PortHandler.PortController { +public class MspDevice extends SingleMeasurementDevice implements PortHandler.PortController { public static final String MSP_DEVICE_TYPE = "msp"; private static final int TIMEOUT = 200; private TcpPortHandler handler; - //listener - private MspListener mspListener; - private Consumer responseDelegate; public MspDevice() { } @@ -91,22 +87,22 @@ public class MspDevice extends SingleMeasurementDevice implements PortHandler.Po @Override public void shutdown() throws ControlException { - super.shutdown(); super.stopMeasurement(true); if (isConnected()) { setFilamentOn(false); setConnected(false); } getHandler().close(); + super.shutdown(); } @Override protected Meta getMeasurementMeta() { - return meta().getMeta("peakJump"); + return meta().getMeta("peakJump"); } @Override - protected Measurement createMeasurement(Meta meta) throws ControlException { + protected PeakJumpMeasurement createMeasurement(Meta meta) throws ControlException { switch (meta.getString("type", "peakJump")) { case "peakJump": return new PeakJumpMeasurement(meta); @@ -200,10 +196,6 @@ public class MspDevice extends SingleMeasurementDevice implements PortHandler.Po } } - public void setMspListener(MspListener listener) { - this.mspListener = listener; - } - /** * Send request to the msp * @@ -213,9 +205,12 @@ public class MspDevice extends SingleMeasurementDevice implements PortHandler.Po */ private void send(String command, Object... parameters) throws PortException { String request = buildCommand(command, parameters); - if (mspListener != null) { - mspListener.acceptRequest(request); - } + dispatchEvent( + EventBuilder + .make("msp") + .setMetaValue("request", request) + .build() + ); getHandler().send(request); } @@ -247,9 +242,12 @@ public class MspDevice extends SingleMeasurementDevice implements PortHandler.Po private MspResponse sendAndWait(String commandName, Object... parameters) throws PortException { String request = buildCommand(commandName, parameters); - if (mspListener != null) { - mspListener.acceptRequest(request); - } + dispatchEvent( + EventBuilder + .make("msp") + .setMetaValue("request", request) + .build() + ); String response = getHandler().sendAndWait( request, @@ -275,8 +273,8 @@ public class MspDevice extends SingleMeasurementDevice implements PortHandler.Po return getState("filamentOn").booleanValue(); } - public void selectFillament(int fillament) throws PortException { - sendAndWait("FilamentSelect", fillament); + public void selectFillament(int filament) throws PortException { + sendAndWait("FilamentSelect", filament); } /** @@ -305,9 +303,11 @@ public class MspDevice extends SingleMeasurementDevice implements PortHandler.Po @Override public void accept(String message) { - if (mspListener != null) { - mspListener.acceptMessage(message.trim()); - } + dispatchEvent( + EventBuilder + .make("msp") + .setMetaValue("response", message.trim()).build() + ); MspResponse response = new MspResponse(message); switch (response.getCommandName()) { @@ -316,25 +316,17 @@ public class MspDevice extends SingleMeasurementDevice implements PortHandler.Po String status = response.get(0, 2); updateState("filamentOn", status.equals("ON")); updateState("filamentStatus", status); - if (mspListener != null) { - mspListener.acceptFilamentStateChange(status); - } break; } - if (responseDelegate != null) { - responseDelegate.accept(response); + PeakJumpMeasurement measurement = getMeasurement(); + if (measurement != null) { + measurement.eval(response); } } @Override public void error(String errorMessage, Throwable error) { - if (mspListener != null) { - mspListener.error(errorMessage, error); - } else if (error != null) { - throw new RuntimeException(error); - } else { - throw new RuntimeException(errorMessage); - } + notifyError(errorMessage, error); } private TcpPortHandler getHandler() { @@ -345,17 +337,17 @@ public class MspDevice extends SingleMeasurementDevice implements PortHandler.Po } private Duration getAveragingDuration() { - return Duration.parse(meta().getString("averagingDuration", "PT60S")); + return Duration.parse(meta().getString("averagingDuration", "PT30S")); } /** * The MKS response as two-dimensional array of strings */ - static class MspResponse { + private static class MspResponse { private final List> data = new ArrayList<>(); - public MspResponse(String response) { + MspResponse(String response) { String rx = "[^\"\\s]+|\"(\\\\.|[^\\\\\"])*\""; Scanner scanner = new Scanner(response.trim()); @@ -370,15 +362,15 @@ public class MspDevice extends SingleMeasurementDevice implements PortHandler.Po } } - public String getCommandName() { + String getCommandName() { return this.get(0, 0); } - public boolean isOK() { + boolean isOK() { return "OK".equals(this.get(0, 1)); } - public int errorCode() { + int errorCode() { if (isOK()) { return -1; } else { @@ -386,7 +378,7 @@ public class MspDevice extends SingleMeasurementDevice implements PortHandler.Po } } - public String errorDescription() { + String errorDescription() { if (isOK()) { return null; } else { @@ -394,20 +386,20 @@ public class MspDevice extends SingleMeasurementDevice implements PortHandler.Po } } - public String get(int lineNo, int columnNo) { + String get(int lineNo, int columnNo) { return data.get(lineNo).get(columnNo); } } - private class PeakJumpMeasurement extends AbstractMeasurement { + public class PeakJumpMeasurement extends AbstractMeasurement { - private ValueCollector collector = new RegularPointCollector(getAveragingDuration(), this::result); + private RegularPointCollector collector = new RegularPointCollector(getAveragingDuration(), this::result); private StorageHelper helper = new StorageHelper(MspDevice.this, this::makeLoader); private final Meta meta; private Map peakMap; private double zero = 0; - public PeakJumpMeasurement(Meta meta) { + private PeakJumpMeasurement(Meta meta) { this.meta = meta; } @@ -441,15 +433,13 @@ public class MspDevice extends SingleMeasurementDevice implements PortHandler.Po @Override public void start() { - responseDelegate = this::eval; - try { - String name = "peakJump";//an.getString("measurementNAmname", "default"); + String measurementName = "peakJump"; String filterMode = meta.getString("filterMode", "PeakAverage"); int accuracy = meta.getInt("accuracy", 5); //PENDING вставить остальные параметры? - sendAndWait("MeasurementRemove", name); - if (sendAndWait("AddPeakJump", name, filterMode, accuracy, 0, 0, 0).isOK()) { + sendAndWait("MeasurementRemoveAll"); + if (sendAndWait("AddPeakJump", measurementName, filterMode, accuracy, 0, 0, 0).isOK()) { peakMap = new LinkedHashMap<>(); for (Meta peak : meta.getMetaList("peak")) { peakMap.put(peak.getInt("mass"), peak.getString("name", peak.getString("mass"))); @@ -464,7 +454,7 @@ public class MspDevice extends SingleMeasurementDevice implements PortHandler.Po if (!isFilamentOn()) { this.error("Can't start measurement. Filament is not turned on.", null); } - if (!sendAndWait("ScanAdd", "peakJump").isOK()) { + if (!sendAndWait("ScanAdd", measurementName).isOK()) { this.error("Failed to add scan", null); } @@ -480,9 +470,9 @@ public class MspDevice extends SingleMeasurementDevice implements PortHandler.Po @Override public boolean stop(boolean force) throws MeasurementException { try { + collector.stop(); boolean stop = sendAndWait("ScanStop").isOK(); afterStop(); - responseDelegate = null; helper.close(); return stop; } catch (PortException ex) { @@ -496,7 +486,7 @@ public class MspDevice extends SingleMeasurementDevice implements PortHandler.Po helper.push(result); } - public void eval(MspResponse response) { + void eval(MspResponse response) { //Evaluating device state change evaluateResponse(response); @@ -507,9 +497,11 @@ public class MspDevice extends SingleMeasurementDevice implements PortHandler.Po double value = Double.parseDouble(response.get(0, 2)) / 100d; String massName = Integer.toString((int) Math.floor(mass + 0.5)); collector.put(massName, value); + forEachConnection(Roles.VIEW_ROLE, NamedValueListener.class, listener -> listener.pushValue(massName, value)); break; case "ZeroReading": zero = Double.parseDouble(response.get(0, 2)) / 100d; + break; case "StartingScan": int numScans = Integer.parseInt(response.get(0, 3)); @@ -525,7 +517,7 @@ public class MspDevice extends SingleMeasurementDevice implements PortHandler.Po } } - public void error(String errorMessage, Throwable error) { + void error(String errorMessage, Throwable error) { if (error == null) { error(new MeasurementException(errorMessage)); } else { diff --git a/numass-control/msp/src/main/java/inr/numass/control/msp/MspListener.java b/numass-control/msp/src/main/java/inr/numass/control/msp/MspListener.java deleted file mode 100644 index 374e2d8b..00000000 --- a/numass-control/msp/src/main/java/inr/numass/control/msp/MspListener.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2015 Alexander Nozik. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package inr.numass.control.msp; - -/** - * - * @author darksnake - */ -public interface MspListener { - - void error(String errorMessage, Throwable error); - - void acceptMessage(String message); - - void acceptRequest(String message); - - default void acceptFilamentStateChange(String fillamentState){ - - } -} diff --git a/numass-control/msp/src/main/java/inr/numass/control/msp/fx/MspApp.java b/numass-control/msp/src/main/java/inr/numass/control/msp/fx/MspApp.java index 068829d3..228afbfe 100644 --- a/numass-control/msp/src/main/java/inr/numass/control/msp/fx/MspApp.java +++ b/numass-control/msp/src/main/java/inr/numass/control/msp/fx/MspApp.java @@ -52,66 +52,5 @@ public class MspApp extends NumassControlApplication { return Objects.equals(meta.getString("name"), "msp"); } - // private Device device; -// -// -// /** -// * @param args the command line arguments -// */ -// public static void main(String[] args) { -// launch(args); -// } -// -// @Override -// public void start(Stage primaryStage) throws Exception { -// Locale.setDefault(Locale.US);// чтобы отделение десятичных знаков было точкой -// ch.qos.logback.classic.Logger rootLogger = (ch.qos.logback.classic.Logger) LoggerFactory.getLogger(ch.qos.logback.classic.Logger.ROOT_LOGGER_NAME); -// rootLogger.setLevel(Level.INFO); -// -// FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/MspView.fxml")); -// -// Parent parent = loader.load(); -// MspViewController controller = loader.getController(); -// -// Scene scene = new Scene(parent, 800, 600); -// -// primaryStage.setTitle("Numass mass-spectrometer view"); -// primaryStage.setScene(scene); -// primaryStage.setMinHeight(400); -// primaryStage.setMinWidth(600); -// -// primaryStage.show(); -// -// setupDevice(controller); -// } -// -// private void setupDevice(MspViewController controller){ -// Meta config = NumassControlUtils.getConfig(this) -// .orElseGet(() -> NumassControlUtils.readResourceMeta("/config/msp-config.xml")); -// -// Context ctx = NumassControlUtils.setupContext(config); -// Meta mspConfig = NumassControlUtils.findDeviceMeta(config,it-> Objects.equals(it.getString("name"), "msp")) -// .orElseThrow(()-> new RuntimeException("Msp configuration not found")); -// -// -// Platform.runLater(() -> { -// try { -// device = new MspDeviceFactory().build(ctx, mspConfig); -// device.init(); -// device.connect(controller, Roles.VIEW_ROLE); -// NumassControlUtils.connectStorage(device,config); -// } catch (ControlException e) { -// throw new RuntimeException("Failed to build device", e); -// } -// }); -// } -// -// @Override -// public void stop() throws Exception { -// super.stop(); -// if (device != null) { -// device.shutdown(); -// } -// } } diff --git a/numass-control/msp/src/main/java/inr/numass/control/msp/fx/MspViewController.java b/numass-control/msp/src/main/java/inr/numass/control/msp/fx/MspViewController.java index 4ffb6a52..0f29fe66 100644 --- a/numass-control/msp/src/main/java/inr/numass/control/msp/fx/MspViewController.java +++ b/numass-control/msp/src/main/java/inr/numass/control/msp/fx/MspViewController.java @@ -15,9 +15,9 @@ */ package inr.numass.control.msp.fx; +import hep.dataforge.control.NamedValueListener; +import hep.dataforge.control.devices.Device; import hep.dataforge.control.devices.DeviceListener; -import hep.dataforge.control.measurements.Measurement; -import hep.dataforge.control.measurements.MeasurementListener; import hep.dataforge.exceptions.ControlException; import hep.dataforge.exceptions.PortException; import hep.dataforge.fx.fragments.FragmentWindow; @@ -28,12 +28,11 @@ import hep.dataforge.plots.data.TimePlottable; import hep.dataforge.plots.data.TimePlottableGroup; import hep.dataforge.plots.fx.PlotContainer; import hep.dataforge.plots.jfreechart.JFreeChartFrame; -import hep.dataforge.tables.DataPoint; import hep.dataforge.values.Value; import inr.numass.control.DeviceViewConnection; import inr.numass.control.msp.MspDevice; -import inr.numass.control.msp.MspListener; import javafx.application.Platform; +import javafx.beans.value.ChangeListener; import javafx.beans.value.ObservableValue; import javafx.collections.FXCollections; import javafx.event.ActionEvent; @@ -52,7 +51,6 @@ import org.controlsfx.control.ToggleSwitch; import java.io.IOException; import java.net.URL; -import java.time.Instant; import java.util.ResourceBundle; /** @@ -60,7 +58,7 @@ import java.util.ResourceBundle; * * @author darksnake */ -public class MspViewController extends DeviceViewConnection implements DeviceListener, Initializable, MspListener, MeasurementListener { +public class MspViewController extends DeviceViewConnection implements DeviceListener, Initializable, NamedValueListener { public static MspViewController build() { try { @@ -77,26 +75,12 @@ public class MspViewController extends DeviceViewConnection implement private JFreeChartFrame plot; private LogFragment logFragment; -// private final ConfigChangeListener viewConfigObserver = new ConfigChangeListener() { -// -// @Override -// public void notifyElementChanged(String name, List oldItem, List newItem) { -// updatePlot(); -// } -// -// @Override -// public void notifyValueChanged(String name, Value oldItem, Value newItem) { -// updatePlot(); -// } -// -// }; - @FXML private BorderPane root; @FXML - private ToggleSwitch fillamentButton; + private ToggleSwitch filamentButton; @FXML - private Circle fillamentIndicator; + private Circle filamentIndicator; @FXML private ToggleButton measureButton; @FXML @@ -106,7 +90,7 @@ public class MspViewController extends DeviceViewConnection implement @FXML private ToggleButton consoleButton; @FXML - private ComboBox fillamentSelector; + private ComboBox filamentSelector; @FXML private ToggleButton storeButton; @@ -121,8 +105,8 @@ public class MspViewController extends DeviceViewConnection implement logFragment = new LogFragment(); new FragmentWindow(logFragment).bindTo(consoleButton); logFragment.addRootLogHandler(); - fillamentSelector.setItems(FXCollections.observableArrayList(1, 2)); - fillamentSelector.setConverter(new StringConverter() { + filamentSelector.setItems(FXCollections.observableArrayList(1, 2)); + filamentSelector.setConverter(new StringConverter() { @Override public String toString(Integer object) { return "Filament " + object; @@ -134,19 +118,39 @@ public class MspViewController extends DeviceViewConnection implement } }); - fillamentSelector.getSelectionModel().select(0); - fillamentButton.selectedProperty().addListener((ObservableValue observable, Boolean oldValue, Boolean newValue) -> { + filamentSelector.getSelectionModel().select(0); + filamentButton.selectedProperty().addListener((ObservableValue observable, Boolean oldValue, Boolean newValue) -> { try { - fillamentSelector.setDisable(newValue); + filamentSelector.setDisable(newValue); getDevice().setFilamentOn(newValue); } catch (PortException ex) { getDevice().getLogger().error("Failed to toggle filaments"); } }); - fillamentButton.disableProperty().bind(connectButton.selectedProperty().not()); - measureButton.disableProperty().bind(fillamentButton.selectedProperty().not()); + filamentButton.disableProperty().bind(connectButton.selectedProperty().not()); + measureButton.disableProperty().bind(filamentButton.selectedProperty().not()); storeButton.disableProperty().bind(measureButton.selectedProperty().not()); + getStateBinding("filamentStatus").addListener(new ChangeListener() { + @Override + public void changed(ObservableValue observable, Value oldValue, Value newValue) { + String filamentState = newValue.stringValue(); + Platform.runLater(() -> { + switch (filamentState) { + case "ON": + filamentIndicator.setFill(Paint.valueOf("red")); + break; + case "OFF": + filamentIndicator.setFill(Paint.valueOf("blue")); + break; + case "WARM-UP": + case "COOL-DOWN": + filamentIndicator.setFill(Paint.valueOf("yellow")); + break; + } + }); + } + }); } @@ -158,7 +162,6 @@ public class MspViewController extends DeviceViewConnection implement @Override public void open(MspDevice device) throws Exception { super.open(device); - getDevice().setMspListener(this); updatePlot(); bindBooleanToState("connected", connectButton.selectedProperty()); @@ -187,17 +190,18 @@ public class MspViewController extends DeviceViewConnection implement this.plot.configure(config.getMeta("plotFrame")); } if (config.hasMeta("peakJump.peak")) { - for (Meta an : config.getMetaList("peakJump.peak")) { - String mass = an.getString("mass"); + for (Meta peakMeta : config.getMetaList("peakJump.peak")) { + String mass = peakMeta.getString("mass"); if (!this.plottables.has(mass)) { TimePlottable newPlottable = new TimePlottable(mass, mass); - newPlottable.configure(an); + newPlottable.configure(peakMeta); newPlottable.setMaxItems(1000); newPlottable.setPrefItems(400); + newPlottable.configureValue("titleBase",peakMeta.getString("title",mass)); this.plottables.add(newPlottable); plot.add(newPlottable); } else { - plottables.get(mass).configure(an); + plottables.get(mass).configure(peakMeta); } } } else { @@ -207,28 +211,13 @@ public class MspViewController extends DeviceViewConnection implement } @Override - public void acceptMessage(String message) { + public void evaluateDeviceException(Device device, String message, Throwable exception) { Platform.runLater(() -> { - logFragment.appendLine("RECIEVE: " + message); + logFragment.appendLine("ERROR: " + message); + showError(message); }); } - @Override - public void acceptRequest(String message) { - Platform.runLater(() -> { - logFragment.appendLine("SEND: " + message); - }); - } - - @Override - public void error(String errorMessage, Throwable error) { - Platform.runLater(() -> { - logFragment.appendLine("ERROR: " + errorMessage); - showError(errorMessage); - }); - - } - @FXML private void onPlotToggle(ActionEvent event) throws ControlException { if (measureButton.isSelected()) { @@ -251,50 +240,28 @@ public class MspViewController extends DeviceViewConnection implement } - @Override - public void acceptFilamentStateChange(String fillamentState) { - Platform.runLater(() -> { - switch (fillamentState) { - case "ON": - this.fillamentIndicator.setFill(Paint.valueOf("red")); - break; - case "OFF": - this.fillamentIndicator.setFill(Paint.valueOf("blue")); - break; - case "WARM-UP": - case "COOL-DOWN": - this.fillamentIndicator.setFill(Paint.valueOf("yellow")); - break; - - } - }); - } - @FXML private void onStoreButtonClick(ActionEvent event) { getDevice().setState("storing", storeButton.isSelected()); } - @Override public Node getFXNode() { return root; } @Override - public void onMeasurementResult(Measurement measurement, Object res, Instant time) { - DataPoint result = DataPoint.class.cast(res); - for (String valueName : result.names()) { - TimePlottable pl = plottables.get(valueName); - if (pl != null) { - pl.put(Value.of(result.getValue(valueName))); + public void pushValue(String valueName, Value value) { + TimePlottable pl = plottables.get(valueName); + if (pl != null) { + if (value.doubleValue() > 0) { + pl.put(value); + } else { + pl.put(Value.NULL); } + String titleBase = pl.getConfig().getString("titleBase"); + String title = String.format("%s (%.4g)", titleBase, value.doubleValue()); + pl.configureValue("title", title); } } - - @Override - public void onMeasurementFailed(Measurement measurement, Throwable exception) { - - } - } diff --git a/numass-control/msp/src/main/resources/config/devices.xml b/numass-control/msp/src/main/resources/config/devices.xml index 0197d597..a1f61c5e 100644 --- a/numass-control/msp/src/main/resources/config/devices.xml +++ b/numass-control/msp/src/main/resources/config/devices.xml @@ -21,23 +21,15 @@ limitations under the License. - + - + - + - + - - - - - - - - \ No newline at end of file diff --git a/numass-control/msp/src/main/resources/fxml/MspView.fxml b/numass-control/msp/src/main/resources/fxml/MspView.fxml index 80c2d07b..1ac7e6ca 100644 --- a/numass-control/msp/src/main/resources/fxml/MspView.fxml +++ b/numass-control/msp/src/main/resources/fxml/MspView.fxml @@ -27,13 +27,13 @@ limitations under the License. - - + + - +