Numass control room global update
This commit is contained in:
parent
c160fcdea4
commit
0bc03b6053
@ -16,7 +16,7 @@ dependencies {
|
||||
|
||||
task debug(dependsOn: classes, type: JavaExec) {
|
||||
main mainClass
|
||||
args "--config.resource=/config-debug/devices.xml"
|
||||
args = ["--config.resource=/config-debug/devices.xml"]
|
||||
classpath = sourceSets.main.runtimeClasspath
|
||||
description "Start application in debug mode with default virtual port"
|
||||
group "debug"
|
||||
@ -24,7 +24,7 @@ task debug(dependsOn: classes, type: JavaExec) {
|
||||
|
||||
task testRun(dependsOn: classes, type: JavaExec) {
|
||||
main mainClass
|
||||
args(["--config=D:/temp/test/numass-devices.xml", "--device=thermo-1"])
|
||||
args = ["--config=D:/temp/test/numass-devices.xml", "--device=thermo-1"]
|
||||
classpath = sourceSets.main.runtimeClasspath
|
||||
description "Start application using real device"
|
||||
group "debug"
|
||||
|
@ -1,53 +0,0 @@
|
||||
/*
|
||||
* Copyright 2015 Alexander Nozik.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package inr.numass.control.cryotemp;
|
||||
|
||||
import hep.dataforge.control.devices.DeviceFactory;
|
||||
import hep.dataforge.meta.Meta;
|
||||
import inr.numass.control.DeviceViewConnection;
|
||||
import inr.numass.control.NumassControlApplication;
|
||||
import javafx.stage.Stage;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* @author darksnake
|
||||
*/
|
||||
public class PKT8App extends NumassControlApplication<PKT8Device> {
|
||||
@Override
|
||||
protected DeviceViewConnection<PKT8Device> buildView(PKT8Device device) {
|
||||
return PKT8ViewConnection.build(device.getContext());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DeviceFactory getDeviceFactory() {
|
||||
return new PKT8DeviceFactory();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setupStage(Stage stage, PKT8Device device) {
|
||||
stage.setTitle("Numass temperature view " + device.getName());
|
||||
stage.setMinHeight(400);
|
||||
stage.setMinWidth(400);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean acceptDevice(Meta meta) {
|
||||
return Objects.equals(meta.getString("type"), "PKT8");
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -22,6 +22,6 @@ public class PKT8DeviceFactory implements DeviceViewFactory {
|
||||
|
||||
@Override
|
||||
public DeviceViewConnection buildView(Device device) {
|
||||
return PKT8ViewConnection.build(device.getContext());
|
||||
return new PKT8ViewConnection();
|
||||
}
|
||||
}
|
||||
|
@ -1,35 +0,0 @@
|
||||
package inr.numass.control.cryotemp;
|
||||
|
||||
import hep.dataforge.control.connections.Roles;
|
||||
import hep.dataforge.fx.fragments.FXFragment;
|
||||
import javafx.fxml.FXMLLoader;
|
||||
import javafx.scene.Parent;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Created by darksnake on 07-Oct-16.
|
||||
*/
|
||||
public class PKT8PlotFragment extends FXFragment {
|
||||
private PKT8PlotView plotController;
|
||||
|
||||
public PKT8PlotFragment(PKT8Device device) {
|
||||
super("PKT8 cryogenic temperature viewer", 600, 400);
|
||||
|
||||
try {
|
||||
FXMLLoader loader = new FXMLLoader(device.getContext().getClassLoader().getResource("fxml/PKT8Plot.fxml"));
|
||||
loader.setClassLoader(device.getContext().getClassLoader());
|
||||
loader.load();
|
||||
plotController = loader.getController();
|
||||
device.connect(plotController, Roles.VIEW_ROLE);
|
||||
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Parent buildRoot() {
|
||||
return plotController.getPane();
|
||||
}
|
||||
}
|
@ -1,144 +0,0 @@
|
||||
/*
|
||||
* Copyright 2015 Alexander Nozik.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package inr.numass.control.cryotemp;
|
||||
|
||||
import hep.dataforge.control.measurements.Measurement;
|
||||
import hep.dataforge.control.measurements.MeasurementListener;
|
||||
import hep.dataforge.meta.Meta;
|
||||
import hep.dataforge.plots.PlotUtils;
|
||||
import hep.dataforge.plots.data.TimePlottable;
|
||||
import hep.dataforge.plots.data.TimePlottableGroup;
|
||||
import hep.dataforge.plots.fx.FXPlotFrame;
|
||||
import hep.dataforge.plots.fx.PlotContainer;
|
||||
import hep.dataforge.plots.jfreechart.JFreeChartFrame;
|
||||
import inr.numass.control.DeviceViewConnection;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.fxml.Initializable;
|
||||
import javafx.scene.Node;
|
||||
import javafx.scene.control.ToggleButton;
|
||||
import javafx.scene.layout.AnchorPane;
|
||||
import javafx.scene.layout.BorderPane;
|
||||
|
||||
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 PKT8PlotView extends DeviceViewConnection<PKT8Device> implements Initializable, MeasurementListener {
|
||||
|
||||
private FXPlotFrame plotFrame;
|
||||
private TimePlottableGroup plottables;
|
||||
|
||||
@FXML
|
||||
private BorderPane root;
|
||||
@FXML
|
||||
private ToggleButton rawDataButton;
|
||||
@FXML
|
||||
private AnchorPane plotArea;
|
||||
|
||||
/**
|
||||
* Initializes the controller class.
|
||||
*/
|
||||
@Override
|
||||
public void initialize(URL url, ResourceBundle rb) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void open(PKT8Device device) throws Exception {
|
||||
super.open(device);
|
||||
rawDataButton.selectedProperty().addListener(observable -> {
|
||||
if (plotFrame != null) {
|
||||
setupPlotFrame(plotFrame.getConfig());
|
||||
if (device != null) {
|
||||
setupChannels(device);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
setupPlotFrame(device.meta().getMetaOrEmpty("plot.frame"));
|
||||
setupChannels(device);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws Exception {
|
||||
super.close();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set o reset plot area
|
||||
*/
|
||||
private synchronized void setupPlotFrame(Meta plotFrameMeta) {
|
||||
plottables = new TimePlottableGroup();
|
||||
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(PKT8Device device) {
|
||||
Collection<PKT8Channel> channels = device.getChanels();
|
||||
|
||||
//plot config from device configuration
|
||||
//Do not use view config here, it is applyed separately
|
||||
channels.stream()
|
||||
.filter(channel -> !plottables.has(channel.getName()))
|
||||
.forEachOrdered(channel -> {
|
||||
//plot config from device configuration
|
||||
TimePlottable plottable = new TimePlottable(channel.getName());
|
||||
plottable.configure(channel.meta());
|
||||
plottables.add(plottable);
|
||||
plotFrame.add(plottable);
|
||||
});
|
||||
if (device.meta().hasMeta("plotConfig")) {
|
||||
plottables.applyConfig(device.meta().getMeta("plotConfig"));
|
||||
plottables.setMaxItems(1000);
|
||||
plottables.setPrefItems(400);
|
||||
}
|
||||
// getPlottables.applyConfig(plotFrame.getConfig());
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void onMeasurementResult(Measurement measurement, Object result, Instant time) {
|
||||
PKT8Result res = PKT8Result.class.cast(result);
|
||||
//PENDING replace by connection?
|
||||
if (rawDataButton.isSelected()) {
|
||||
plottables.put(res.getChannel(), res.getRawValue());
|
||||
} else {
|
||||
plottables.put(res.getChannel(), res.getTemperature());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMeasurementFailed(Measurement measurement, Throwable exception) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Node getFXNode() {
|
||||
return root;
|
||||
}
|
||||
}
|
@ -1,150 +0,0 @@
|
||||
package inr.numass.control.cryotemp;
|
||||
|
||||
import hep.dataforge.context.Context;
|
||||
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.fragments.FragmentWindow;
|
||||
import hep.dataforge.fx.fragments.LogFragment;
|
||||
import inr.numass.control.DeviceViewConnection;
|
||||
import javafx.application.Platform;
|
||||
import javafx.event.ActionEvent;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.fxml.FXMLLoader;
|
||||
import javafx.fxml.Initializable;
|
||||
import javafx.scene.Node;
|
||||
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 javafx.scene.layout.BorderPane;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.time.Instant;
|
||||
import java.util.Comparator;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
/**
|
||||
* Created by darksnake on 07-Oct-16.
|
||||
*/
|
||||
public class PKT8View extends DeviceViewConnection<PKT8Device> implements Initializable, MeasurementListener {
|
||||
|
||||
public static PKT8ViewConnection build(Context context) {
|
||||
try {
|
||||
FXMLLoader loader = new FXMLLoader(context.getClassLoader().getResource("fxml/PKT8Indicator.fxml"));
|
||||
loader.setClassLoader(context.getClassLoader());
|
||||
loader.load();
|
||||
return loader.getController();
|
||||
} catch (IOException e) {
|
||||
throw new Error(e);
|
||||
}
|
||||
}
|
||||
|
||||
private LogFragment logFragment;
|
||||
private PKT8PlotFragment plotFragment;
|
||||
|
||||
@FXML
|
||||
private BorderPane root;
|
||||
@FXML
|
||||
private ToggleButton startStopButton;
|
||||
@FXML
|
||||
private ToggleButton storeButton;
|
||||
@FXML
|
||||
private ToggleButton consoleButton;
|
||||
@FXML
|
||||
private ToggleButton plotButton;
|
||||
@FXML
|
||||
private Label lastUpdateLabel;
|
||||
@FXML
|
||||
private TableView<PKT8Result> table;
|
||||
@FXML
|
||||
private TableColumn<TableView<PKT8Result>, String> sensorColumn;
|
||||
@FXML
|
||||
private TableColumn<TableView<PKT8Result>, Double> resColumn;
|
||||
@FXML
|
||||
private TableColumn<TableView<PKT8Result>, String> tempColumn;
|
||||
|
||||
|
||||
@Override
|
||||
public void initialize(URL location, ResourceBundle resources) {
|
||||
sensorColumn.setCellValueFactory(new PropertyValueFactory<>("channel"));
|
||||
resColumn.setCellValueFactory(new PropertyValueFactory<>("rawString"));
|
||||
tempColumn.setCellValueFactory(new PropertyValueFactory<>("temperatureString"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void open(@NotNull PKT8Device device) throws Exception {
|
||||
super.open(device);
|
||||
|
||||
this.logFragment = new LogFragment();
|
||||
logFragment.addRootLogHandler();
|
||||
new FragmentWindow(logFragment).bindTo(consoleButton);
|
||||
|
||||
|
||||
plotFragment = new PKT8PlotFragment(device);
|
||||
startStopButton.selectedProperty().setValue(getDevice().isMeasuring());
|
||||
|
||||
new FragmentWindow(plotFragment).bindTo(plotButton);
|
||||
bindBooleanToState("storing", storeButton.selectedProperty());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws Exception {
|
||||
super.close();
|
||||
logFragment = null;
|
||||
plotFragment = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMeasurementResult(Measurement<?> measurement, Object result, Instant time) {
|
||||
PKT8Result res = PKT8Result.class.cast(result);
|
||||
Platform.runLater(() -> {
|
||||
lastUpdateLabel.setText(time.toString());
|
||||
table.getItems().removeIf(it -> it.getChannel().equals(res.getChannel()));
|
||||
table.getItems().add(res);
|
||||
table.getItems().sort(Comparator.comparing(PKT8Result::getChannel));
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMeasurementFailed(Measurement measurement, Throwable exception) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
private void startMeasurement() throws MeasurementException {
|
||||
getDevice().startMeasurement();
|
||||
}
|
||||
|
||||
private void stopMeasurement() throws MeasurementException {
|
||||
if (getDevice().isMeasuring()) {
|
||||
getDevice().stopMeasurement(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@FXML
|
||||
private void onStartStopClick(ActionEvent event) {
|
||||
if (getDevice() != null) {
|
||||
try {
|
||||
if (startStopButton.isSelected()) {
|
||||
startMeasurement();
|
||||
} else {
|
||||
//in case device started
|
||||
stopMeasurement();
|
||||
}
|
||||
} catch (ControlException ex) {
|
||||
getDevice().getLogger().error("Failed to start or stop device", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node getFXNode() {
|
||||
return root;
|
||||
}
|
||||
}
|
@ -27,7 +27,7 @@ public class PKT8VirtualPort extends VirtualPort implements Metoid {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void evaluateRequest(String request) {
|
||||
protected synchronized void evaluateRequest(String request) {
|
||||
switch (request) {
|
||||
case "s":
|
||||
String[] letters = {"a", "b", "c", "d", "e", "f", "g", "h"};
|
||||
@ -48,16 +48,15 @@ public class PKT8VirtualPort extends VirtualPort implements Metoid {
|
||||
() -> {
|
||||
double res = average + generator.nextGaussian() * sigma;
|
||||
//TODO convert double value to formatted string
|
||||
return letter + "000120000\n";
|
||||
return String.format("%s000%d", letter, (int) (res * 100));
|
||||
},
|
||||
Duration.ZERO, Duration.ofMillis(200), letter, "measurement"
|
||||
Duration.ZERO, Duration.ofMillis(500), letter, "measurement"
|
||||
);
|
||||
}
|
||||
return;
|
||||
case "p":
|
||||
cancelByTag("measurement");
|
||||
this.recievePhrase("stopped\n\r");
|
||||
return;
|
||||
this.receivePhrase("Stopped");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright 2015 Alexander Nozik.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package inr.numass.control.cryotemp
|
||||
|
||||
import hep.dataforge.control.connections.Roles
|
||||
import hep.dataforge.control.devices.DeviceFactory
|
||||
import hep.dataforge.meta.Meta
|
||||
import inr.numass.control.DeviceViewConnection
|
||||
import inr.numass.control.NumassControlApplication
|
||||
import javafx.stage.Stage
|
||||
|
||||
/**
|
||||
* @author darksnake
|
||||
*/
|
||||
class PKT8App : NumassControlApplication<PKT8Device>() {
|
||||
override fun buildView(device: PKT8Device): DeviceViewConnection<PKT8Device> {
|
||||
return PKT8ViewConnection().apply {
|
||||
device.connect(this, Roles.VIEW_ROLE)
|
||||
}
|
||||
}
|
||||
|
||||
override val deviceFactory: DeviceFactory = PKT8DeviceFactory()
|
||||
|
||||
override fun setupStage(stage: Stage, device: PKT8Device) {
|
||||
stage.title = "Numass temperature view " + device.name
|
||||
stage.minHeight = 400.0
|
||||
stage.minWidth = 400.0
|
||||
}
|
||||
|
||||
override fun acceptDevice(meta: Meta): Boolean {
|
||||
return meta.getString("type") == "PKT8"
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -13,11 +13,13 @@ import hep.dataforge.plots.fx.FXPlotFrame
|
||||
import hep.dataforge.plots.fx.PlotContainer
|
||||
import hep.dataforge.plots.jfreechart.JFreeChartFrame
|
||||
import inr.numass.control.DeviceViewConnection
|
||||
import inr.numass.control.bindView
|
||||
import javafx.application.Platform
|
||||
import javafx.beans.binding.ListBinding
|
||||
import javafx.beans.property.SimpleObjectProperty
|
||||
import javafx.collections.FXCollections
|
||||
import javafx.collections.ListChangeListener
|
||||
import javafx.collections.transformation.SortedList
|
||||
import javafx.collections.MapChangeListener
|
||||
import javafx.collections.ObservableList
|
||||
import javafx.geometry.Orientation
|
||||
import javafx.scene.Node
|
||||
import javafx.scene.Parent
|
||||
@ -33,10 +35,11 @@ import java.time.Instant
|
||||
* Created by darksnake on 30-May-17.
|
||||
*/
|
||||
class PKT8ViewConnection : DeviceViewConnection<PKT8Device>(), MeasurementListener {
|
||||
private val view by lazy { CryoView() }
|
||||
internal val table = SortedList(FXCollections.observableArrayList<PKT8Result>()) { r1, r2 ->
|
||||
r1.channel.compareTo(r2.channel)
|
||||
}
|
||||
private val cryoView by lazy{ CryoView()}
|
||||
private val plotView by lazy { CryoPlotView()}
|
||||
|
||||
internal val table = FXCollections.observableHashMap<String, PKT8Result>()
|
||||
|
||||
|
||||
val lastUpdateProperty = SimpleObjectProperty<String>("NEVER")
|
||||
|
||||
@ -48,23 +51,21 @@ class PKT8ViewConnection : DeviceViewConnection<PKT8Device>(), MeasurementListen
|
||||
}
|
||||
|
||||
override fun getFXNode(): Node {
|
||||
return view.root;
|
||||
if (!isOpen) {
|
||||
throw RuntimeException("Not connected!")
|
||||
}
|
||||
return cryoView.root;
|
||||
}
|
||||
|
||||
override fun onMeasurementFailed(measurement: Measurement<*>, exception: Throwable) {
|
||||
throw exception;
|
||||
|
||||
}
|
||||
|
||||
override fun onMeasurementResult(measurement: Measurement<*>, result: Any, time: Instant) {
|
||||
if (result is PKT8Result) {
|
||||
Platform.runLater {
|
||||
lastUpdateProperty.set(time.toString())
|
||||
val item = table.find { it.channel == result.channel };
|
||||
if (item == null) {
|
||||
table.add(result);
|
||||
} else {
|
||||
table[table.indexOf(item)] = result
|
||||
}
|
||||
table.put(result.channel, result);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -74,9 +75,11 @@ class PKT8ViewConnection : DeviceViewConnection<PKT8Device>(), MeasurementListen
|
||||
top {
|
||||
toolbar {
|
||||
togglebutton("Measure") {
|
||||
isSelected = false
|
||||
bindBooleanToState(Sensor.MEASURING_STATE, selectedProperty())
|
||||
}
|
||||
togglebutton("Store") {
|
||||
isSelected = false
|
||||
bindBooleanToState("storing", selectedProperty())
|
||||
}
|
||||
separator(Orientation.VERTICAL)
|
||||
@ -85,9 +88,11 @@ class PKT8ViewConnection : DeviceViewConnection<PKT8Device>(), MeasurementListen
|
||||
}
|
||||
separator(Orientation.VERTICAL)
|
||||
togglebutton("Plot") {
|
||||
FragmentWindow(CryoPlotView().root).bindTo(this)
|
||||
isSelected = false
|
||||
bindView(plotView)
|
||||
}
|
||||
togglebutton("Log") {
|
||||
isSelected = false
|
||||
FragmentWindow(LogFragment().apply {
|
||||
addLogHandler(device.logger)
|
||||
}).bindTo(this)
|
||||
@ -95,12 +100,24 @@ class PKT8ViewConnection : DeviceViewConnection<PKT8Device>(), MeasurementListen
|
||||
}
|
||||
}
|
||||
center {
|
||||
tableview(table) {
|
||||
tableview<PKT8Result> {
|
||||
items = object : ListBinding<PKT8Result>() {
|
||||
init {
|
||||
bind(table)
|
||||
}
|
||||
|
||||
override fun computeValue(): ObservableList<PKT8Result> {
|
||||
return FXCollections.observableArrayList(table.values).apply {
|
||||
sortBy { it.channel }
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
column("Sensor", PKT8Result::channel);
|
||||
column("Resistance", PKT8Result::rawValue).cellFormat {
|
||||
text = String.format("%.2f", it)
|
||||
}
|
||||
column("Resistance", PKT8Result::temperature).cellFormat {
|
||||
column("Temperature", PKT8Result::temperature).cellFormat {
|
||||
text = String.format("%.2f", it)
|
||||
}
|
||||
}
|
||||
@ -116,7 +133,7 @@ class PKT8ViewConnection : DeviceViewConnection<PKT8Device>(), MeasurementListen
|
||||
}
|
||||
}
|
||||
|
||||
inner class CryoPlotView : View() {
|
||||
inner class CryoPlotView : View("PKT8 temperature plot") {
|
||||
val plotFrameMeta: Meta = device.meta.getMetaOrEmpty("plotConfig")
|
||||
|
||||
val plotFrame: FXPlotFrame by lazy {
|
||||
@ -130,27 +147,24 @@ class PKT8ViewConnection : DeviceViewConnection<PKT8Device>(), MeasurementListen
|
||||
val plottables: TimePlottableGroup by lazy {
|
||||
TimePlottableGroup().apply {
|
||||
setMaxAge(Duration.parse(plotFrameMeta.getString("maxAge", "PT2H")))
|
||||
table.addListener(ListChangeListener { change ->
|
||||
while (change.next()) {
|
||||
change.addedSubList.forEach {
|
||||
if (rawDataButton.isSelected()) {
|
||||
plottables.put(it.channel, it.rawValue)
|
||||
} else {
|
||||
plottables.put(it.channel, it.temperature)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
override val root: Parent = borderpane {
|
||||
prefWidth = 800.0
|
||||
prefHeight = 600.0
|
||||
PlotContainer.centerIn(this).plot = plotFrame
|
||||
bottom {
|
||||
rawDataButton = togglebutton("Raw data") {
|
||||
action {
|
||||
plottables.forEach {
|
||||
it.clear()
|
||||
top {
|
||||
toolbar {
|
||||
rawDataButton = togglebutton("Raw data") {
|
||||
isSelected = false
|
||||
action {
|
||||
clearPlot()
|
||||
}
|
||||
}
|
||||
button("Reset") {
|
||||
action {
|
||||
clearPlot()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -158,7 +172,7 @@ class PKT8ViewConnection : DeviceViewConnection<PKT8Device>(), MeasurementListen
|
||||
}
|
||||
|
||||
init {
|
||||
val channels = device.chanels
|
||||
val channels = device.chanels
|
||||
|
||||
//plot config from device configuration
|
||||
//Do not use view config here, it is applyed separately
|
||||
@ -176,6 +190,23 @@ class PKT8ViewConnection : DeviceViewConnection<PKT8Device>(), MeasurementListen
|
||||
plottables.setMaxItems(1000)
|
||||
plottables.setPrefItems(400)
|
||||
}
|
||||
table.addListener(MapChangeListener { change ->
|
||||
if (change.wasAdded()) {
|
||||
change.valueAdded.apply {
|
||||
if (rawDataButton.isSelected()) {
|
||||
plottables.put(this.channel, this.rawValue)
|
||||
} else {
|
||||
plottables.put(this.channel, this.temperature)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fun clearPlot() {
|
||||
plottables.forEach {
|
||||
it.clear()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -18,10 +18,11 @@ package inr.numass.control.magnet;
|
||||
import hep.dataforge.control.ports.VirtualPort;
|
||||
import hep.dataforge.exceptions.PortException;
|
||||
import hep.dataforge.meta.Meta;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
*
|
||||
@ -69,7 +70,7 @@ public class VirtualLambdaPort extends VirtualPort {
|
||||
evaluateRequest(comand.trim(), value.trim());
|
||||
} catch (RuntimeException ex) {
|
||||
|
||||
recievePhrase("FAIL");//TODO какая команда правильная?
|
||||
receivePhrase("FAIL");//TODO какая команда правильная?
|
||||
LoggerFactory.getLogger(getClass()).error("Request evaluation failure", ex);
|
||||
}
|
||||
|
||||
|
@ -1,9 +1,12 @@
|
||||
package inr.numass.control
|
||||
|
||||
import hep.dataforge.fx.fragments.FXFragment
|
||||
import hep.dataforge.fx.fragments.FragmentWindow
|
||||
import hep.dataforge.values.Value
|
||||
import javafx.beans.value.ObservableValue
|
||||
import javafx.event.EventTarget
|
||||
import javafx.geometry.Orientation
|
||||
import javafx.scene.control.ToggleButton
|
||||
import javafx.scene.paint.Color
|
||||
import javafx.scene.paint.Paint
|
||||
import javafx.scene.shape.Circle
|
||||
@ -96,3 +99,9 @@ fun EventTarget.deviceStateIndicator(connection: DeviceViewConnection<*>, state:
|
||||
separator(Orientation.VERTICAL)
|
||||
}
|
||||
}
|
||||
|
||||
fun ToggleButton.bindView(view: View) {
|
||||
//TODO use view instead of FXFragment
|
||||
FragmentWindow(FXFragment.buildFromNode(view.title) { view.root }).bindTo(this)
|
||||
}
|
||||
|
@ -67,7 +67,7 @@ abstract class NumassControlApplication<D : Device> : App() {
|
||||
|
||||
|
||||
try {
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val d = deviceFactory.build(ctx, deviceConfig) as D
|
||||
d.init()
|
||||
connectStorage(d, config)
|
||||
@ -80,9 +80,14 @@ abstract class NumassControlApplication<D : Device> : App() {
|
||||
}
|
||||
|
||||
override fun stop() {
|
||||
super.stop()
|
||||
device.shutdown()
|
||||
device.context.close()
|
||||
try {
|
||||
device.shutdown()
|
||||
} catch (ex: Exception) {
|
||||
LoggerFactory.getLogger(javaClass).error("Failed to shutdown application", ex);
|
||||
} finally {
|
||||
device.context.close()
|
||||
super.stop()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -31,7 +31,7 @@ class JFCTest : View("My View") {
|
||||
override val root = borderpane {
|
||||
center {
|
||||
container.plot = plot
|
||||
add(container.root)
|
||||
add(container.pane)
|
||||
}
|
||||
bottom {
|
||||
add(button)
|
||||
|
Loading…
Reference in New Issue
Block a user