[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 {
Storage storage = con.getStorage();
if (peakMap == null) { try {
throw new IllegalStateException("Peak map is not initialized"); Storage storage = connection.getStorage();
}
FormatBuilder builder = new FormatBuilder().addTime("timestamp"); if (peakMap == null) {
for (String peakName : this.peakMap.values()) { throw new IllegalStateException("Peak map is not initialized");
builder.addNumber(peakName);
}
Format format = builder.build();
//TODO Переделать!!!
String run = meta().getString("storage.run", "");
String suffix = Integer.toString((int) Instant.now().toEpochMilli());
PointLoader loader = LoaderFactory
.buildPointLoder(storage, "msp" + suffix, run, "timestamp", format);
loaders.add(loader);
} catch (StorageException ex) {
getLogger().error("Failed to initialize peak jump loader", ex);
} }
});
FormatBuilder builder = new FormatBuilder().addTime("timestamp");
this.peakMap.values().stream().forEach((peakName) -> {
builder.addNumber(peakName);
});
Format format = builder.build();
String suffix = Integer.toString((int) Instant.now().toEpochMilli());
PointLoader loader = LoaderFactory
.buildPointLoder(storage, "msp" + suffix, "", "timestamp", format);
return loader;
} catch (StorageException 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,58 +1,56 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!--
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.
-->
<?import javafx.scene.effect.*?> <!--
<?import javafx.scene.paint.*?> Copyright 2015 Alexander Nozik.
<?import javafx.scene.shape.*?>
<?import javafx.scene.chart.*?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<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"> Licensed under the Apache License, Version 2.0 (the "License");
<children> you may not use this file except in compliance with the License.
<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"> You may obtain a copy of the License at
<items>
<AnchorPane minHeight="300.0" minWidth="300.0" prefHeight="100.0" prefWidth="160.0"> http://www.apache.org/licenses/LICENSE-2.0
<children>
<ToolBar layoutX="130.0" prefHeight="50.0" prefWidth="200.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0"> Unless required by applicable law or agreed to in writing, software
<items> distributed under the License is distributed on an "AS IS" BASIS,
<ToggleButton fx:id="fillamentButton" mnemonicParsing="false" onAction="#onFillamentToggle" text="Fillament" /> WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
<Circle fx:id="fillamentIndicator" fill="GRAY" radius="10.0" stroke="BLACK" strokeType="INSIDE" /> See the License for the specific language governing permissions and
<Separator orientation="VERTICAL" prefHeight="20.0" /> limitations under the License.
<ToggleButton fx:id="plotButton" mnemonicParsing="false" onAction="#onPlotToggle" text="Aquire" /> -->
<Button fx:id="loadConfigButton" mnemonicParsing="false" onAction="#onLoadConfig" text="Load config" />
<Separator orientation="VERTICAL" prefHeight="20.0" /> <?import javafx.geometry.Insets?>
<Label text="Autorange (min):" /> <?import javafx.scene.control.ComboBox?>
<Slider fx:id="autoRangeSlider" max="210.0" min="10.0" onDragDone="#onAutoRangeChange" showTickLabels="true" showTickMarks="true" snapToTicks="true" value="30.0" /> <?import javafx.scene.control.Label?>
<Separator orientation="VERTICAL" prefHeight="20.0" /> <?import javafx.scene.control.Separator?>
</items> <?import javafx.scene.control.Slider?>
</ToolBar> <?import javafx.scene.control.ToggleButton?>
<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" /> <?import javafx.scene.control.ToolBar?>
</children> <?import javafx.scene.layout.AnchorPane?>
</AnchorPane> <?import javafx.scene.layout.HBox?>
<AnchorPane maxHeight="200.0" minHeight="0.0" minWidth="0.0" prefHeight="100.0" prefWidth="160.0"> <?import javafx.scene.layout.Pane?>
<children> <?import javafx.scene.shape.Circle?>
<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" /> <?import org.controlsfx.control.ToggleSwitch?>
</children>
</AnchorPane> <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">
</items> <children>
</SplitPane> <ToolBar prefHeight="50.0" prefWidth="200.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
</children> <items>
<ComboBox fx:id="fillamentSelector" promptText="Fillament 1" visibleRowCount="2" />
<ToggleSwitch fx:id="fillamentButton" prefHeight="40.0" prefWidth="35.0">
<padding>
<Insets top="11.0" />
</padding>
</ToggleSwitch>
<Circle fx:id="fillamentIndicator" fill="GRAY" radius="10.0" stroke="BLACK" strokeType="INSIDE" />
<Separator orientation="VERTICAL" prefHeight="20.0" />
<ToggleButton fx:id="plotButton" mnemonicParsing="false" onAction="#onPlotToggle" text="Measure" />
<ToggleButton fx:id="storeButton" mnemonicParsing="false" onAction="#onStoreButtonClick" text="Store" />
<Separator orientation="VERTICAL" prefHeight="20.0" />
<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" />
<Separator orientation="VERTICAL" prefHeight="20.0" />
<Pane HBox.hgrow="ALWAYS" />
<ToggleButton fx:id="consoleButton" mnemonicParsing="false" text="Console" />
</items>
</ToolBar>
<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>

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,9 +80,8 @@ 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;
@FXML @FXML
@ -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" />