[no commit message]

This commit is contained in:
Alexander Nozik 2016-04-14 20:45:11 +03:00
parent 0c0d9f2aa4
commit 9a9a0beca4
10 changed files with 1359 additions and 249 deletions

View File

@ -1,6 +1,6 @@
apply plugin: 'application' apply plugin: 'application'
version = "0.2.4" version = "0.3.0"
if (!hasProperty('mainClass')) { if (!hasProperty('mainClass')) {
ext.mainClass = 'inr.numass.control.msp.fx.MspApp' ext.mainClass = 'inr.numass.control.msp.fx.MspApp'
@ -9,9 +9,7 @@ mainClassName = mainClass
dependencies { dependencies {
compile 'ch.qos.logback:logback-classic:1.1.0+' compile project(':numass-storage:numass-client')
compile 'org.scream3r:jssc:2.8.0'
compile project(':dataforge-plots') compile project(':dataforge-plots')
compile project(':dataforge-storage')
compile project(':dataforge-control') compile project(':dataforge-control')
} }

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog" prefer="system">
<system systemId="http://javafx.com/javafx/8.0.65" uri="www.oracle.com/technetwork/java/javase/overview/index.html"/>
</catalog>

File diff suppressed because one or more lines are too long

View File

@ -23,8 +23,6 @@ import hep.dataforge.control.measurements.AbstractMeasurement;
import hep.dataforge.control.measurements.Measurement; import hep.dataforge.control.measurements.Measurement;
import hep.dataforge.control.ports.PortHandler; import hep.dataforge.control.ports.PortHandler;
import hep.dataforge.control.ports.TcpPortHandler; import hep.dataforge.control.ports.TcpPortHandler;
import hep.dataforge.points.Format;
import hep.dataforge.points.FormatBuilder;
import hep.dataforge.points.DataPoint; import hep.dataforge.points.DataPoint;
import hep.dataforge.points.MapPoint; import hep.dataforge.points.MapPoint;
import hep.dataforge.exceptions.ControlException; import hep.dataforge.exceptions.ControlException;
@ -32,12 +30,15 @@ import hep.dataforge.exceptions.MeasurementException;
import hep.dataforge.exceptions.PortException; import hep.dataforge.exceptions.PortException;
import hep.dataforge.exceptions.StorageException; import hep.dataforge.exceptions.StorageException;
import hep.dataforge.meta.Meta; import hep.dataforge.meta.Meta;
import hep.dataforge.points.Format;
import hep.dataforge.points.FormatBuilder;
import hep.dataforge.storage.api.PointLoader; import hep.dataforge.storage.api.PointLoader;
import hep.dataforge.storage.api.Storage; import hep.dataforge.storage.api.Storage;
import hep.dataforge.storage.commons.LoaderFactory; import hep.dataforge.storage.commons.LoaderFactory;
import hep.dataforge.values.Value; import hep.dataforge.values.Value;
import java.time.Instant; import java.time.Instant;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -49,7 +50,7 @@ import java.util.function.Consumer;
* *
* @author Alexander Nozik * @author Alexander Nozik
*/ */
@RoleDef(name = Roles.STORAGE_ROLE) @RoleDef(name = Roles.STORAGE_ROLE, objectType = StorageConnection.class)
public class MspDevice extends SingleMeasurementDevice implements PortHandler.PortController { public class MspDevice extends SingleMeasurementDevice implements PortHandler.PortController {
// private static final String PEAK_SET_PATH = "peakJump.peak"; // private static final String PEAK_SET_PATH = "peakJump.peak";
@ -63,6 +64,10 @@ public class MspDevice extends SingleMeasurementDevice implements PortHandler.Po
private Consumer<MspResponse> responseDelegate; private Consumer<MspResponse> responseDelegate;
private Consumer<Throwable> errorDelegate; private Consumer<Throwable> errorDelegate;
boolean connected = false;
boolean selected = false;
boolean controlled = false;
// public MspDevice(String name, Context context, Meta config) { // public MspDevice(String name, Context context, Meta config) {
// super(name, context, config); // super(name, context, config);
// } // }
@ -159,7 +164,8 @@ public class MspDevice extends SingleMeasurementDevice implements PortHandler.Po
response = sendAndWait("Select", sensorName); response = sendAndWait("Select", sensorName);
if (response.isOK()) { if (response.isOK()) {
updateState("selected", true); selected = true;
// updateState("selected", true);
} else { } else {
error(response.errorDescription(), null); error(response.errorDescription(), null);
return false; return false;
@ -167,12 +173,15 @@ public class MspDevice extends SingleMeasurementDevice implements PortHandler.Po
response = sendAndWait("Control", "inr.numass.msp", "1.0"); response = sendAndWait("Control", "inr.numass.msp", "1.0");
if (response.isOK()) { if (response.isOK()) {
updateState("controlled", true); controlled = true;
// invalidateState("controlled");
// updateState("controlled", true);
} else { } else {
error(response.errorDescription(), null); error(response.errorDescription(), null);
return false; return false;
} }
updateState("connected", true); connected = true;
// updateState("connected", true);
return true; return true;
} else { } else {
return !sendAndWait("Release").isOK(); return !sendAndWait("Release").isOK();
@ -243,21 +252,28 @@ public class MspDevice extends SingleMeasurementDevice implements PortHandler.Po
} }
public boolean isConnected() { public boolean isConnected() {
return getState("connected") != null && getState("connected").booleanValue(); return connected;
//return getState("connected") != null && getState("connected").booleanValue();
} }
public boolean isSelected() { public boolean isSelected() {
return getState("selected") != null && getState("selected").booleanValue(); return selected;
//return getState("selected") != null && getState("selected").booleanValue();
} }
public boolean isControlled() { public boolean isControlled() {
return getState("controlled") != null && getState("controlled").booleanValue(); return controlled;
//return getState("controlled") != null && getState("controlled").booleanValue();
} }
public boolean isFilamentOn() { public boolean isFilamentOn() {
return getState("filamentOn").booleanValue(); return getState("filamentOn").booleanValue();
} }
public void selectFillament(int fillament) throws PortException {
sendAndWait("FilamentSelect", fillament);
}
/** /**
* Turn filament on or off * Turn filament on or off
* *
@ -372,41 +388,39 @@ public class MspDevice extends SingleMeasurementDevice implements PortHandler.Po
private final Map<Integer, Double> measurement = new ConcurrentSkipListMap<>(); private final Map<Integer, Double> measurement = new ConcurrentSkipListMap<>();
private Map<Integer, String> peakMap; private Map<Integer, String> peakMap;
private List<PointLoader> loaders = new ArrayList<>(); private final Map<StorageConnection, PointLoader> loaderMap = new HashMap<>();
// private List<PointLoader> loaders = new ArrayList<>();
private final Meta meta; private final Meta meta;
private double zero = 0;
public PeakJumpMeasurement(Meta meta) { public PeakJumpMeasurement(Meta meta) {
this.meta = meta; this.meta = meta;
} }
private void prepareLoaders() { private PointLoader makeLoader(StorageConnection connection) {
loaders = new ArrayList<>();
forEachTypedConnection(Roles.STORAGE_ROLE, StorageConnection.class, (StorageConnection con) -> {
try { try {
Storage storage = con.getStorage(); Storage storage = connection.getStorage();
if (peakMap == null) { if (peakMap == null) {
throw new IllegalStateException("Peak map is not initialized"); throw new IllegalStateException("Peak map is not initialized");
} }
FormatBuilder builder = new FormatBuilder().addTime("timestamp"); FormatBuilder builder = new FormatBuilder().addTime("timestamp");
for (String peakName : this.peakMap.values()) { this.peakMap.values().stream().forEach((peakName) -> {
builder.addNumber(peakName); builder.addNumber(peakName);
} });
Format format = builder.build(); Format format = builder.build();
//TODO Переделать!!!
String run = meta().getString("storage.run", "");
String suffix = Integer.toString((int) Instant.now().toEpochMilli()); String suffix = Integer.toString((int) Instant.now().toEpochMilli());
PointLoader loader = LoaderFactory PointLoader loader = LoaderFactory
.buildPointLoder(storage, "msp" + suffix, run, "timestamp", format); .buildPointLoder(storage, "msp" + suffix, "", "timestamp", format);
loaders.add(loader); return loader;
} catch (StorageException ex) { } catch (StorageException ex) {
getLogger().error("Failed to initialize peak jump loader", ex); getLogger().error("Failed to create Loader", ex);
return null;
} }
});
} }
@Override @Override
@ -427,7 +441,6 @@ public class MspDevice extends SingleMeasurementDevice implements PortHandler.Po
throw new ControlException("Can't add mass to measurement measurement for msp"); throw new ControlException("Can't add mass to measurement measurement for msp");
} }
} }
prepareLoaders();
} else { } else {
throw new ControlException("Can't create measurement for msp"); throw new ControlException("Can't create measurement for msp");
} }
@ -454,6 +467,13 @@ public class MspDevice extends SingleMeasurementDevice implements PortHandler.Po
boolean stop = sendAndWait("ScanStop").isOK(); boolean stop = sendAndWait("ScanStop").isOK();
afterStop(); afterStop();
responseDelegate = null; responseDelegate = null;
loaderMap.values().forEach(loader -> {
try {
loader.close();
} catch (Exception ex) {
getLogger().error("Failed to close Loader", ex);
}
});
return stop; return stop;
} catch (PortException ex) { } catch (PortException ex) {
throw new MeasurementException(ex); throw new MeasurementException(ex);
@ -468,9 +488,11 @@ public class MspDevice extends SingleMeasurementDevice implements PortHandler.Po
switch (response.getCommandName()) { switch (response.getCommandName()) {
case "MassReading": case "MassReading":
double mass = Double.parseDouble(response.get(0, 1)); double mass = Double.parseDouble(response.get(0, 1));
double value = Double.parseDouble(response.get(0, 2)); double value = Double.parseDouble(response.get(0, 2)) / 100d;
measurement.put((int) Math.floor(mass + 0.5), value); measurement.put((int) Math.floor(mass + 0.5), value);
break; break;
case "ZeroReading":
zero = Double.parseDouble(response.get(0, 2)) / 100d;
case "StartingScan": case "StartingScan":
if (mspListener != null && !measurement.isEmpty()) { if (mspListener != null && !measurement.isEmpty()) {
if (peakMap == null) { if (peakMap == null) {
@ -490,13 +512,14 @@ public class MspDevice extends SingleMeasurementDevice implements PortHandler.Po
if (isFilamentOn()) { if (isFilamentOn()) {
mspListener.acceptScan(measurement); mspListener.acceptScan(measurement);
for (PointLoader loader : this.loaders) { forEachTypedConnection(Roles.STORAGE_ROLE, StorageConnection.class, (StorageConnection connection) -> {
PointLoader pl = loaderMap.computeIfAbsent(connection, con -> makeLoader(con));
try { try {
loader.push(point); pl.push(point);
} catch (StorageException ex) { } catch (StorageException ex) {
getLogger().error("Push to repo failed", ex); getLogger().error("Push to loader failed", ex);
}
} }
});
} }
measurement.clear(); measurement.clear();
@ -505,7 +528,7 @@ public class MspDevice extends SingleMeasurementDevice implements PortHandler.Po
if (numScans == 0) { if (numScans == 0) {
try { try {
send("ScanResume", 2); send("ScanResume", 10);
//FIXME обработать ошибку связи //FIXME обработать ошибку связи
} catch (PortException ex) { } catch (PortException ex) {
error(null, ex); error(null, ex);

View File

@ -17,9 +17,11 @@ package inr.numass.control.msp.fx;
import ch.qos.logback.classic.Level; import ch.qos.logback.classic.Level;
import hep.dataforge.context.GlobalContext; import hep.dataforge.context.GlobalContext;
import hep.dataforge.io.MetaFileReader;
import hep.dataforge.io.XMLMetaReader;
import hep.dataforge.meta.Meta;
import hep.dataforge.storage.commons.StorageManager; import hep.dataforge.storage.commons.StorageManager;
import java.io.File; import java.io.File;
import java.io.IOException;
import java.util.Locale; import java.util.Locale;
import javafx.application.Application; import javafx.application.Application;
import javafx.fxml.FXMLLoader; import javafx.fxml.FXMLLoader;
@ -37,26 +39,31 @@ public class MspApp extends Application {
MspViewController controller; MspViewController controller;
@Override @Override
public void start(Stage primaryStage) throws IOException { public void start(Stage primaryStage) throws Exception {
Locale.setDefault(Locale.US);// чтобы отделение десятичных знаков было точкой 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); 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); rootLogger.setLevel(Level.INFO);
new StorageManager().startGlobal(); new StorageManager().startGlobal();
String configFileName = getParameters().getNamed().get("config");
if (configFileName == null) {
configFileName = "msp-config.xml";
}
File configFile = new File(configFileName);
Meta config;
if (configFile.exists()) {
config = MetaFileReader.read(configFile).build();
} else {
// throw new RuntimeException("Configuration file not found");
config = new XMLMetaReader().read(MspApp.class.getClassLoader().getResourceAsStream("config/msp-config.xml"), -1, null);
}
FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/MspView.fxml")); FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/MspView.fxml"));
Parent parent = loader.load(); Parent parent = loader.load();
controller = loader.getController(); controller = loader.getController();
try { controller.setDeviceConfig(GlobalContext.instance(), config);
String configPath = getParameters().getNamed().get("config");
if (configPath != null) {
File configFile = new File(configPath);
controller.setDeviceConfig(GlobalContext.instance(), configFile);
}
} catch (Exception ex) {
LoggerFactory.getLogger(getClass()).error("Failed to load predefined configuration", ex);
}
Scene scene = new Scene(parent, 600, 400); Scene scene = new Scene(parent, 600, 400);
@ -72,9 +79,9 @@ public class MspApp extends Application {
@Override @Override
public void stop() throws Exception { public void stop() throws Exception {
super.stop(); //To change body of generated methods, choose Tools | Templates. super.stop();
controller.disconnect(); controller.shutdown();
System.exit(0); // System.exit(0);
} }
/** /**

View File

@ -22,6 +22,8 @@ import hep.dataforge.control.connections.StorageConnection;
import hep.dataforge.points.MapPoint; import hep.dataforge.points.MapPoint;
import hep.dataforge.exceptions.ControlException; import hep.dataforge.exceptions.ControlException;
import hep.dataforge.exceptions.PortException; import hep.dataforge.exceptions.PortException;
import hep.dataforge.exceptions.StorageException;
import hep.dataforge.fx.ConsoleWindow;
import hep.dataforge.io.MetaFileReader; import hep.dataforge.io.MetaFileReader;
import hep.dataforge.meta.ConfigChangeListener; import hep.dataforge.meta.ConfigChangeListener;
import hep.dataforge.meta.Configuration; import hep.dataforge.meta.Configuration;
@ -29,9 +31,10 @@ import hep.dataforge.meta.Meta;
import hep.dataforge.meta.MetaBuilder; import hep.dataforge.meta.MetaBuilder;
import hep.dataforge.plots.data.DynamicPlottable; import hep.dataforge.plots.data.DynamicPlottable;
import hep.dataforge.plots.data.DynamicPlottableSet; import hep.dataforge.plots.data.DynamicPlottableSet;
import hep.dataforge.plots.fx.PlotContainer;
import hep.dataforge.plots.jfreechart.JFreeChartFrame; import hep.dataforge.plots.jfreechart.JFreeChartFrame;
import hep.dataforge.storage.api.Storage;
import hep.dataforge.storage.commons.StorageManager; import hep.dataforge.storage.commons.StorageManager;
import hep.dataforge.storage.filestorage.FileStorage;
import hep.dataforge.values.Value; import hep.dataforge.values.Value;
import inr.numass.control.msp.MspDevice; import inr.numass.control.msp.MspDevice;
import inr.numass.control.msp.MspListener; import inr.numass.control.msp.MspListener;
@ -44,11 +47,12 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.ResourceBundle; import java.util.ResourceBundle;
import javafx.application.Platform; import javafx.application.Platform;
import javafx.collections.FXCollections;
import javafx.event.ActionEvent; import javafx.event.ActionEvent;
import javafx.fxml.FXML; import javafx.fxml.FXML;
import javafx.fxml.Initializable; import javafx.fxml.Initializable;
import javafx.scene.control.Alert; import javafx.scene.control.Alert;
import javafx.scene.control.Button; import javafx.scene.control.ComboBox;
import javafx.scene.control.Slider; import javafx.scene.control.Slider;
import javafx.scene.control.TextArea; import javafx.scene.control.TextArea;
import javafx.scene.control.ToggleButton; import javafx.scene.control.ToggleButton;
@ -56,8 +60,12 @@ import javafx.scene.input.DragEvent;
import javafx.scene.layout.AnchorPane; import javafx.scene.layout.AnchorPane;
import javafx.scene.paint.Paint; import javafx.scene.paint.Paint;
import javafx.scene.shape.Circle; import javafx.scene.shape.Circle;
import javafx.stage.FileChooser; import javafx.stage.DirectoryChooser;
import javafx.util.StringConverter;
import org.controlsfx.control.ToggleSwitch;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import inr.numass.client.NumassClient;
import javafx.beans.value.ObservableValue;
/** /**
* FXML Controller class * FXML Controller class
@ -74,26 +82,13 @@ public class MspViewController implements Initializable, MspListener {
private Configuration viewConfig; private Configuration viewConfig;
private JFreeChartFrame plotFrame; private JFreeChartFrame plot;
private final DynamicPlottableSet plottables = new DynamicPlottableSet(); private final DynamicPlottableSet plottables = new DynamicPlottableSet();
private final String mspName = "msp"; private final String mspName = "msp";
@FXML
private Slider autoRangeSlider;
@FXML
private ToggleButton fillamentButton;
@FXML
private Circle fillamentIndicator;
@FXML
private TextArea logArea; private TextArea logArea;
@FXML
private ToggleButton plotButton;
@FXML
private AnchorPane plotPane;
@FXML
private Button loadConfigButton;
private final ConfigChangeListener viewConfigObserver = new ConfigChangeListener() { private final ConfigChangeListener viewConfigObserver = new ConfigChangeListener() {
@ -109,7 +104,57 @@ public class MspViewController implements Initializable, MspListener {
}; };
public MspViewController() { private StorageConnection connection;
@FXML
private Slider autoRangeSlider;
@FXML
private ToggleSwitch fillamentButton;
@FXML
private Circle fillamentIndicator;
@FXML
private ToggleButton plotButton;
@FXML
private AnchorPane plotPane;
@FXML
private ToggleButton consoleButton;
@FXML
private ComboBox<Integer> fillamentSelector;
@FXML
private ToggleButton storeButton;
/**
* Initializes the controller class.
*
* @param url
* @param rb
*/
@Override
public void initialize(URL url, ResourceBundle rb) {
ConsoleWindow cw = new ConsoleWindow(consoleButton);
this.logArea = cw.getTextArea();
fillamentSelector.setItems(FXCollections.observableArrayList(1, 2));
fillamentSelector.setConverter(new StringConverter<Integer>() {
@Override
public String toString(Integer object) {
return "Fillament " + object;
}
@Override
public Integer fromString(String string) {
return Integer.parseInt(string.substring(9));
}
});
fillamentSelector.getSelectionModel().select(0);
fillamentButton.selectedProperty().addListener((ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) -> {
try {
fillamentSelector.setDisable(newValue);
getDevice().setFileamentOn(newValue);
} catch (PortException ex) {
device.getLogger().error("Failed to toggle fillaments");
}
});
} }
public Configuration getViewConfig() { public Configuration getViewConfig() {
@ -159,9 +204,7 @@ public class MspViewController implements Initializable, MspListener {
device.setName(mspName); device.setName(mspName);
device.setContext(context); device.setContext(context);
device.setMeta(mspConfig); device.setMeta(mspConfig);
if (mspConfig.hasNode("storage")) {
device.connect(new StorageConnection(StorageManager.buildFrom(context).buildStorage(mspConfig.getNode("storage"))), Roles.STORAGE_ROLE);
}
try { try {
getDevice().setListener(this); getDevice().setListener(this);
getDevice().init(); getDevice().init();
@ -201,19 +244,22 @@ public class MspViewController implements Initializable, MspListener {
.setValue("axisUnits", "mbar") .setValue("axisUnits", "mbar")
) )
.setValue("xAxis.type", "time"); .setValue("xAxis.type", "time");
this.plotFrame = new JFreeChartFrame(mspName, plotConfig).display(plotPane);
this.plot = new JFreeChartFrame(mspName, plotConfig);
PlotContainer container = PlotContainer.anchorTo(plotPane);
container.setPlot(plot);
updatePlot(); updatePlot();
// this.plot = DynamicPlot.attachToFX(plotPane, new AnnotationBuilder("plot-config").putValue("logY", true).build()); // this.plot = DynamicPlot.attachToFX(plotPane, new AnnotationBuilder("plot-config").putValue("logY", true).build());
// plot.setAutoRange(30 * 60); // plot.setAutoRange(30 * 60);
} }
public void updatePlot() { public void updatePlot() {
if (plotFrame == null) { if (plot == null) {
initPlot(); initPlot();
} }
Meta config = getViewConfig(); Meta config = getViewConfig();
if (config.hasNode("plotFrame")) { if (config.hasNode("plotFrame")) {
this.plotFrame.configure(config.getNode("plotFrame")); this.plot.configure(config.getNode("plotFrame"));
} }
if (config.hasNode("peakJump.line")) { if (config.hasNode("peakJump.line")) {
for (Meta an : config.getNodes("peakJump.line")) { for (Meta an : config.getNodes("peakJump.line")) {
@ -223,7 +269,7 @@ public class MspViewController implements Initializable, MspListener {
DynamicPlottable newPlottable = new DynamicPlottable(mass, mass); DynamicPlottable newPlottable = new DynamicPlottable(mass, mass);
newPlottable.configure(an); newPlottable.configure(an);
this.plottables.addPlottable(newPlottable); this.plottables.addPlottable(newPlottable);
plotFrame.add(newPlottable); plot.add(newPlottable);
} else { } else {
plottables.getPlottable(mass).configure(an); plottables.getPlottable(mass).configure(an);
} }
@ -270,40 +316,11 @@ public class MspViewController implements Initializable, MspListener {
} }
/**
* Initializes the controller class.
*
* @param url
* @param rb
*/
@Override
public void initialize(URL url, ResourceBundle rb) {
}
@FXML @FXML
private void onAutoRangeChange(DragEvent event) { private void onAutoRangeChange(DragEvent event) {
plottables.setMaxAge((int) (this.autoRangeSlider.getValue() * 60 * 1000)); plottables.setMaxAge((int) (this.autoRangeSlider.getValue() * 60 * 1000));
} }
@FXML
private void onFillamentToggle(ActionEvent event) throws PortException {
getDevice().setFileamentOn(fillamentButton.isSelected());
}
@FXML
private void onLoadConfig(ActionEvent event) {
FileChooser fileChooser = new FileChooser();
fileChooser.setTitle("Open Resource 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("all", "*.*"));
File cfgFile = fileChooser.showOpenDialog(loadConfigButton.getScene().getWindow());
if (cfgFile != null) {
setDeviceConfig(GlobalContext.instance(), cfgFile);
}
}
@FXML @FXML
private void onPlotToggle(ActionEvent event) throws ControlException { private void onPlotToggle(ActionEvent event) throws ControlException {
if (plotButton.isSelected()) { if (plotButton.isSelected()) {
@ -326,7 +343,7 @@ public class MspViewController implements Initializable, MspListener {
} }
public void disconnect() throws IOException, PortException, ControlException { public void shutdown() throws IOException, PortException, ControlException {
getDevice().shutdown(); getDevice().shutdown();
} }
@ -349,4 +366,52 @@ public class MspViewController implements Initializable, MspListener {
}); });
} }
@FXML
private void onStoreButtonClick(ActionEvent event) {
if (storeButton.isSelected()) {
if (!device.meta().hasNode("storage")) {
device.getLogger().info("Storage not defined. Starting storage selection dialog");
DirectoryChooser chooser = new DirectoryChooser();
File storageDir = chooser.showDialog(this.plotPane.getScene().getWindow());
if (storageDir == null) {
storeButton.setSelected(false);
throw new RuntimeException("User canceled directory selection");
}
device.getConfig().putNode(new MetaBuilder("storage")
.putValue("path", storageDir.getAbsolutePath()));
}
Meta storageConfig = device.meta().getNode("storage");
Storage localStorage = StorageManager.buildFrom(device.getContext())
.buildStorage(storageConfig);
String runName = device.meta().getString("numass.run", "");
Meta meta = device.meta();
if (meta.hasNode("numass")) {
try {
device.getLogger().info("Obtaining run information from cetral server...");
NumassClient client = new NumassClient(meta.getString("numass.ip", "192.168.111.1"),
meta.getInt("numass.port", 8335));
runName = client.getCurrentRun().getString("path", "");
device.getLogger().info("Run name is '{}'", runName);
} catch (Exception ex) {
device.getLogger().warn("Failed to download current run information", ex);
}
}
if (!runName.isEmpty()) {
try {
localStorage = localStorage.buildShelf(runName, null);
} catch (StorageException ex) {
device.getLogger().error("Failed to create storage shelf. Using root storage instead");
}
}
connection = new StorageConnection(localStorage);
device.connect(connection, Roles.STORAGE_ROLE);
} else if (connection != null) {
device.disconnect(connection);
}
}
} }

View File

@ -1,4 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!-- <!--
Copyright 2015 Alexander Nozik. Copyright 2015 Alexander Nozik.
@ -15,44 +16,41 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
--> -->
<?import javafx.scene.effect.*?> <?import javafx.geometry.Insets?>
<?import javafx.scene.paint.*?> <?import javafx.scene.control.ComboBox?>
<?import javafx.scene.shape.*?> <?import javafx.scene.control.Label?>
<?import javafx.scene.chart.*?> <?import javafx.scene.control.Separator?>
<?import java.lang.*?> <?import javafx.scene.control.Slider?>
<?import java.util.*?> <?import javafx.scene.control.ToggleButton?>
<?import javafx.scene.*?> <?import javafx.scene.control.ToolBar?>
<?import javafx.scene.control.*?> <?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.*?> <?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.Pane?>
<?import javafx.scene.shape.Circle?>
<?import org.controlsfx.control.ToggleSwitch?>
<AnchorPane id="AnchorPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="400.0" minWidth="600.0" prefHeight="480.0" prefWidth="640.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="inr.numass.control.msp.fx.MspViewController"> <AnchorPane id="AnchorPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="400.0" minWidth="600.0" prefHeight="480.0" prefWidth="640.0" xmlns="http://javafx.com/javafx/8.0.65" xmlns:fx="http://javafx.com/fxml/1" fx:controller="inr.numass.control.msp.fx.MspViewController">
<children> <children>
<SplitPane dividerPositions="0.8" minHeight="400.0" minWidth="600.0" orientation="VERTICAL" prefHeight="200.0" prefWidth="160.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0"> <ToolBar prefHeight="50.0" prefWidth="200.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<items> <items>
<AnchorPane minHeight="300.0" minWidth="300.0" prefHeight="100.0" prefWidth="160.0"> <ComboBox fx:id="fillamentSelector" promptText="Fillament 1" visibleRowCount="2" />
<children> <ToggleSwitch fx:id="fillamentButton" prefHeight="40.0" prefWidth="35.0">
<ToolBar layoutX="130.0" prefHeight="50.0" prefWidth="200.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0"> <padding>
<items> <Insets top="11.0" />
<ToggleButton fx:id="fillamentButton" mnemonicParsing="false" onAction="#onFillamentToggle" text="Fillament" /> </padding>
</ToggleSwitch>
<Circle fx:id="fillamentIndicator" fill="GRAY" radius="10.0" stroke="BLACK" strokeType="INSIDE" /> <Circle fx:id="fillamentIndicator" fill="GRAY" radius="10.0" stroke="BLACK" strokeType="INSIDE" />
<Separator orientation="VERTICAL" prefHeight="20.0" /> <Separator orientation="VERTICAL" prefHeight="20.0" />
<ToggleButton fx:id="plotButton" mnemonicParsing="false" onAction="#onPlotToggle" text="Aquire" /> <ToggleButton fx:id="plotButton" mnemonicParsing="false" onAction="#onPlotToggle" text="Measure" />
<Button fx:id="loadConfigButton" mnemonicParsing="false" onAction="#onLoadConfig" text="Load config" /> <ToggleButton fx:id="storeButton" mnemonicParsing="false" onAction="#onStoreButtonClick" text="Store" />
<Separator orientation="VERTICAL" prefHeight="20.0" /> <Separator orientation="VERTICAL" prefHeight="20.0" />
<Label text="Autorange (min):" /> <Label text="Autorange (min):" />
<Slider fx:id="autoRangeSlider" max="210.0" min="10.0" onDragDone="#onAutoRangeChange" showTickLabels="true" showTickMarks="true" snapToTicks="true" value="30.0" /> <Slider fx:id="autoRangeSlider" max="210.0" min="10.0" onDragDone="#onAutoRangeChange" showTickLabels="true" showTickMarks="true" snapToTicks="true" value="30.0" />
<Separator orientation="VERTICAL" prefHeight="20.0" /> <Separator orientation="VERTICAL" prefHeight="20.0" />
<Pane HBox.hgrow="ALWAYS" />
<ToggleButton fx:id="consoleButton" mnemonicParsing="false" text="Console" />
</items> </items>
</ToolBar> </ToolBar>
<AnchorPane fx:id="plotPane" layoutX="144.0" layoutY="82.0" minHeight="400.0" minWidth="600.0" prefHeight="200.0" prefWidth="200.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="50.0" /> <AnchorPane fx:id="plotPane" minHeight="400.0" minWidth="600.0" prefHeight="200.0" prefWidth="200.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="50.0" />
</children>
</AnchorPane>
<AnchorPane maxHeight="200.0" minHeight="0.0" minWidth="0.0" prefHeight="100.0" prefWidth="160.0">
<children>
<TextArea fx:id="logArea" editable="false" maxHeight="200.0" minHeight="0.0" prefHeight="200.0" prefWidth="200.0" wrapText="true" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
</children>
</AnchorPane>
</items>
</SplitPane>
</children> </children>
</AnchorPane> </AnchorPane>

View File

@ -81,7 +81,7 @@ public class ReadVac extends Application {
controller.setLoaderFactory((VacCollectorDevice device, Storage localStorage) -> { controller.setLoaderFactory((VacCollectorDevice device, Storage localStorage) -> {
try { try {
String runName = device.meta().getString("storage.run", ""); String runName = device.meta().getString("numass.run", "");
if (config.hasNode("numass")) { if (config.hasNode("numass")) {
try { try {
logger.info("Obtaining run information from cetral server..."); logger.info("Obtaining run information from cetral server...");

View File

@ -5,8 +5,7 @@
*/ */
package inr.numass.readvac.fx; package inr.numass.readvac.fx;
import de.jensd.shichimifx.utils.ConsoleDude; import hep.dataforge.control.connections.LoaderConnection;
import hep.dataforge.control.connections.Connection;
import hep.dataforge.control.connections.Roles; import hep.dataforge.control.connections.Roles;
import hep.dataforge.control.devices.Device; import hep.dataforge.control.devices.Device;
import hep.dataforge.control.devices.DeviceListener; import hep.dataforge.control.devices.DeviceListener;
@ -16,7 +15,7 @@ import hep.dataforge.control.measurements.Sensor;
import hep.dataforge.points.DataPoint; import hep.dataforge.points.DataPoint;
import hep.dataforge.exceptions.ControlException; import hep.dataforge.exceptions.ControlException;
import hep.dataforge.exceptions.MeasurementException; import hep.dataforge.exceptions.MeasurementException;
import hep.dataforge.exceptions.StorageException; import hep.dataforge.fx.ConsoleWindow;
import hep.dataforge.meta.Meta; import hep.dataforge.meta.Meta;
import hep.dataforge.meta.MetaBuilder; import hep.dataforge.meta.MetaBuilder;
import hep.dataforge.plots.PlotFrame; import hep.dataforge.plots.PlotFrame;
@ -25,7 +24,6 @@ import hep.dataforge.plots.data.DynamicPlottableSet;
import hep.dataforge.plots.fx.PlotContainer; import hep.dataforge.plots.fx.PlotContainer;
import hep.dataforge.plots.jfreechart.JFreeChartFrame; import hep.dataforge.plots.jfreechart.JFreeChartFrame;
import hep.dataforge.points.FormatBuilder; import hep.dataforge.points.FormatBuilder;
import hep.dataforge.points.PointListener;
import hep.dataforge.storage.api.PointLoader; import hep.dataforge.storage.api.PointLoader;
import hep.dataforge.storage.api.Storage; import hep.dataforge.storage.api.Storage;
import hep.dataforge.storage.commons.LoaderFactory; import hep.dataforge.storage.commons.LoaderFactory;
@ -49,16 +47,12 @@ import javafx.collections.FXCollections;
import javafx.event.ActionEvent; import javafx.event.ActionEvent;
import javafx.fxml.FXML; import javafx.fxml.FXML;
import javafx.fxml.Initializable; import javafx.fxml.Initializable;
import javafx.scene.Scene;
import javafx.scene.control.ChoiceBox; import javafx.scene.control.ChoiceBox;
import javafx.scene.control.Label; import javafx.scene.control.Label;
import javafx.scene.control.TextArea;
import javafx.scene.control.ToggleButton; import javafx.scene.control.ToggleButton;
import javafx.scene.layout.AnchorPane; import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.VBox; import javafx.scene.layout.VBox;
import javafx.stage.DirectoryChooser; import javafx.stage.DirectoryChooser;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;
import javafx.util.Duration; import javafx.util.Duration;
import org.controlsfx.control.Notifications; import org.controlsfx.control.Notifications;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -86,8 +80,7 @@ public class VacCollectorController implements Initializable, DeviceListener, Me
private DynamicPlottableSet plottables; private DynamicPlottableSet plottables;
private BiFunction<VacCollectorDevice, Storage, PointLoader> loaderFactory; private BiFunction<VacCollectorDevice, Storage, PointLoader> loaderFactory;
private TextArea consolePane; ConsoleWindow consoleWindow;
private Stage consoleWindow;
@FXML @FXML
private AnchorPane plotHolder; private AnchorPane plotHolder;
@ -122,20 +115,8 @@ public class VacCollectorController implements Initializable, DeviceListener, Me
} }
}); });
consolePane = new TextArea(); consoleWindow = new ConsoleWindow(logButton);
consolePane.setEditable(false); consoleWindow.hookStd();
consolePane.setWrapText(true);
// consolePane.textProperty().addListener((ObservableValue<? extends String> observable, String oldValue, String newValue) -> {
// if (newValue.length() > 10000) {
// consolePane.clear();
// }
// });
consoleWindow = new Stage();
consoleWindow.setTitle("Vacuum measurement console");
consoleWindow.setScene(new Scene(consolePane, 800, 200));
consoleWindow.setOnHidden((WindowEvent event) -> {
logButton.setSelected(false);
});
} }
@Override @Override
@ -297,17 +278,6 @@ public class VacCollectorController implements Initializable, DeviceListener, Me
} }
} }
@FXML
private void onLogToggle(ActionEvent event) {
if (logButton.isSelected() && logButton.isSelected() != consoleWindow.isShowing()) {
consoleWindow.show();
ConsoleDude.hookStdStreams(consolePane);
} else {
consoleWindow.hide();
ConsoleDude.restoreStdStreams();
}
}
/** /**
* @return the logger * @return the logger
*/ */
@ -324,39 +294,4 @@ public class VacCollectorController implements Initializable, DeviceListener, Me
public void setLogger(Logger logger) { public void setLogger(Logger logger) {
this.logger = logger; this.logger = logger;
} }
private class LoaderConnection implements PointListener, Connection<Device> {
private final PointLoader loader;
public LoaderConnection(PointLoader loader) {
this.loader = loader;
}
@Override
public void accept(DataPoint point) {
try {
loader.push(point);
} catch (StorageException ex) {
getLogger().error("Error while pushing data", ex);
}
}
@Override
public boolean isOpen() {
return loader.isOpen();
}
@Override
public void open(Device object) throws Exception {
loader.open();
}
@Override
public void close() throws Exception {
loader.close();
}
}
} }

View File

@ -1,11 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import java.net.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.*?>
<?import java.net.URL?> <?import java.net.URL?>
<?import javafx.geometry.Insets?> <?import javafx.geometry.Insets?>
<?import javafx.scene.control.ChoiceBox?> <?import javafx.scene.control.ChoiceBox?>
@ -19,7 +13,7 @@
<?import javafx.scene.layout.VBox?> <?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Font?> <?import javafx.scene.text.Font?>
<AnchorPane id="root" prefHeight="600.0" prefWidth="800.0" xmlns="http://javafx.com/javafx/8.0.40" xmlns:fx="http://javafx.com/fxml/1" fx:controller="inr.numass.readvac.fx.VacCollectorController"> <AnchorPane id="root" prefHeight="600.0" prefWidth="800.0" xmlns="http://javafx.com/javafx/8.0.65" xmlns:fx="http://javafx.com/fxml/1" fx:controller="inr.numass.readvac.fx.VacCollectorController">
<stylesheets> <stylesheets>
<URL value="@/styles/vacstyles.css" /> <URL value="@/styles/vacstyles.css" />
</stylesheets> </stylesheets>
@ -38,7 +32,7 @@
<Separator orientation="VERTICAL" /> <Separator orientation="VERTICAL" />
<Pane HBox.hgrow="ALWAYS" /> <Pane HBox.hgrow="ALWAYS" />
<Separator orientation="VERTICAL" /> <Separator orientation="VERTICAL" />
<ToggleButton fx:id="logButton" mnemonicParsing="false" onAction="#onLogToggle" text="Console" /> <ToggleButton fx:id="logButton" mnemonicParsing="false" text="Console" />
</items> </items>
</ToolBar> </ToolBar>
<AnchorPane fx:id="plotHolder" VBox.vgrow="ALWAYS" /> <AnchorPane fx:id="plotHolder" VBox.vgrow="ALWAYS" />