diff --git a/numass-control/cryotemp/build.gradle b/numass-control/cryotemp/build.gradle index 09b1b135..73fc1ae9 100644 --- a/numass-control/cryotemp/build.gradle +++ b/numass-control/cryotemp/build.gradle @@ -21,4 +21,12 @@ task debug(dependsOn: classes, type: JavaExec) { classpath = sourceSets.main.runtimeClasspath description "Start application in debug mode with default virtual port" group "debug" +} + +task testRun(dependsOn: classes, type: JavaExec) { + main mainClass + args(["--cfgFile=D:/temp/test/numass-devices.xml", "--device=thermo-1"]) + classpath = sourceSets.main.runtimeClasspath + description "Start application using real device" + group "debug" } \ No newline at end of file diff --git a/numass-control/cryotemp/src/main/java/inr/numass/cryotemp/PKT8App.java b/numass-control/cryotemp/src/main/java/inr/numass/cryotemp/PKT8App.java index 19094ea3..3a2319da 100644 --- a/numass-control/cryotemp/src/main/java/inr/numass/cryotemp/PKT8App.java +++ b/numass-control/cryotemp/src/main/java/inr/numass/cryotemp/PKT8App.java @@ -16,10 +16,16 @@ package inr.numass.cryotemp; import ch.qos.logback.classic.Level; +import hep.dataforge.control.connections.Roles; +import hep.dataforge.control.connections.StorageConnection; import hep.dataforge.exceptions.ControlException; import hep.dataforge.io.MetaFileReader; +import hep.dataforge.meta.Meta; +import hep.dataforge.meta.MetaUtils; +import hep.dataforge.storage.commons.StorageFactory; import hep.dataforge.storage.commons.StorageManager; import javafx.application.Application; +import javafx.application.Platform; import javafx.fxml.FXMLLoader; import javafx.scene.Parent; import javafx.scene.Scene; @@ -28,6 +34,7 @@ import org.slf4j.LoggerFactory; import java.io.File; import java.io.IOException; +import java.net.URISyntaxException; import java.text.ParseException; import java.util.Locale; @@ -35,54 +42,10 @@ import java.util.Locale; * @author darksnake */ public class PKT8App extends Application { - - PKT8MainViewController controller; - - @Override - public void start(Stage primaryStage) throws IOException, ControlException, ParseException { - 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); - new StorageManager().startGlobal(); - - FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/PKT8MainView.fxml")); - - Parent parent = loader.load(); - controller = loader.getController(); - -// Meta deviceMeta = XMLMetaConverter.fromStream(getClass().getResourceAsStream("/defaultConfig.xml")); - -// controller.setupDevice(deviceMeta); - - Scene scene = new Scene(parent, 600, 400); + public static final String DEFAULT_CONFIG_LOCATION = "numass-devices.xml"; - primaryStage.setTitle("PKT8 cryogenic temperature viewer"); - primaryStage.setScene(scene); - primaryStage.setMinHeight(400); - primaryStage.setMinWidth(600); -// primaryStage.setResizable(false); - - primaryStage.show(); - - if (getParameters().getNamed().containsKey("cfgFile")) { - controller.setConfig(MetaFileReader.read(new File(getParameters().getNamed().get("cfgFile")))); - } else if (Boolean.parseBoolean(getParameters().getNamed().getOrDefault("debug", "false"))) { - controller.loadTestConfig(); - } else { - controller.startConfigDialog(); - } - } - - @Override - public void stop() throws Exception { - super.stop(); - if (controller != null) { - controller.close(); - controller = null; - } -// System.exit(0); - } + PKT8Device device; /** * @param args the command line arguments @@ -91,4 +54,109 @@ public class PKT8App extends Application { launch(args); } + +// public Meta startConfigDialog(Scene scene) throws IOException, ParseException, ControlException { +// FileChooser fileChooser = new FileChooser(); +// fileChooser.setTitle("Open configuration file"); +// fileChooser.setInitialFileName(DEFAULT_CONFIG_LOCATION); +//// fileChooser.setInitialDirectory(GlobalContext.instance().io().getRootDirectory()); +// fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("xml", "*.xml", "*.XML")); +// fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("json", "*.json", "*.JSON")); +//// fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("all", "*.*")); +// File cfgFile = fileChooser.showOpenDialog(scene.getWindow()); +// +// if (cfgFile != null) { +// return MetaFileReader.read(cfgFile); +// } else { +// return null; +// } +// } + + @Override + public void start(Stage primaryStage) throws IOException, ControlException, ParseException { + 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); + new StorageManager().startGlobal(); + + String deviceName = getParameters().getNamed().getOrDefault("device", "PKT-8"); + + Meta config; + + if (Boolean.parseBoolean(getParameters().getNamed().getOrDefault("debug", "false"))) { + config = loadTestConfig(); + } else { + config = MetaFileReader.read(new File(getParameters().getNamed().getOrDefault("cfgFile", DEFAULT_CONFIG_LOCATION))); + } + + + device = setupDevice(deviceName, config); + + // setting up storage connections + if (config.hasNode("storage")) { + config.getNodes("storage").forEach(node -> { + device.connect(new StorageConnection(StorageFactory.buildStorage(device.getContext(), node)), Roles.STORAGE_ROLE); + }); + } + + FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/PKT8Indicator.fxml")); + PKT8Controller controller = new PKT8Controller(device); + loader.setController(controller); + + Parent parent = loader.load(); + + + Scene scene = new Scene(parent, 400, 400); + primaryStage.setTitle("Numass temperature view"); + primaryStage.setScene(scene); + primaryStage.setMinHeight(400); + primaryStage.setMinWidth(400); +// primaryStage.setResizable(false); + + primaryStage.show(); + + Platform.runLater(() -> { + try { + device.init(); +// controller.start(); + } catch (ControlException e) { + e.printStackTrace(); + throw new RuntimeException(e); + } + }); + } + + public Meta loadTestConfig() throws ControlException { + try { + return MetaFileReader + .read(new File(getClass().getResource("/config/defaultConfig.xml").toURI())); + } catch (URISyntaxException | IOException | ParseException ex) { + throw new Error(ex); + } + } + + public PKT8Device setupDevice(String deviceName, Meta config) throws ControlException { + Meta deviceMeta; + + if (config.hasNode("device")) { + deviceMeta = MetaUtils.findNodeByValue(config, "device", "name", deviceName); + } else { + deviceMeta = config; + } + + PKT8Device device = new PKT8Device(deviceMeta.getString("port", "virtual")); + + device.configure(deviceMeta); + + return device; + } + + @Override + public void stop() throws Exception { + super.stop(); + if (device != null) { + device.shutdown(); + } + } + } diff --git a/numass-control/cryotemp/src/main/java/inr/numass/cryotemp/PKT8Controller.java b/numass-control/cryotemp/src/main/java/inr/numass/cryotemp/PKT8Controller.java new file mode 100644 index 00000000..25b44d9c --- /dev/null +++ b/numass-control/cryotemp/src/main/java/inr/numass/cryotemp/PKT8Controller.java @@ -0,0 +1,125 @@ +package inr.numass.cryotemp; + +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.MeasurementException; +import hep.dataforge.fx.ConsoleFragment; +import hep.dataforge.values.Value; +import javafx.application.Platform; +import javafx.event.ActionEvent; +import javafx.fxml.FXML; +import javafx.fxml.Initializable; +import javafx.scene.control.Label; +import javafx.scene.control.TableColumn; +import javafx.scene.control.TableView; +import javafx.scene.control.ToggleButton; +import javafx.scene.control.cell.PropertyValueFactory; + +import java.net.URL; +import java.time.Instant; +import java.util.ResourceBundle; + +/** + * Created by darksnake on 07-Oct-16. + */ +public class PKT8Controller implements Initializable, DeviceListener, MeasurementListener { + + private final PKT8Device device; + private ConsoleFragment consoleFragment; + private PKT8PlotFragment plotFragment; + @FXML + private ToggleButton startStopButton; + @FXML + private ToggleButton consoleButton; + @FXML + private ToggleButton plotButton; + @FXML + private Label lastUpdateLabel; + + @FXML + private TableView table; + + @FXML + private TableColumn, String> sensorColumn; + + @FXML + private TableColumn, Double> resColumn; + + @FXML + private TableColumn, String> tempColumn; + + + public PKT8Controller(PKT8Device device) { + this.device = device; + } + + @Override + public void initialize(URL location, ResourceBundle resources) { + this.consoleFragment = new ConsoleFragment(); + consoleFragment.bindTo(consoleButton); + plotFragment = new PKT8PlotFragment(device); + plotFragment.bindTo(plotButton); + + sensorColumn.setCellValueFactory(new PropertyValueFactory<>("channel")); + resColumn.setCellValueFactory(new PropertyValueFactory<>("rawString")); + tempColumn.setCellValueFactory(new PropertyValueFactory<>("temperatureString")); + startStopButton.selectedProperty().setValue(device.isMeasuring()); + } + + @Override + public void onMeasurementResult(Measurement measurement, PKT8Result result, Instant time) { + Platform.runLater(() -> { + lastUpdateLabel.setText(time.toString()); + table.getItems().removeIf(it -> it.channel.equals(result.channel)); + table.getItems().add(result); + table.getItems().sort((o1, o2) -> o1.channel.compareTo(o2.channel)); + }); + } + + @Override + public void onMeasurementFailed(Measurement measurement, Throwable exception) { + + } + + @Override + public void notifyDeviceStateChanged(Device device, String name, Value state) { + + } + + @Override + public void evaluateDeviceException(Device device, String message, Throwable exception) { + + } + + + public void start() throws MeasurementException { + device.startMeasurement().addListener(this); + } + + public void stop() throws MeasurementException { + if (device.isMeasuring()) { + device.getMeasurement().removeListener(this); + device.stopMeasurement(false); + } + } + + + @FXML + private void onStartStopClick(ActionEvent event) { + if (device != null) { + try { + if (startStopButton.isSelected()) { + start(); + } else { + //in case device started + stop(); + } + } catch (ControlException ex) { + evaluateDeviceException(device, "Failed to start or stop device", ex); + } + } + } +} diff --git a/numass-control/cryotemp/src/main/java/inr/numass/cryotemp/PKT8Device.java b/numass-control/cryotemp/src/main/java/inr/numass/cryotemp/PKT8Device.java index f8dd6e94..057c82df 100644 --- a/numass-control/cryotemp/src/main/java/inr/numass/cryotemp/PKT8Device.java +++ b/numass-control/cryotemp/src/main/java/inr/numass/cryotemp/PKT8Device.java @@ -21,6 +21,7 @@ import hep.dataforge.control.connections.PointListenerConnection; import hep.dataforge.control.connections.Roles; import hep.dataforge.control.connections.StorageConnection; import hep.dataforge.control.devices.PortSensor; +import hep.dataforge.control.devices.annotations.RoleDef; import hep.dataforge.control.measurements.AbstractMeasurement; import hep.dataforge.control.measurements.Measurement; import hep.dataforge.control.ports.PortHandler; @@ -30,8 +31,8 @@ import hep.dataforge.exceptions.PortException; import hep.dataforge.exceptions.StorageException; import hep.dataforge.meta.Meta; import hep.dataforge.storage.api.PointLoader; +import hep.dataforge.storage.api.Storage; import hep.dataforge.storage.commons.LoaderFactory; -import hep.dataforge.storage.commons.StorageFactory; import hep.dataforge.tables.DataPoint; import hep.dataforge.tables.PointListener; import hep.dataforge.tables.TableFormatBuilder; @@ -39,12 +40,15 @@ import hep.dataforge.tables.TableFormatBuilder; import java.time.Duration; import java.time.Instant; import java.util.*; +import java.util.stream.Collectors; /** * A device controller for Dubna PKT 8 cryogenic thermometry device * * @author Alexander Nozik */ +@RoleDef(name = Roles.STORAGE_ROLE) +@RoleDef(name = Roles.POINT_LISTENER_ROLE) public class PKT8Device extends PortSensor { public static final String PGA = "pga"; @@ -55,7 +59,6 @@ public class PKT8Device extends PortSensor { * The key is the letter (a,b,c,d...) as in measurements */ private final Map channels = new HashMap<>(); - // private PointLoader pointLoader; private RegularPointCollector collector; public PKT8Device(String portName) { @@ -95,7 +98,7 @@ public class PKT8Device extends PortSensor { setSPS(meta().getInt("sps", 0)); setBUF(meta().getInt("abuf", 100)); - setupStorage(); + setupLoaders(); } @@ -240,7 +243,7 @@ public class PKT8Device extends PortSensor { return getState(ABUF).stringValue(); } - private void setupStorage() { + private void setupLoaders() { // Building data format TableFormatBuilder tableFormatBuilder = new TableFormatBuilder() @@ -252,24 +255,21 @@ public class PKT8Device extends PortSensor { names.add(channel.getName()); } - // setting up storage connections - if (meta().hasNode("storage")) { - meta().getNodes("storage").forEach(node -> { - connect(new StorageConnection(StorageFactory.buildStorage(getContext(), node))); - }); - } - // setting up loader for each of storages - forEachTypedConnection(Roles.STORAGE_ROLE, StorageConnection.class, connection -> { + List storages = connections().filter(it -> it.getValue() + .contains(Roles.STORAGE_ROLE) && it.getKey() instanceof StorageConnection) + .map(it -> ((StorageConnection) it.getKey()).getStorage()).collect(Collectors.toList()); + + storages.forEach(storage -> { String suffix = Integer.toString((int) Instant.now().toEpochMilli()); PointLoader pointLoader = null; try { - pointLoader = LoaderFactory.buildPointLoder(connection.getStorage(), + pointLoader = LoaderFactory.buildPointLoder(storage, "cryotemp_" + suffix, "", "timestamp", tableFormatBuilder.build()); this.connect(new LoaderConnection(pointLoader), Roles.POINT_LISTENER_ROLE); } catch (StorageException e) { - getLogger().error("Failed to build loader from storage {}", connection.getStorage().getName()); + getLogger().error("Failed to build loader from storage {}", storage.getName()); } }); @@ -284,7 +284,7 @@ public class PKT8Device extends PortSensor { }, duration, names); } - public void connectPointListener(PointListenerConnection listener){ + public void connectPointListener(PointListenerConnection listener) { this.connect(listener, Roles.POINT_LISTENER_ROLE); } @@ -334,6 +334,7 @@ public class PKT8Device extends PortSensor { } try { + getLogger().info("Starting measurement"); handler.holdBy(this); handler.send("s"); afterStart(); @@ -350,6 +351,7 @@ public class PKT8Device extends PortSensor { } try { + getLogger().info("Stopping measurement"); String response = getHandler().sendAndWait("p", 400).trim(); // Должно быть именно с большой буквы!!! return "Stopped".equals(response) || "stopped".equals(response); @@ -372,7 +374,7 @@ public class PKT8Device extends PortSensor { if (isStarted()) { if (trimmed.equals("Stopped") || trimmed.equals("stopped")) { afterPause(); - getLogger().info("Measurement stopped"); +// getLogger().info("Measurement stopped"); } else { String designation = trimmed.substring(0, 1); double rawValue = Double.parseDouble(trimmed.substring(1)) / 100; diff --git a/numass-control/cryotemp/src/main/java/inr/numass/cryotemp/PKT8MainViewController.java b/numass-control/cryotemp/src/main/java/inr/numass/cryotemp/PKT8MainViewController.java deleted file mode 100644 index bf51544b..00000000 --- a/numass-control/cryotemp/src/main/java/inr/numass/cryotemp/PKT8MainViewController.java +++ /dev/null @@ -1,261 +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.cryotemp; - -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.fx.ConsoleFragment; -import hep.dataforge.io.MetaFileReader; -import hep.dataforge.meta.Meta; -import hep.dataforge.meta.MetaUtils; -import hep.dataforge.plots.PlotUtils; -import hep.dataforge.plots.data.TimePlottable; -import hep.dataforge.plots.data.TimePlottableGroup; -import hep.dataforge.plots.data.XYPlottable; -import hep.dataforge.plots.fx.FXPlotFrame; -import hep.dataforge.plots.fx.PlotContainer; -import hep.dataforge.plots.jfreechart.JFreeChartFrame; -import hep.dataforge.values.Value; -import javafx.beans.InvalidationListener; -import javafx.beans.Observable; -import javafx.event.ActionEvent; -import javafx.fxml.FXML; -import javafx.fxml.Initializable; -import javafx.scene.control.ToggleButton; -import javafx.scene.layout.AnchorPane; -import javafx.stage.FileChooser; - -import java.io.File; -import java.io.IOException; -import java.net.URISyntaxException; -import java.net.URL; -import java.text.ParseException; -import java.time.Duration; -import java.time.Instant; -import java.util.Collection; -import java.util.ResourceBundle; - -/** - * FXML Controller class - * - * @author darksnake - */ -public class PKT8MainViewController implements Initializable, DeviceListener, MeasurementListener, AutoCloseable { - - public static final String DEFAULT_CONFIG_LOCATION = "devices.xml"; - ConsoleFragment consoleFragment; - private PKT8Device device; - private FXPlotFrame plotFrame; - private TimePlottableGroup plottables; - - @FXML - private ToggleButton startStopButton; - @FXML - private ToggleButton rawDataButton; - @FXML - private AnchorPane plotArea; - @FXML - private ToggleButton consoleButton; - - @Override - public void close() throws Exception { - if (device != null) { - device.shutdown(); - } - } - - /** - * Initializes the controller class. - */ - @Override - public void initialize(URL url, ResourceBundle rb) { -// setupPlotFrame(Meta.empty()); - this.consoleFragment = new ConsoleFragment(); - consoleFragment.bindTo(consoleButton); - rawDataButton.selectedProperty().addListener(new InvalidationListener() { - @Override - public void invalidated(Observable observable) { - if (plotFrame != null) { - setupPlotFrame(plotFrame.getConfig()); - if (device != null) { - setupChannels(); - } - } - } - }); - } - - public void startConfigDialog() throws IOException, ParseException, ControlException { - FileChooser fileChooser = new FileChooser(); - fileChooser.setTitle("Open configuration file"); - fileChooser.setInitialFileName(DEFAULT_CONFIG_LOCATION); -// fileChooser.setInitialDirectory(GlobalContext.instance().io().getRootDirectory()); - fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("xml", "*.xml", "*.XML")); - fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("json", "*.json", "*.JSON")); -// fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("all", "*.*")); - File cfgFile = fileChooser.showOpenDialog(startStopButton.getScene().getWindow()); - - if (cfgFile != null) { - setConfig(MetaFileReader.read(cfgFile)); - } - } - - public void loadTestConfig() throws ControlException { - try { - Meta testConfig = MetaFileReader - .read(new File(getClass().getResource("/config/defaultConfig.xml").toURI())); - setConfig(testConfig); - } catch (URISyntaxException | IOException | ParseException ex) { - throw new Error(ex); - } - } - - public String getDeviceName() { - return "PKT8"; - } - - public void setConfig(Meta config) throws ControlException { - if (config.hasNode("plotConfig")) { - Meta plotConfig = MetaUtils.findNodeByValue(config, "plotConfig", "device", getDeviceName()); - if (plotConfig == null) { - plotConfig = config.getNode("plotConfig"); - } - - setupPlotFrame(plotConfig.getNode("plotFrame", Meta.empty())); - } - - if (config.hasNode("device")) { - Meta deviceMeta = MetaUtils.findNodeByValue(config, "device", "name", Value.of(getDeviceName())); - setupDevice(deviceMeta); - } else { - setupDevice(config); - } - - } - - /** - * Set o reset plot area - */ - private synchronized void setupPlotFrame(Meta plotFrameMeta) { - plottables = new TimePlottableGroup(); - plottables.setMaxItems(plotFrameMeta.getInt("maxItems", 3000)); - plottables.setMaxAge(Duration.parse(plotFrameMeta.getString("maxAge", "PT2H"))); - plotArea.getChildren().clear(); - plotFrame = new JFreeChartFrame(plotFrameMeta); - PlotUtils.setXAxis(plotFrame, "timestamp", null, "time"); - PlotContainer container = PlotContainer.anchorTo(plotArea); - container.setPlot(plotFrame); - } - - public void setupDevice(Meta deviceMeta) throws ControlException { - if (device != null) { - device.stopMeasurement(true); - device.shutdown(); - } - - this.device = new PKT8Device(deviceMeta.getString("port", "virtual")); - - device.configure(deviceMeta); - - device.addDeviceListener(this); - consoleFragment.addLogHandler(device.getLogger()); - - device.init(); - } - - private void setupChannels() { - Collection channels = this.device.getChanels(); - - //plot config from device configuration - //Do not use view config here, it is applyed separately - channels.stream() - .filter(channel -> !plottables.hasPlottable(channel.getName())) - .forEach(channel -> { - - //plot config from device configuration - Meta deviceLineMeta = channel.meta().getNode("plot", channel.meta()); - - //Do not use view config here, it is applyed separately - TimePlottable plottable = new TimePlottable(channel.getName()); - plottable.configure(deviceLineMeta); - plottables.addPlottable(plottable); - plotFrame.add(plottable); - }); - plottables.applyConfig(plotFrame.getConfig()); - } - - @Override - public void notifyDeviceInitialized(Device device) { - setupChannels(); - startStopButton.setDisable(false); - } - - - @Override - public void notifyDeviceShutdown(Device device) { - startStopButton.setDisable(true); - } - - - @Override - public synchronized void onMeasurementResult(Measurement measurement, PKT8Result result, Instant time) { - //PENDING replace by connection? - if (rawDataButton.isSelected()) { - plottables.put(result.channel, result.rawValue); - } else { - plottables.put(result.channel, result.temperature); - } - } - - @Override - public void onMeasurementFailed(Measurement measurement, Throwable exception) { - - } - - @Override - public void notifyDeviceStateChanged(Device device, String name, Value state) { - - } - - @Override - public void evaluateDeviceException(Device device, String message, Throwable exception) { - - } - - @FXML - private void onStartStopClick(ActionEvent event) { - if (device != null) { - try { - if (startStopButton.isSelected()) { - device.startMeasurement() - .addListener(this); - } else { - //in case device started - if (device.isMeasuring()) { - device.getMeasurement().removeListener(this); - device.stopMeasurement(false); - } - } - } catch (ControlException ex) { - - } - } - } - -} diff --git a/numass-control/cryotemp/src/main/java/inr/numass/cryotemp/PKT8PlotController.java b/numass-control/cryotemp/src/main/java/inr/numass/cryotemp/PKT8PlotController.java new file mode 100644 index 00000000..4d61f5a9 --- /dev/null +++ b/numass-control/cryotemp/src/main/java/inr/numass/cryotemp/PKT8PlotController.java @@ -0,0 +1,145 @@ +/* + * 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.cryotemp; + +import hep.dataforge.control.measurements.Measurement; +import hep.dataforge.control.measurements.MeasurementListener; +import hep.dataforge.meta.Meta; +import hep.dataforge.meta.MetaUtils; +import hep.dataforge.plots.PlotUtils; +import hep.dataforge.plots.data.TimePlottable; +import hep.dataforge.plots.data.TimePlottableGroup; +import hep.dataforge.plots.data.XYPlottable; +import hep.dataforge.plots.fx.FXPlotFrame; +import hep.dataforge.plots.fx.PlotContainer; +import hep.dataforge.plots.jfreechart.JFreeChartFrame; +import javafx.fxml.FXML; +import javafx.fxml.Initializable; +import javafx.scene.control.ToggleButton; +import javafx.scene.layout.AnchorPane; + +import java.net.URL; +import java.time.Duration; +import java.time.Instant; +import java.util.Collection; +import java.util.ResourceBundle; + +/** + * FXML Controller class + * + * @author darksnake + */ +public class PKT8PlotController implements Initializable, MeasurementListener { + + private final PKT8Device device; + private FXPlotFrame plotFrame; + private TimePlottableGroup plottables; + + @FXML + private ToggleButton rawDataButton; + @FXML + private AnchorPane plotArea; + + public PKT8PlotController(PKT8Device device) { + this.device = device; + } + + /** + * Initializes the controller class. + */ + @Override + public void initialize(URL url, ResourceBundle rb) { + rawDataButton.selectedProperty().addListener(observable -> { + if (plotFrame != null) { + setupPlotFrame(plotFrame.getConfig()); + if (device != null) { + setupChannels(); + } + } + }); + + configure(device.getConfig()); + setupChannels(); + } + + public String getDeviceName() { + return device.getName(); + } + + public void configure(Meta config) { + if (config.hasNode("plotConfig")) { + Meta plotConfig = MetaUtils.findNodeByValue(config, "plotConfig", "device", getDeviceName()); + if (plotConfig == null) { + plotConfig = config.getNode("plotConfig"); + } + + setupPlotFrame(plotConfig.getNode("plotFrame", Meta.empty())); + } + } + + /** + * Set o reset plot area + */ + private synchronized void setupPlotFrame(Meta plotFrameMeta) { + plottables = new TimePlottableGroup(); + plottables.setMaxItems(plotFrameMeta.getInt("maxItems", 3000)); + plottables.setMaxAge(Duration.parse(plotFrameMeta.getString("maxAge", "PT2H"))); + plotArea.getChildren().clear(); + plotFrame = new JFreeChartFrame(plotFrameMeta); + PlotUtils.setXAxis(plotFrame, "timestamp", null, "time"); + PlotContainer container = PlotContainer.anchorTo(plotArea); + container.setPlot(plotFrame); + } + + private void setupChannels() { + Collection channels = this.device.getChanels(); + + //plot config from device configuration + //Do not use view config here, it is applyed separately + channels.stream() + .filter(channel -> !plottables.hasPlottable(channel.getName())) + .forEach(channel -> { + + //plot config from device configuration + Meta deviceLineMeta = channel.meta().getNode("plot", channel.meta()); + + //Do not use view config here, it is applyed separately + TimePlottable plottable = new TimePlottable(channel.getName()); + plottable.configure(deviceLineMeta); + plottables.addPlottable(plottable); + plotFrame.add(plottable); + }); + plottables.applyConfig(plotFrame.getConfig()); + } + + @Override + public synchronized void onMeasurementResult(Measurement measurement, PKT8Result result, Instant time) { + //PENDING replace by connection? + if (rawDataButton.isSelected()) { + plottables.put(result.channel, result.rawValue); + } else { + plottables.put(result.channel, result.temperature); + } + } + + @Override + public void onMeasurementFailed(Measurement measurement, Throwable exception) { + + } + + + +} diff --git a/numass-control/cryotemp/src/main/java/inr/numass/cryotemp/PKT8PlotFragment.java b/numass-control/cryotemp/src/main/java/inr/numass/cryotemp/PKT8PlotFragment.java new file mode 100644 index 00000000..d8b77554 --- /dev/null +++ b/numass-control/cryotemp/src/main/java/inr/numass/cryotemp/PKT8PlotFragment.java @@ -0,0 +1,70 @@ +package inr.numass.cryotemp; + +import hep.dataforge.fx.FXFragment; +import javafx.fxml.FXMLLoader; +import javafx.scene.Parent; +import javafx.scene.Scene; +import javafx.stage.Stage; +import javafx.stage.Window; + +import java.io.IOException; + +/** + * Created by darksnake on 07-Oct-16. + */ +public class PKT8PlotFragment extends FXFragment { + private final PKT8Device device; + private PKT8PlotController plotController; + + public PKT8PlotFragment(PKT8Device device) { + this.device = device; + } + + public PKT8PlotFragment(Window window, PKT8Device device) { + super(window); + this.device = device; + } + + @Override + protected Stage buildStage(Parent root) { + Stage stage = new Stage(); + Scene scene = new Scene(root, 600, 400); + + + stage.setTitle("PKT8 cryogenic temperature viewer"); + stage.setScene(scene); + stage.setMinHeight(400); + stage.setMinWidth(600); + stage.sizeToScene(); + + return stage; + } + + @Override + protected Parent getRoot() { + FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/PKT8Plot.fxml")); + plotController = new PKT8PlotController(device); + loader.setController(plotController); + try { + return loader.load(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + @Override + protected void onShow() { + super.onShow(); + if (device.isMeasuring()) { + device.getMeasurement().addListener(plotController); + } + } + + @Override + protected void onHide() { + super.onHide(); + if (device.isMeasuring()) { + device.getMeasurement().removeListener(plotController); + } + } +} diff --git a/numass-control/cryotemp/src/main/java/inr/numass/cryotemp/PKT8Result.java b/numass-control/cryotemp/src/main/java/inr/numass/cryotemp/PKT8Result.java index eedf7be3..09cce9da 100644 --- a/numass-control/cryotemp/src/main/java/inr/numass/cryotemp/PKT8Result.java +++ b/numass-control/cryotemp/src/main/java/inr/numass/cryotemp/PKT8Result.java @@ -31,4 +31,15 @@ public class PKT8Result { this.temperature = temperature; } + public String getChannel() { + return channel; + } + + public String getRawString() { + return String.format("%.2f", rawValue); + } + + public String getTemperatureString() { + return String.format("%.2f", temperature); + } } diff --git a/numass-control/cryotemp/src/main/resources/fxml/PKT8Indicator.fxml b/numass-control/cryotemp/src/main/resources/fxml/PKT8Indicator.fxml new file mode 100644 index 00000000..653f4781 --- /dev/null +++ b/numass-control/cryotemp/src/main/resources/fxml/PKT8Indicator.fxml @@ -0,0 +1,45 @@ + + + + + + +
+ + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + +
diff --git a/numass-control/cryotemp/src/main/resources/fxml/PKT8MainView.fxml b/numass-control/cryotemp/src/main/resources/fxml/PKT8Plot.fxml similarity index 64% rename from numass-control/cryotemp/src/main/resources/fxml/PKT8MainView.fxml rename to numass-control/cryotemp/src/main/resources/fxml/PKT8Plot.fxml index 5ab0f2ce..d0661f2b 100644 --- a/numass-control/cryotemp/src/main/resources/fxml/PKT8MainView.fxml +++ b/numass-control/cryotemp/src/main/resources/fxml/PKT8Plot.fxml @@ -16,23 +16,22 @@ See the License for the specific language governing permissions and limitations under the License. --> - + + + - +
- - + - diff --git a/numass-storage/numass-server/src/main/groovy/inr/numass/scripts/TestServer.groovy b/numass-storage/numass-server/src/main/groovy/inr/numass/scripts/TestServer.groovy index 667a7e63..aca62a18 100644 --- a/numass-storage/numass-server/src/main/groovy/inr/numass/scripts/TestServer.groovy +++ b/numass-storage/numass-server/src/main/groovy/inr/numass/scripts/TestServer.groovy @@ -20,7 +20,7 @@ import inr.numass.server.NumassServer import inr.numass.storage.NumassStorage import org.apache.commons.vfs2.FileObject -String path = "D:\\temp\\test\\numass-server\\" +String path = "D:\\temp\\test\\numass\\" FileObject file = VFSUtils.getLocalFile(new File(path)) diff --git a/numass-storage/numass-server/src/main/java/inr/numass/server/NumassStorageHandler.java b/numass-storage/numass-server/src/main/java/inr/numass/server/NumassStorageHandler.java index 49a986b9..55abae23 100644 --- a/numass-storage/numass-server/src/main/java/inr/numass/server/NumassStorageHandler.java +++ b/numass-storage/numass-server/src/main/java/inr/numass/server/NumassStorageHandler.java @@ -51,7 +51,7 @@ public class NumassStorageHandler extends StorageRatpackHandler { List notes = getNotes(noteLoader).limit(100).map(note -> render(note)).collect(Collectors.toList()); - Map data = new HashMap(2); + Map data = new HashMap<>(2); data.put("notes", notes); StringWriter writer = new StringWriter();