vac to kotlin finished
This commit is contained in:
parent
5e21fa5a0f
commit
a7b5ec1101
@ -1,4 +1,3 @@
|
||||
|
||||
apply plugin: 'application'
|
||||
|
||||
if (!hasProperty('mainClass')) {
|
||||
@ -14,18 +13,18 @@ dependencies {
|
||||
compile project(':numass-control')
|
||||
}
|
||||
|
||||
task debug(dependsOn: classes, type: JavaExec) {
|
||||
task testDevice(dependsOn: classes, type: JavaExec) {
|
||||
main mainClass
|
||||
args = ["--config.resource=/config-debug/devices.xml"]
|
||||
args = ["--config.resource=/config-test/devices.xml"]
|
||||
classpath = sourceSets.main.runtimeClasspath
|
||||
description "Start application in debug mode with default virtual port"
|
||||
group "debug"
|
||||
group "test"
|
||||
}
|
||||
|
||||
task testRun(dependsOn: classes, type: JavaExec) {
|
||||
main mainClass
|
||||
args = ["--config=D:/temp/test/numass-devices.xml", "--device=thermo-1"]
|
||||
classpath = sourceSets.main.runtimeClasspath
|
||||
description "Start application using real device"
|
||||
group "debug"
|
||||
}
|
||||
//task testRun(dependsOn: classes, type: JavaExec) {
|
||||
// main mainClass
|
||||
// args = ["--config=D:/temp/test/numass-devices.xml", "--device=thermo-1"]
|
||||
// classpath = sourceSets.main.runtimeClasspath
|
||||
// description "Start application using real device"
|
||||
// group "debug"
|
||||
//}
|
@ -16,7 +16,6 @@
|
||||
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
|
||||
@ -32,7 +31,7 @@ class PKT8App : NumassControlApplication<PKT8Device>() {
|
||||
}
|
||||
}
|
||||
|
||||
override val deviceFactory: DeviceFactory = PKT8DeviceFactory()
|
||||
override val deviceFactory = PKT8DeviceFactory()
|
||||
|
||||
override fun setupStage(stage: Stage, device: PKT8Device) {
|
||||
stage.title = "Numass temperature view " + device.name
|
||||
|
@ -9,7 +9,7 @@ import inr.numass.control.DeviceViewFactory
|
||||
/**
|
||||
* Created by darksnake on 09-May-17.
|
||||
*/
|
||||
class PKT8DeviceFactory : DeviceViewFactory {
|
||||
class PKT8DeviceFactory : DeviceViewFactory<PKT8Device> {
|
||||
override fun getType(): String {
|
||||
return PKT8Device.PKT8_DEVICE_TYPE
|
||||
}
|
||||
@ -18,7 +18,7 @@ class PKT8DeviceFactory : DeviceViewFactory {
|
||||
return PKT8Device(context, meta)
|
||||
}
|
||||
|
||||
override fun buildView(device: Device): DeviceViewConnection<*> {
|
||||
override fun buildView(device: Device): DeviceViewConnection<PKT8Device> {
|
||||
return PKT8ViewConnection()
|
||||
}
|
||||
}
|
||||
|
@ -21,7 +21,6 @@ import javafx.collections.FXCollections
|
||||
import javafx.collections.MapChangeListener
|
||||
import javafx.collections.ObservableList
|
||||
import javafx.geometry.Orientation
|
||||
import javafx.scene.Node
|
||||
import javafx.scene.Parent
|
||||
import javafx.scene.control.ToggleButton
|
||||
import javafx.scene.layout.Priority
|
||||
@ -34,7 +33,10 @@ import java.time.Instant
|
||||
* Created by darksnake on 30-May-17.
|
||||
*/
|
||||
class PKT8ViewConnection : DeviceViewConnection<PKT8Device>(), MeasurementListener {
|
||||
private val cryoView by lazy { CryoView() }
|
||||
|
||||
override fun buildView(): View {
|
||||
return CryoView()
|
||||
}
|
||||
|
||||
internal val table = FXCollections.observableHashMap<String, PKT8Result>()
|
||||
val lastUpdateProperty = SimpleObjectProperty<String>("NEVER")
|
||||
@ -46,13 +48,6 @@ class PKT8ViewConnection : DeviceViewConnection<PKT8Device>(), MeasurementListen
|
||||
}
|
||||
}
|
||||
|
||||
override fun getFXNode(): Node {
|
||||
if (!isOpen) {
|
||||
throw RuntimeException("Not connected!")
|
||||
}
|
||||
return cryoView.root;
|
||||
}
|
||||
|
||||
override fun onMeasurementFailed(measurement: Measurement<*>, exception: Throwable) {
|
||||
|
||||
}
|
||||
@ -66,7 +61,7 @@ class PKT8ViewConnection : DeviceViewConnection<PKT8Device>(), MeasurementListen
|
||||
}
|
||||
}
|
||||
|
||||
inner class CryoView() : View() {
|
||||
inner class CryoView : View() {
|
||||
private var plotButton: ToggleButton by singleAssign()
|
||||
private var logButton: ToggleButton by singleAssign()
|
||||
|
||||
|
@ -15,7 +15,6 @@
|
||||
*/
|
||||
package inr.numass.control.msp
|
||||
|
||||
import hep.dataforge.control.devices.DeviceFactory
|
||||
import hep.dataforge.meta.Meta
|
||||
import inr.numass.control.DeviceViewConnection
|
||||
import inr.numass.control.NumassControlApplication
|
||||
@ -30,7 +29,7 @@ class MspApp : NumassControlApplication<MspDevice>() {
|
||||
return MspViewConnection()
|
||||
}
|
||||
|
||||
override val deviceFactory: DeviceFactory = MspDeviceFactory()
|
||||
override val deviceFactory = MspDeviceFactory()
|
||||
|
||||
|
||||
override fun setupStage(stage: Stage, device: MspDevice) {
|
||||
|
@ -9,7 +9,7 @@ import inr.numass.control.DeviceViewFactory
|
||||
/**
|
||||
* Created by darksnake on 09-May-17.
|
||||
*/
|
||||
class MspDeviceFactory : DeviceViewFactory {
|
||||
class MspDeviceFactory : DeviceViewFactory<MspDevice> {
|
||||
override fun getType(): String {
|
||||
return MspDevice.MSP_DEVICE_TYPE
|
||||
}
|
||||
@ -19,7 +19,7 @@ class MspDeviceFactory : DeviceViewFactory {
|
||||
return device
|
||||
}
|
||||
|
||||
override fun buildView(device: Device): DeviceViewConnection<*> {
|
||||
override fun buildView(device: Device): DeviceViewConnection<MspDevice> {
|
||||
return MspViewConnection()
|
||||
}
|
||||
}
|
||||
|
@ -41,7 +41,6 @@ import javafx.geometry.Insets
|
||||
import javafx.geometry.Orientation
|
||||
import javafx.scene.Parent
|
||||
import javafx.scene.control.Alert
|
||||
import javafx.scene.control.ToggleButton
|
||||
import javafx.scene.layout.Priority
|
||||
import javafx.scene.layout.VBox
|
||||
import javafx.scene.paint.Paint
|
||||
@ -63,7 +62,7 @@ class MspViewConnection() : DeviceViewConnection<MspDevice>(), DeviceListener, N
|
||||
}
|
||||
|
||||
override fun buildView(): View {
|
||||
return MspView();
|
||||
return MspView()
|
||||
}
|
||||
|
||||
override fun pushValue(valueName: String, value: Value) {
|
||||
@ -110,8 +109,6 @@ class MspViewConnection() : DeviceViewConnection<MspDevice>(), DeviceListener, N
|
||||
}
|
||||
}
|
||||
|
||||
private var logButton: ToggleButton by singleAssign()
|
||||
|
||||
private val logWindow = FragmentWindow(LogFragment().apply {
|
||||
addLogHandler(device.logger)
|
||||
})
|
||||
@ -174,7 +171,7 @@ class MspViewConnection() : DeviceViewConnection<MspDevice>(), DeviceListener, N
|
||||
}
|
||||
separator(Orientation.VERTICAL)
|
||||
|
||||
logButton = togglebutton("Log") {
|
||||
togglebutton("Log") {
|
||||
isSelected = false
|
||||
logWindow.bindTo(this)
|
||||
}
|
||||
@ -199,7 +196,6 @@ class MspViewConnection() : DeviceViewConnection<MspDevice>(), DeviceListener, N
|
||||
pl.configureValue("title", title)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -24,43 +24,56 @@ import java.util.*
|
||||
/**
|
||||
* Created by darksnake on 14-May-17.
|
||||
*/
|
||||
abstract class DeviceViewConnection<D : Device>() : Component(), Connection<D>, DeviceListener, FXObject {
|
||||
abstract class DeviceViewConnection<D : Device> : Component(), Connection, DeviceListener, FXObject {
|
||||
|
||||
private val bindings = HashMap<String, ObjectBinding<Value>>()
|
||||
|
||||
var device: D by singleAssign()
|
||||
|
||||
val viewProperty = SimpleObjectProperty<View>(this, "view", null)
|
||||
var view: View? by viewProperty
|
||||
|
||||
override fun isOpen(): Boolean {
|
||||
return this.view != null
|
||||
private val deviceProperty = SimpleObjectProperty<D>(this, "device", null)
|
||||
val device: D
|
||||
get() {
|
||||
val res = deviceProperty.get();
|
||||
if (res == null) {
|
||||
throw RuntimeException("Not connected!");
|
||||
} else {
|
||||
return res
|
||||
}
|
||||
}
|
||||
|
||||
override fun open(device: D) {
|
||||
if(!isOpen) {
|
||||
this.device = device
|
||||
this.view = buildView();
|
||||
} else{
|
||||
private val viewProperty = SimpleObjectProperty<View>(this, "view", null)
|
||||
val view: View
|
||||
get() {
|
||||
if (viewProperty.get() == null) {
|
||||
viewProperty.set(buildView(device))
|
||||
}
|
||||
return viewProperty.get();
|
||||
}
|
||||
|
||||
override fun isOpen(): Boolean {
|
||||
return this.deviceProperty.get() != null
|
||||
}
|
||||
|
||||
override fun open(obj: Any) {
|
||||
if (!isOpen) {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
deviceProperty.set(obj as D)
|
||||
} else {
|
||||
log.warning("Connection already opened")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
override fun close() {
|
||||
view?.close()
|
||||
this.view = null
|
||||
if (viewProperty.isNotNull.get()) {
|
||||
view.close()
|
||||
}
|
||||
deviceProperty.set(null)
|
||||
}
|
||||
|
||||
override fun getFXNode(): Node {
|
||||
if (view == null) {
|
||||
throw RuntimeException("Connection not opened");
|
||||
} else {
|
||||
return view!!.root;
|
||||
}
|
||||
return view.root;
|
||||
}
|
||||
|
||||
abstract fun buildView(): View;
|
||||
abstract fun buildView(device: D): View;
|
||||
|
||||
/**
|
||||
* Get binding for a given device state
|
||||
@ -74,7 +87,7 @@ abstract class DeviceViewConnection<D : Device>() : Component(), Connection<D>,
|
||||
object : ObjectBinding<Value>() {
|
||||
override fun computeValue(): Value {
|
||||
if (isOpen) {
|
||||
return device!!.getState(stateName)
|
||||
return device.getState(stateName)
|
||||
} else {
|
||||
return Value.NULL
|
||||
}
|
||||
@ -103,7 +116,7 @@ abstract class DeviceViewConnection<D : Device>() : Component(), Connection<D>,
|
||||
property.addListener { observable, oldValue, newValue ->
|
||||
if (isOpen && oldValue != newValue) {
|
||||
runAsync {
|
||||
device!!.setState(state, newValue).get().booleanValue();
|
||||
device.setState(state, newValue).get().booleanValue();
|
||||
} ui {
|
||||
property.set(it)
|
||||
}
|
||||
@ -128,7 +141,7 @@ abstract class DeviceViewConnection<D : Device>() : Component(), Connection<D>,
|
||||
}
|
||||
togglebutton("View") {
|
||||
isSelected = false
|
||||
FragmentWindow(FXFragment.buildFromNode(device?.name) { fxNode }).bindTo(this)
|
||||
FragmentWindow(FXFragment.buildFromNode(device.name) { fxNode }).bindTo(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,10 +3,10 @@ package inr.numass.control
|
||||
import hep.dataforge.control.devices.Device
|
||||
import hep.dataforge.control.devices.DeviceFactory
|
||||
|
||||
interface DeviceViewFactory : DeviceFactory {
|
||||
interface DeviceViewFactory<D : Device> : DeviceFactory<D> {
|
||||
/**
|
||||
* Create but do not connect view connection for the device
|
||||
* @return
|
||||
*/
|
||||
fun buildView(device: Device): DeviceViewConnection<*>
|
||||
fun buildView(device: Device): DeviceViewConnection<D>
|
||||
}
|
||||
|
@ -1,16 +1,23 @@
|
||||
package inr.numass.control
|
||||
|
||||
import hep.dataforge.kodex.KMetaBuilder
|
||||
import hep.dataforge.plots.PlotFrame
|
||||
import hep.dataforge.plots.Plottable
|
||||
import hep.dataforge.plots.fx.PlotContainer
|
||||
import hep.dataforge.plots.jfreechart.JFreeChartFrame
|
||||
import hep.dataforge.values.Value
|
||||
import javafx.beans.value.ObservableValue
|
||||
import javafx.event.EventTarget
|
||||
import javafx.geometry.Orientation
|
||||
import javafx.scene.Node
|
||||
import javafx.scene.layout.BorderPane
|
||||
import javafx.scene.paint.Color
|
||||
import javafx.scene.paint.Paint
|
||||
import javafx.scene.shape.Circle
|
||||
import javafx.scene.shape.StrokeType
|
||||
import org.controlsfx.control.ToggleSwitch
|
||||
import tornadofx.*
|
||||
import java.util.*
|
||||
|
||||
|
||||
/**
|
||||
@ -128,3 +135,15 @@ fun EventTarget.switch(text: String = "", op: (ToggleSwitch.() -> Unit)? = null)
|
||||
val switch = ToggleSwitch(text)
|
||||
return opcr(this, switch, op)
|
||||
}
|
||||
|
||||
/**
|
||||
* Add plot
|
||||
*/
|
||||
fun BorderPane.plot(plottables: Iterable<Plottable> = Collections.emptyList(), metaTransform: (KMetaBuilder.() -> Unit)? = null): PlotFrame {
|
||||
val meta = KMetaBuilder("plotFrame");
|
||||
metaTransform?.invoke(meta)
|
||||
val plot = JFreeChartFrame(meta)
|
||||
plot.addAll(plottables)
|
||||
PlotContainer.centerIn(this).plot = plot
|
||||
return plot;
|
||||
}
|
@ -3,9 +3,9 @@ package inr.numass.control
|
||||
import ch.qos.logback.classic.Level
|
||||
import hep.dataforge.control.connections.Roles
|
||||
import hep.dataforge.control.devices.Device
|
||||
import hep.dataforge.control.devices.DeviceFactory
|
||||
import hep.dataforge.exceptions.ControlException
|
||||
import hep.dataforge.meta.Meta
|
||||
import hep.dataforge.utils.ContextMetaFactory
|
||||
import javafx.scene.Scene
|
||||
import javafx.stage.Stage
|
||||
import org.slf4j.LoggerFactory
|
||||
@ -31,8 +31,6 @@ abstract class NumassControlApplication<D : Device> : App() {
|
||||
stage.scene = scene
|
||||
|
||||
stage.show()
|
||||
|
||||
|
||||
setupStage(stage, device)
|
||||
setDFStageIcon(stage)
|
||||
}
|
||||
@ -49,7 +47,7 @@ abstract class NumassControlApplication<D : Device> : App() {
|
||||
|
||||
* @return
|
||||
*/
|
||||
protected abstract val deviceFactory: DeviceFactory
|
||||
protected abstract val deviceFactory: ContextMetaFactory<D>
|
||||
|
||||
protected abstract fun setupStage(stage: Stage, device: D)
|
||||
|
||||
|
@ -3,10 +3,18 @@ apply plugin: 'application'
|
||||
version = "0.5.0"
|
||||
|
||||
if (!hasProperty('mainClass')) {
|
||||
ext.mainClass = 'inr.numass.readvac.ReadVac'
|
||||
ext.mainClass = 'inr.numass.control.readvac.ReadVac'
|
||||
}
|
||||
mainClassName = mainClass
|
||||
|
||||
dependencies {
|
||||
compile project(':numass-control')
|
||||
}
|
||||
|
||||
task testDevice(dependsOn: classes, type: JavaExec) {
|
||||
main mainClass
|
||||
args = ["--config.resource=/config-test/devices.xml"]
|
||||
classpath = sourceSets.main.runtimeClasspath
|
||||
description "Start application in debug mode with default virtual port"
|
||||
group "test"
|
||||
}
|
@ -13,16 +13,12 @@ import hep.dataforge.control.measurements.SimpleMeasurement;
|
||||
import hep.dataforge.control.ports.ComPortHandler;
|
||||
import hep.dataforge.control.ports.PortFactory;
|
||||
import hep.dataforge.control.ports.PortHandler;
|
||||
import hep.dataforge.description.ValueDef;
|
||||
import hep.dataforge.exceptions.ControlException;
|
||||
import hep.dataforge.meta.Meta;
|
||||
|
||||
/**
|
||||
* @author Alexander Nozik
|
||||
*/
|
||||
@ValueDef(name = "port")
|
||||
@ValueDef(name = "delay")
|
||||
@ValueDef(name = "timeout")
|
||||
public class CM32Device extends PortSensor<Double> {
|
||||
public CM32Device() {
|
||||
}
|
||||
@ -68,7 +64,7 @@ public class CM32Device extends PortSensor<Double> {
|
||||
this.progressUpdate("No signal");
|
||||
updateState(CONNECTED_STATE, false);
|
||||
return null;
|
||||
} else if (answer.indexOf("PM1:mbar") < -1) {
|
||||
} else if (!answer.contains("PM1:mbar")) {
|
||||
this.progressUpdate("Wrong answer: " + answer);
|
||||
updateState(CONNECTED_STATE, false);
|
||||
return null;
|
||||
|
@ -7,7 +7,7 @@ package inr.numass.control.readvac;
|
||||
|
||||
import hep.dataforge.context.Context;
|
||||
import hep.dataforge.control.RoleDef;
|
||||
import hep.dataforge.control.collectors.PointCollector;
|
||||
import hep.dataforge.control.collectors.RegularPointCollector;
|
||||
import hep.dataforge.control.collectors.ValueCollector;
|
||||
import hep.dataforge.control.connections.Roles;
|
||||
import hep.dataforge.control.connections.StorageConnection;
|
||||
@ -18,7 +18,6 @@ import hep.dataforge.control.measurements.AbstractMeasurement;
|
||||
import hep.dataforge.control.measurements.Measurement;
|
||||
import hep.dataforge.description.ValueDef;
|
||||
import hep.dataforge.exceptions.ControlException;
|
||||
import hep.dataforge.exceptions.MeasurementException;
|
||||
import hep.dataforge.meta.Meta;
|
||||
import hep.dataforge.storage.api.PointLoader;
|
||||
import hep.dataforge.storage.commons.LoaderFactory;
|
||||
@ -30,6 +29,7 @@ import hep.dataforge.values.Value;
|
||||
import hep.dataforge.values.ValueType;
|
||||
import inr.numass.control.StorageHelper;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
@ -53,7 +53,6 @@ import static hep.dataforge.control.devices.PortSensor.CONNECTED_STATE;
|
||||
public class VacCollectorDevice extends Sensor<DataPoint> {
|
||||
|
||||
private Map<String, Sensor<Double>> sensorMap = new LinkedHashMap<>();
|
||||
private int delay = 5000;
|
||||
private StorageHelper helper = new StorageHelper(VacCollectorDevice.this, this::buildLoader);
|
||||
|
||||
public VacCollectorDevice() {
|
||||
@ -72,8 +71,7 @@ public class VacCollectorDevice extends Sensor<DataPoint> {
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void setSensors(Sensor... sensors) {
|
||||
public void setSensors(Sensor<Double>... sensors) {
|
||||
setSensors(Arrays.asList(sensors));
|
||||
}
|
||||
|
||||
@ -98,13 +96,13 @@ public class VacCollectorDevice extends Sensor<DataPoint> {
|
||||
return "Numass vacuum";
|
||||
}
|
||||
|
||||
public void setDelay(int delay) throws MeasurementException {
|
||||
this.delay = delay;
|
||||
if (isMeasuring()) {
|
||||
getMeasurement().stop(false);
|
||||
getMeasurement().start();
|
||||
}
|
||||
}
|
||||
// public void setDelay(int delay) throws MeasurementException {
|
||||
// this.delay = delay;
|
||||
// if (isMeasuring()) {
|
||||
// getMeasurement().stop(false);
|
||||
// getMeasurement().start();
|
||||
// }
|
||||
// }
|
||||
|
||||
@Override
|
||||
public void shutdown() throws ControlException {
|
||||
@ -130,9 +128,13 @@ public class VacCollectorDevice extends Sensor<DataPoint> {
|
||||
return sensorMap.values();
|
||||
}
|
||||
|
||||
private Duration getAveragingDuration() {
|
||||
return Duration.parse(meta().getString("averagingDuration", "PT30S"));
|
||||
}
|
||||
|
||||
private class VacuumMeasurement extends AbstractMeasurement<DataPoint> {
|
||||
|
||||
private final ValueCollector collector = new PointCollector(this::result, sensorMap.keySet());
|
||||
private final ValueCollector collector = new RegularPointCollector(getAveragingDuration(), this::result);
|
||||
private ScheduledExecutorService executor;
|
||||
private ScheduledFuture<?> currentTask;
|
||||
|
||||
@ -142,11 +144,10 @@ public class VacCollectorDevice extends Sensor<DataPoint> {
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
executor = Executors
|
||||
.newSingleThreadScheduledExecutor((Runnable r) -> new Thread(r, "VacuumMeasurement thread"));
|
||||
executor = Executors.newSingleThreadScheduledExecutor((Runnable r) -> new Thread(r, "VacuumMeasurement thread"));
|
||||
int delay = meta().getInt("delay", 5) * 1000;
|
||||
currentTask = executor.scheduleWithFixedDelay(() -> {
|
||||
sensorMap.values().forEach((sensor) -> {
|
||||
try {
|
||||
|
@ -1,52 +0,0 @@
|
||||
package inr.numass.control.readvac;
|
||||
|
||||
import hep.dataforge.context.Context;
|
||||
import hep.dataforge.control.devices.Device;
|
||||
import hep.dataforge.control.devices.Sensor;
|
||||
import hep.dataforge.meta.Meta;
|
||||
import inr.numass.control.DeviceViewConnection;
|
||||
import inr.numass.control.DeviceViewFactory;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* A factory for vacuum measurements collector
|
||||
* Created by darksnake on 16-May-17.
|
||||
*/
|
||||
public class VacDeviceFactory implements DeviceViewFactory {
|
||||
@Override
|
||||
public String getType() {
|
||||
return "numass:vac";
|
||||
}
|
||||
|
||||
public Sensor<Double> buildSensor(Context context, Meta sensorConfig) {
|
||||
switch (sensorConfig.getString("sensorType", "")) {
|
||||
case "mks":
|
||||
return new MKSVacDevice(context, sensorConfig);
|
||||
case "CM32":
|
||||
return new CM32Device(context, sensorConfig);
|
||||
case "meradat":
|
||||
return new MeradatVacDevice(context, sensorConfig);
|
||||
case "baratron":
|
||||
return new MKSBaratronDevice(context, sensorConfig);
|
||||
default:
|
||||
throw new RuntimeException("Unknown vacuum sensor type");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public VacCollectorDevice build(Context context, Meta config) {
|
||||
List<Sensor<Double>> sensors = config.getMetaList("sensor").stream()
|
||||
.map(sensorConfig -> buildSensor(context, sensorConfig)).collect(Collectors.toList());
|
||||
|
||||
VacCollectorDevice collector = new VacCollectorDevice(context, config);
|
||||
collector.setSensors(sensors);
|
||||
return collector;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DeviceViewConnection buildView(Device device) {
|
||||
return VacCollectorView.build(device.getContext());
|
||||
}
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package inr.numass.control.readvac;
|
||||
|
||||
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 Alexander Nozik
|
||||
*/
|
||||
public class ReadVac extends NumassControlApplication<VacCollectorDevice> {
|
||||
@Override
|
||||
protected DeviceViewConnection<VacCollectorDevice> buildView(VacCollectorDevice device) {
|
||||
return VacCollectorView.build(device.getContext());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DeviceFactory getDeviceFactory() {
|
||||
return new VacDeviceFactory();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setupStage(Stage stage, VacCollectorDevice device) {
|
||||
stage.setTitle("Numass vacuum measurements");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean acceptDevice(Meta meta) {
|
||||
return Objects.equals(meta.getString("type", ""), "numass:vac");
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package inr.numass.control.readvac
|
||||
|
||||
import hep.dataforge.meta.Meta
|
||||
import hep.dataforge.utils.ContextMetaFactory
|
||||
import inr.numass.control.DeviceViewConnection
|
||||
import inr.numass.control.NumassControlApplication
|
||||
import javafx.stage.Stage
|
||||
|
||||
/**
|
||||
* @author Alexander Nozik
|
||||
*/
|
||||
class ReadVac : NumassControlApplication<VacCollectorDevice>() {
|
||||
override fun buildView(device: VacCollectorDevice): DeviceViewConnection<VacCollectorDevice> {
|
||||
return VacCollectorViewConnection()
|
||||
}
|
||||
|
||||
override val deviceFactory: ContextMetaFactory<VacCollectorDevice> = VacDeviceFactory()
|
||||
|
||||
override fun setupStage(stage: Stage, device: VacCollectorDevice) {
|
||||
stage.title = "Numass vacuum measurements"
|
||||
}
|
||||
|
||||
override fun acceptDevice(meta: Meta): Boolean {
|
||||
return meta.getString("type", "") == "numass:vac"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,90 +0,0 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package inr.numass.control.readvac;
|
||||
|
||||
import hep.dataforge.control.connections.Roles;
|
||||
import hep.dataforge.control.devices.Sensor;
|
||||
import hep.dataforge.control.virtual.Virtual;
|
||||
import javafx.application.Application;
|
||||
import javafx.fxml.FXMLLoader;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.stage.Stage;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexander Nozik
|
||||
*/
|
||||
public class TestVac extends Application {
|
||||
|
||||
VacCollectorView controller;
|
||||
|
||||
@Override
|
||||
public void start(Stage stage) {
|
||||
try {
|
||||
Sensor<Double> sensor1 = Virtual.randomDoubleSensor("vac1", Duration.ofMillis(200), 1e-5, 2e-6);
|
||||
Sensor<Double> sensor2 = Virtual.randomDoubleSensor("vac2", Duration.ofMillis(200), 2e-5, 2e-6);
|
||||
Sensor<Double> sensor3 = Virtual.randomDoubleSensor("vac3", Duration.ofMillis(200), 1e-7, 1e-8);
|
||||
|
||||
// Sensor<Double> poweredSensor = new VirtualSensorFactory<Double>(
|
||||
// "vac4",
|
||||
// (sensor) -> {
|
||||
// if (sensor.getState("power").booleanValue()) {
|
||||
// return 1e-6;
|
||||
// } else {
|
||||
// return null;
|
||||
// }
|
||||
// })
|
||||
// .addState("power")
|
||||
// .setMeta(new MetaBuilder("device")
|
||||
// .setValue("color", "magenta")
|
||||
// .setValue("thickness", 3)
|
||||
// .setValue("powerButton", true))
|
||||
// .addCommand("setPower", new BiConsumer<Sensor<Double>, Value>() {
|
||||
// @Override
|
||||
// public void accept(Sensor<Double> sensor, Value power) {
|
||||
//
|
||||
// }
|
||||
// })
|
||||
// .build();
|
||||
VacCollectorDevice collector = new VacCollectorDevice();
|
||||
collector.setSensors(sensor1, sensor2, sensor3);
|
||||
collector.init();
|
||||
|
||||
// collector.getConfig().putNode(new MetaBuilder("storage").putValue("path", "D:\\temp\\test"));
|
||||
|
||||
FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/VacCollector.fxml"));
|
||||
loader.load();
|
||||
controller = loader.getController();
|
||||
collector.connect(controller, Roles.VIEW_ROLE);
|
||||
|
||||
Scene scene = new Scene(loader.getRoot(), 800, 600);
|
||||
|
||||
stage.setTitle("Vacuum measurement test");
|
||||
stage.setScene(scene);
|
||||
stage.show();
|
||||
} catch (Exception ex) {
|
||||
throw new Error(ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() throws Exception {
|
||||
if (controller != null) {
|
||||
controller.getDevice().shutdown();
|
||||
}
|
||||
super.stop();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param args the command line arguments
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
launch(args);
|
||||
}
|
||||
|
||||
}
|
@ -1,277 +0,0 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package inr.numass.control.readvac;
|
||||
|
||||
import hep.dataforge.context.Context;
|
||||
import hep.dataforge.control.connections.Roles;
|
||||
import hep.dataforge.control.devices.Device;
|
||||
import hep.dataforge.control.devices.Sensor;
|
||||
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 hep.dataforge.meta.Meta;
|
||||
import hep.dataforge.meta.MetaBuilder;
|
||||
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 hep.dataforge.tables.DataPoint;
|
||||
import hep.dataforge.values.Value;
|
||||
import inr.numass.control.DeviceViewConnection;
|
||||
import javafx.application.Platform;
|
||||
import javafx.beans.value.ObservableValue;
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.event.ActionEvent;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.fxml.FXMLLoader;
|
||||
import javafx.fxml.Initializable;
|
||||
import javafx.scene.Node;
|
||||
import javafx.scene.control.ChoiceBox;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.control.ToggleButton;
|
||||
import javafx.scene.layout.AnchorPane;
|
||||
import javafx.scene.layout.BorderPane;
|
||||
import javafx.scene.layout.VBox;
|
||||
import javafx.util.Duration;
|
||||
import org.controlsfx.control.Notifications;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneOffset;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
/**
|
||||
* A view controller for Vac collector
|
||||
*
|
||||
* @author <a href="mailto:altavir@gmail.com">Alexander Nozik</a>
|
||||
*/
|
||||
public class VacCollectorView extends DeviceViewConnection<VacCollectorDevice> implements Initializable, MeasurementListener {
|
||||
|
||||
public static VacCollectorView build(Context context) {
|
||||
try {
|
||||
FXMLLoader loader = new FXMLLoader(context.getClassLoader().getResource("fxml/VacCollector.fxml"));
|
||||
loader.setClassLoader(context.getClassLoader());
|
||||
loader.load();
|
||||
return loader.getController();
|
||||
} catch (IOException e) {
|
||||
throw new Error(e);
|
||||
}
|
||||
}
|
||||
|
||||
private final DateTimeFormatter TIME_FORMAT = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
|
||||
|
||||
private final String[] intervalNames = {"1 sec", "5 sec", "10 sec", "30 sec", "1 min"};
|
||||
private final int[] intervals = {1000, 5000, 10000, 30000, 60000};
|
||||
private final List<VacuumeterViewConnection> views = new ArrayList<>();
|
||||
private TimePlottableGroup plottables;
|
||||
|
||||
@FXML
|
||||
private BorderPane root;
|
||||
@FXML
|
||||
private AnchorPane plotHolder;
|
||||
@FXML
|
||||
private VBox vacBoxHolder;
|
||||
@FXML
|
||||
private Label timeLabel;
|
||||
@FXML
|
||||
private ChoiceBox<String> intervalSelector;
|
||||
@FXML
|
||||
private ToggleButton startStopButton;
|
||||
@FXML
|
||||
private ToggleButton storeButton;
|
||||
@FXML
|
||||
private ToggleButton logButton;
|
||||
|
||||
|
||||
@Override
|
||||
public Node getFXNode() {
|
||||
return root;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the controller class.
|
||||
*/
|
||||
@Override
|
||||
public void initialize(URL url, ResourceBundle rb) {
|
||||
intervalSelector.setItems(FXCollections.observableArrayList(intervalNames));
|
||||
intervalSelector.getSelectionModel().select(1);
|
||||
intervalSelector.getSelectionModel().selectedIndexProperty().addListener((ObservableValue<? extends Number> observable, Number oldValue, Number newValue) -> {
|
||||
if (getDevice() != null) {
|
||||
try {
|
||||
getDevice().setDelay(intervals[newValue.intValue()]);
|
||||
} catch (MeasurementException ex) {
|
||||
evaluateDeviceException(getDevice(), "Failed to restart measurement", null);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
LogFragment logFragment = new LogFragment();
|
||||
new FragmentWindow(logFragment).bindTo(logButton);
|
||||
logFragment.addRootLogHandler();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void evaluateDeviceException(Device device, String message, Throwable exception) {
|
||||
Notifications.create().darkStyle().hideAfter(Duration.seconds(2d)).text(message).showError();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void open(VacCollectorDevice device) {
|
||||
super.open(device);
|
||||
device.getSensors().stream().map((sensor) -> {
|
||||
VacuumeterViewConnection view;
|
||||
if (sensor.hasState("power")) {
|
||||
view = new PoweredVacuumeterViewConnection();
|
||||
} else {
|
||||
view = new VacuumeterViewConnection();
|
||||
}
|
||||
sensor.connect(view, Roles.VIEW_ROLE, Roles.DEVICE_LISTENER_ROLE);
|
||||
return view;
|
||||
}).forEach(views::add);
|
||||
setupView();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyDeviceStateChanged(Device device, String name, Value state) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMeasurementFailed(Measurement measurement, Throwable exception) {
|
||||
LoggerFactory.getLogger(getClass()).debug("Exception during measurement: {}", exception.getMessage());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMeasurementResult(Measurement measurement, Object res, Instant time) {
|
||||
if (plottables != null) {
|
||||
plottables.put(DataPoint.class.cast(res));
|
||||
}
|
||||
Platform.runLater(() -> timeLabel.setText(TIME_FORMAT.format(LocalDateTime.ofInstant(time, ZoneOffset.UTC))));
|
||||
}
|
||||
|
||||
private void setupView() {
|
||||
vacBoxHolder.getChildren().clear();
|
||||
plottables = new TimePlottableGroup();
|
||||
views.forEach((view) -> {
|
||||
vacBoxHolder.getChildren().add(view.getComponent());
|
||||
TimePlottable plot = new TimePlottable(view.getTitle(),
|
||||
view.getDevice().getName());
|
||||
plot.configure(view.getDevice().meta());
|
||||
plottables.add(plot);
|
||||
});
|
||||
plottables.setValue("thickness", 3);
|
||||
plottables.setMaxAge(java.time.Duration.ofHours(3));
|
||||
PlotContainer.anchorTo(plotHolder).setPlot(setupPlot(plottables));
|
||||
}
|
||||
|
||||
private FXPlotFrame setupPlot(TimePlottableGroup plottables) {
|
||||
Meta plotConfig = new MetaBuilder("plotFrame")
|
||||
.setNode(new MetaBuilder("yAxis")
|
||||
.setValue("type", "log")
|
||||
.setValue("axisTitle", "pressure")
|
||||
.setValue("axisUnits", "mbar")
|
||||
)
|
||||
.setValue("xAxis.type", "time");
|
||||
JFreeChartFrame frame = new JFreeChartFrame(plotConfig);
|
||||
frame.addAll(plottables);
|
||||
return frame;
|
||||
}
|
||||
|
||||
private void startMeasurement() throws ControlException {
|
||||
getDevice().startMeasurement();
|
||||
startStopButton.setSelected(true);
|
||||
}
|
||||
|
||||
private void stopMeasurement() {
|
||||
try {
|
||||
getDevice().stopMeasurement(false);
|
||||
for (Sensor sensor : getDevice().getSensors()) {
|
||||
sensor.stopMeasurement(false);
|
||||
}
|
||||
} catch (ControlException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
@FXML
|
||||
private void onStartStopToggle(ActionEvent event) {
|
||||
if (startStopButton.isSelected() != getDevice().isMeasuring()) {
|
||||
//Starting measurement on non-UI thread
|
||||
new Thread(() -> {
|
||||
if (startStopButton.isSelected()) {
|
||||
try {
|
||||
startMeasurement();
|
||||
} catch (ControlException ex) {
|
||||
getDevice().getLogger().error("Failed to start measurement", ex);
|
||||
startStopButton.setSelected(false);
|
||||
}
|
||||
} else {
|
||||
stopMeasurement();
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
}
|
||||
|
||||
@FXML
|
||||
private void onStoreToggle(ActionEvent event) {
|
||||
getDevice().setState("storing", storeButton.isSelected());
|
||||
// if (storeButton.isSelected()) {
|
||||
// //creating storage on UI thread
|
||||
// if (!device.meta().hasMeta("storage")) {
|
||||
// getLogger().info("Storage not defined. Starting storage selection dialog");
|
||||
// DirectoryChooser chooser = new DirectoryChooser();
|
||||
// File storageDir = chooser.showDialog(plotHolder.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().getMeta("storage");
|
||||
// Storage localStorage = StorageManager.buildFrom(device.getContext())
|
||||
// .buildStorage(storageConfig);
|
||||
// //Start storage creation on non-UI thread
|
||||
// new Thread(() -> {
|
||||
// try {
|
||||
//
|
||||
// PointLoader loader;
|
||||
//
|
||||
// if (loaderFactory != null) {
|
||||
// loader = loaderFactory.apply(device, localStorage);
|
||||
// } else {
|
||||
// TableFormatBuilder format = new TableFormatBuilder().setType("timestamp", ValueType.TIME);
|
||||
// device.getSensors().forEach((s) -> {
|
||||
// format.setType(s.getName(), ValueType.NUMBER);
|
||||
// });
|
||||
//
|
||||
// loader = LoaderFactory.buildPointLoder(localStorage, "vactms",
|
||||
// device.meta().getString("storage.shelf", ""), "timestamp", format.build());
|
||||
// }
|
||||
// storageConnection = new LoaderConnection(loader);
|
||||
// device.connect(storageConnection, Roles.STORAGE_ROLE);
|
||||
// } catch (Exception ex) {
|
||||
// getLogger().error("Failed to start data storing", ex);
|
||||
// storeButton.setSelected(false);
|
||||
// }
|
||||
// }).start();
|
||||
// } else if (storageConnection != null) {
|
||||
// device.disconnect(storageConnection);
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,139 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package inr.numass.control.readvac
|
||||
|
||||
import hep.dataforge.control.Connection
|
||||
import hep.dataforge.control.connections.Roles
|
||||
import hep.dataforge.control.devices.Sensor
|
||||
import hep.dataforge.control.measurements.Measurement
|
||||
import hep.dataforge.control.measurements.MeasurementListener
|
||||
import hep.dataforge.fx.fragments.FragmentWindow
|
||||
import hep.dataforge.fx.fragments.LogFragment
|
||||
import hep.dataforge.plots.data.TimePlottable
|
||||
import hep.dataforge.plots.data.TimePlottableGroup
|
||||
import hep.dataforge.values.Value
|
||||
import inr.numass.control.DeviceViewConnection
|
||||
import inr.numass.control.deviceStateToggle
|
||||
import inr.numass.control.plot
|
||||
import javafx.collections.FXCollections
|
||||
import javafx.collections.MapChangeListener
|
||||
import javafx.geometry.Orientation
|
||||
import javafx.scene.control.ScrollPane
|
||||
import javafx.scene.layout.Priority
|
||||
import tornadofx.*
|
||||
import java.time.Instant
|
||||
|
||||
/**
|
||||
* A view controller for Vac collector
|
||||
|
||||
* @author [Alexander Nozik](mailto:altavir@gmail.com)
|
||||
*/
|
||||
class VacCollectorViewConnection : DeviceViewConnection<VacCollectorDevice>() {
|
||||
|
||||
private val table = FXCollections.observableHashMap<String, Double>()
|
||||
|
||||
private val sensorConnection = object : MeasurementListener, Connection{
|
||||
override fun onMeasurementResult(measurement: Measurement<*>, result: Any, time: Instant?) {
|
||||
if(result is Double){
|
||||
table.put(measurement.device.name, result);
|
||||
}
|
||||
}
|
||||
|
||||
override fun onMeasurementFailed(measurement: Measurement<*>?, exception: Throwable?) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private val viewList = FXCollections.observableArrayList<VacViewConnection>();
|
||||
|
||||
override fun buildView(device: VacCollectorDevice): View {
|
||||
return VacCollectorView();
|
||||
}
|
||||
|
||||
override fun open(obj: Any) {
|
||||
super.open(obj)
|
||||
device.sensors.forEach { sensor ->
|
||||
val view = VacViewConnection()
|
||||
sensor.connect(view, Roles.VIEW_ROLE, Roles.DEVICE_LISTENER_ROLE)
|
||||
sensor.connect(sensorConnection, Roles.MEASUREMENT_LISTENER_ROLE);
|
||||
viewList.add(view)
|
||||
}
|
||||
}
|
||||
|
||||
inner class VacCollectorView : View("Numass vacuum view") {
|
||||
|
||||
private val plottables = TimePlottableGroup().apply {
|
||||
viewList.forEach {
|
||||
val plot = TimePlottable(it.getTitle(), it.device.name)
|
||||
plot.configure(it.device.meta())
|
||||
add(plot)
|
||||
}
|
||||
setValue("thickness", 3)
|
||||
}
|
||||
|
||||
private val logWindow = FragmentWindow(LogFragment().apply {
|
||||
addLogHandler(device.logger)
|
||||
})
|
||||
|
||||
override val root = borderpane {
|
||||
top {
|
||||
toolbar {
|
||||
deviceStateToggle(this@VacCollectorViewConnection, Sensor.MEASURING_STATE, "Measure")
|
||||
deviceStateToggle(this@VacCollectorViewConnection, "storing", "Store")
|
||||
pane {
|
||||
hgrow = Priority.ALWAYS
|
||||
}
|
||||
separator(Orientation.VERTICAL)
|
||||
togglebutton("Log") {
|
||||
isSelected = false
|
||||
logWindow.bindTo(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
plot(plottables) {
|
||||
"xAxis.type" to "time"
|
||||
node("yAxis") {
|
||||
"type" to "log"
|
||||
"axisTitle" to "presure"
|
||||
"axisUnits" to "mbar"
|
||||
}
|
||||
}
|
||||
right {
|
||||
scrollpane {
|
||||
hbarPolicy = ScrollPane.ScrollBarPolicy.NEVER
|
||||
vbox {
|
||||
viewList.forEach {
|
||||
add(it.fxNode)
|
||||
separator(Orientation.HORIZONTAL)
|
||||
}
|
||||
}
|
||||
}
|
||||
// listview(viewList) {
|
||||
// cellFormat {
|
||||
// graphic = it.fxNode
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
init {
|
||||
table.addListener { change: MapChangeListener.Change<out String, out Double> ->
|
||||
if (change.wasAdded()) {
|
||||
val pl = plottables.get(change.key)
|
||||
val value = change.valueAdded
|
||||
if (pl != null) {
|
||||
if (value > 0) {
|
||||
pl.put(Value.of(value))
|
||||
} else {
|
||||
pl.put(Value.NULL)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
package inr.numass.control.readvac
|
||||
|
||||
import hep.dataforge.context.Context
|
||||
import hep.dataforge.control.devices.Device
|
||||
import hep.dataforge.control.devices.Sensor
|
||||
import hep.dataforge.control.virtual.VirtualDevice
|
||||
import hep.dataforge.meta.Meta
|
||||
import inr.numass.control.DeviceViewConnection
|
||||
import inr.numass.control.DeviceViewFactory
|
||||
import java.util.stream.Collectors
|
||||
|
||||
/**
|
||||
* A factory for vacuum measurements collector
|
||||
* Created by darksnake on 16-May-17.
|
||||
*/
|
||||
class VacDeviceFactory : DeviceViewFactory<VacCollectorDevice> {
|
||||
override fun getType(): String {
|
||||
return "numass:vac"
|
||||
}
|
||||
|
||||
fun buildSensor(context: Context, sensorConfig: Meta): Sensor<Double> {
|
||||
when (sensorConfig.getString("sensorType", "")) {
|
||||
"mks" -> return MKSVacDevice(context, sensorConfig)
|
||||
"CM32" -> return CM32Device(context, sensorConfig)
|
||||
"meradat" -> return MeradatVacDevice(context, sensorConfig)
|
||||
"baratron" -> return MKSBaratronDevice(context, sensorConfig)
|
||||
VirtualDevice.VIRTUAL_SENSOR_TYPE -> return VirtualDevice.randomDoubleSensor(context, sensorConfig)
|
||||
else -> throw RuntimeException("Unknown vacuum sensor type")
|
||||
}
|
||||
}
|
||||
|
||||
override fun build(context: Context, config: Meta): VacCollectorDevice {
|
||||
val sensors = config.getMetaList("sensor").stream()
|
||||
.map { sensorConfig ->
|
||||
buildSensor(context, sensorConfig)
|
||||
}.collect(Collectors.toList<Sensor<Double>>())
|
||||
|
||||
val collector = VacCollectorDevice(context, config)
|
||||
collector.setSensors(sensors)
|
||||
return collector
|
||||
}
|
||||
|
||||
override fun buildView(device: Device): DeviceViewConnection<VacCollectorDevice> {
|
||||
return VacCollectorViewConnection();
|
||||
}
|
||||
}
|
@ -13,6 +13,7 @@ import hep.dataforge.control.measurements.MeasurementListener
|
||||
import inr.numass.control.DeviceViewConnection
|
||||
import inr.numass.control.switch
|
||||
import javafx.application.Platform
|
||||
import javafx.beans.property.SimpleObjectProperty
|
||||
import javafx.beans.property.SimpleStringProperty
|
||||
import javafx.geometry.Insets
|
||||
import javafx.geometry.Orientation
|
||||
@ -30,7 +31,7 @@ import java.time.format.DateTimeFormatter
|
||||
/**
|
||||
* @author [Alexander Nozik](mailto:altavir@gmail.com)
|
||||
*/
|
||||
open class VacuumeterViewConnection : DeviceViewConnection<Sensor<Double>>(), MeasurementListener {
|
||||
open class VacViewConnection : DeviceViewConnection<Sensor<Double>>(), MeasurementListener {
|
||||
|
||||
val statusProperty = SimpleStringProperty("")
|
||||
var status: String by statusProperty
|
||||
@ -38,8 +39,11 @@ open class VacuumeterViewConnection : DeviceViewConnection<Sensor<Double>>(), Me
|
||||
val valueProperty = SimpleStringProperty("---")
|
||||
var value: String by valueProperty
|
||||
|
||||
val timeProperty = SimpleObjectProperty<Instant>()
|
||||
var time: Instant by timeProperty
|
||||
|
||||
override fun buildView(): View {
|
||||
|
||||
override fun buildView(device: Sensor<Double>): View {
|
||||
return VacView();
|
||||
}
|
||||
|
||||
@ -64,17 +68,23 @@ open class VacuumeterViewConnection : DeviceViewConnection<Sensor<Double>>(), Me
|
||||
}
|
||||
|
||||
override fun onMeasurementResult(measurement: Measurement<*>, res: Any, time: Instant) {
|
||||
val result = Double::class.java.cast(res)
|
||||
val result = Number::class.java.cast(res).toDouble()
|
||||
val resString = FORMAT.format(result)
|
||||
Platform.runLater {
|
||||
value = resString
|
||||
this.time = time
|
||||
status = "OK: " + TIME_FORMAT.format(LocalDateTime.ofInstant(time, ZoneOffset.UTC));
|
||||
}
|
||||
}
|
||||
|
||||
inner class VacView : View("Numass vacuumeter ${device.meta().getString("title", device.name)}") {
|
||||
fun getTitle(): String{
|
||||
return device.meta().getString("title", device.name);
|
||||
}
|
||||
|
||||
inner class VacView : View("Numass vacuumeter ${getTitle()}") {
|
||||
|
||||
override val root = borderpane {
|
||||
minWidth = 90.0
|
||||
style {
|
||||
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<config>
|
||||
<storage path="D:/temp/test"/>
|
||||
<device type="numass:vac">
|
||||
<sensor name="test1" color="red" sensorType="@test" mean="1e-6" sigma="5e-7"/>
|
||||
<sensor name="test2" color="green" sensorType="@test" mean="2e-6" sigma="5e-7"/>
|
||||
<sensor name="test3" color="blue" sensorType="@test" mean="3e-6" sigma="1e-6"/>
|
||||
</device>
|
||||
</config>
|
@ -1,55 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<?import javafx.geometry.Insets?>
|
||||
<?import javafx.scene.control.*?>
|
||||
<?import javafx.scene.layout.*?>
|
||||
<?import org.controlsfx.control.ToggleSwitch?>
|
||||
<?import java.net.URL?>
|
||||
<AnchorPane styleClass="vacBox" xmlns="http://javafx.com/javafx/8.0.112" xmlns:fx="http://javafx.com/fxml/1">
|
||||
<stylesheets>
|
||||
<URL value="@vacstyles.css"/>
|
||||
</stylesheets>
|
||||
<VBox layoutX="50.0" layoutY="6.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0"
|
||||
AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
|
||||
<AnchorPane styleClass="namePane">
|
||||
<Label id="name" fx:id="deviceNameLabel" alignment="CENTER" prefHeight="40.0" text="device Name"
|
||||
AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="50.0"
|
||||
AnchorPane.topAnchor="0.0"/>
|
||||
<ToggleSwitch fx:id="disableButton" alignment="CENTER" layoutX="130.0" layoutY="10.0"
|
||||
prefWidth="40.0" AnchorPane.bottomAnchor="10.0" AnchorPane.rightAnchor="10.0"
|
||||
AnchorPane.topAnchor="10.0"/>
|
||||
</AnchorPane>
|
||||
<Separator/>
|
||||
<BorderPane>
|
||||
<left>
|
||||
<Label id="pressure" fx:id="valueLabel" alignment="CENTER_RIGHT" minWidth="110.0"
|
||||
prefHeight="60.0" text="---" BorderPane.alignment="CENTER">
|
||||
<padding>
|
||||
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0"/>
|
||||
</padding>
|
||||
</Label>
|
||||
</left>
|
||||
<right>
|
||||
<Label id="units" fx:id="unitLabel" prefHeight="60.0" prefWidth="75.0" text="mbar"
|
||||
BorderPane.alignment="CENTER">
|
||||
<padding>
|
||||
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0"/>
|
||||
</padding>
|
||||
</Label>
|
||||
</right>
|
||||
</BorderPane>
|
||||
<Separator/>
|
||||
<Pane minHeight="30.0" prefHeight="30.0" VBox.vgrow="ALWAYS">
|
||||
<ToggleSwitch fx:id="powerSwitch" layoutX="58.0" layoutY="5.0" text="Power"/>
|
||||
</Pane>
|
||||
<Separator/>
|
||||
<AnchorPane styleClass="statusPane">
|
||||
<padding>
|
||||
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0"/>
|
||||
</padding>
|
||||
<Label fx:id="status" maxWidth="200.0" text="Initializing" wrapText="true"
|
||||
AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0"
|
||||
AnchorPane.topAnchor="0.0"/>
|
||||
</AnchorPane>
|
||||
</VBox>
|
||||
</AnchorPane>
|
@ -1,46 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<?import javafx.scene.control.*?>
|
||||
<?import javafx.scene.layout.*?>
|
||||
<?import javafx.scene.text.Font?>
|
||||
<?import java.net.URL?>
|
||||
<BorderPane fx:id="root" prefHeight="600.0" prefWidth="800.0" xmlns="http://javafx.com/javafx/8.0.111" xmlns:fx="http://javafx.com/fxml/1" fx:controller="inr.numass.control.readvac.VacCollectorView">
|
||||
<stylesheets>
|
||||
<URL value="@/fxml/vacstyles.css" />
|
||||
</stylesheets>
|
||||
<right>
|
||||
<ScrollPane fitToHeight="true" fitToWidth="true" hbarPolicy="NEVER" minWidth="250.0" BorderPane.alignment="CENTER">
|
||||
<content>
|
||||
<VBox fx:id="vacBoxHolder" minWidth="200.0" spacing="2.0" />
|
||||
</content>
|
||||
</ScrollPane>
|
||||
</right>
|
||||
<center>
|
||||
<VBox alignment="TOP_CENTER" BorderPane.alignment="CENTER">
|
||||
<ToolBar>
|
||||
<ToggleButton fx:id="startStopButton" mnemonicParsing="false" onAction="#onStartStopToggle" text="Measure" />
|
||||
<ToggleButton fx:id="storeButton" mnemonicParsing="false" onAction="#onStoreToggle" text="Store" />
|
||||
<Separator orientation="VERTICAL" />
|
||||
<Label text="Interval: " />
|
||||
<ChoiceBox fx:id="intervalSelector" prefWidth="150.0" />
|
||||
<Separator orientation="VERTICAL" />
|
||||
<Pane HBox.hgrow="ALWAYS" />
|
||||
<Separator orientation="VERTICAL" />
|
||||
<ToggleButton fx:id="logButton" mnemonicParsing="false" text="Console" />
|
||||
</ToolBar>
|
||||
<AnchorPane fx:id="plotHolder" VBox.vgrow="ALWAYS" />
|
||||
<HBox styleClass="beveled">
|
||||
<Label alignment="CENTER_RIGHT" text="Last update: ">
|
||||
<font>
|
||||
<Font size="24.0" />
|
||||
</font>
|
||||
</Label>
|
||||
<Label fx:id="timeLabel" text="08.02.2016 15:57" HBox.hgrow="ALWAYS">
|
||||
<font>
|
||||
<Font size="24.0" />
|
||||
</font>
|
||||
</Label>
|
||||
</HBox>
|
||||
</VBox>
|
||||
</center>
|
||||
</BorderPane>
|
@ -1,56 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<?import javafx.geometry.Insets?>
|
||||
<?import javafx.scene.control.*?>
|
||||
<?import javafx.scene.layout.*?>
|
||||
<?import org.controlsfx.control.ToggleSwitch?>
|
||||
<?import java.net.URL?>
|
||||
<BorderPane fx:id="root" styleClass="vacBox" xmlns="http://javafx.com/javafx/8.0.40"
|
||||
xmlns:fx="http://javafx.com/fxml/1">
|
||||
<stylesheets>
|
||||
<URL value="@vacstyles.css"/>
|
||||
</stylesheets>
|
||||
<center>
|
||||
<VBox>
|
||||
<AnchorPane styleClass="namePane">
|
||||
<Label id="name" fx:id="deviceNameLabel" alignment="CENTER" prefHeight="40.0" text="device Name"
|
||||
AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="50.0"
|
||||
AnchorPane.topAnchor="0.0"/>
|
||||
<ToggleSwitch fx:id="disableButton" alignment="CENTER" layoutX="140.0" layoutY="20.0"
|
||||
prefWidth="40.0" selected="true" AnchorPane.bottomAnchor="10.0"
|
||||
AnchorPane.rightAnchor="10.0" AnchorPane.topAnchor="10.0"/>
|
||||
</AnchorPane>
|
||||
<Separator/>
|
||||
<BorderPane VBox.vgrow="ALWAYS">
|
||||
<left>
|
||||
<Label id="pressure" fx:id="valueLabel" alignment="CENTER_RIGHT" minWidth="110.0" prefHeight="60.0"
|
||||
text="---" BorderPane.alignment="CENTER">
|
||||
<padding>
|
||||
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0"/>
|
||||
</padding>
|
||||
</Label>
|
||||
</left>
|
||||
<right>
|
||||
<Label id="units" fx:id="unitLabel" prefHeight="60.0" prefWidth="75.0" text="mbar"
|
||||
BorderPane.alignment="CENTER">
|
||||
<padding>
|
||||
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0"/>
|
||||
</padding>
|
||||
</Label>
|
||||
</right>
|
||||
</BorderPane>
|
||||
<Separator/>
|
||||
<AnchorPane styleClass="statusPane">
|
||||
<VBox.margin>
|
||||
<Insets/>
|
||||
</VBox.margin>
|
||||
<padding>
|
||||
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0"/>
|
||||
</padding>
|
||||
<Label fx:id="status" maxWidth="200.0" text="Initializing" wrapText="true"
|
||||
AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0"
|
||||
AnchorPane.topAnchor="0.0"/>
|
||||
</AnchorPane>
|
||||
</VBox>
|
||||
</center>
|
||||
</BorderPane>
|
@ -1,30 +0,0 @@
|
||||
/*
|
||||
* Empty Stylesheet file.
|
||||
*/
|
||||
|
||||
.vacBox {
|
||||
-fx-border-color: blue;
|
||||
}
|
||||
|
||||
.vacBox #pressure{
|
||||
-fx-font-size: 24;
|
||||
-fx-font-weight: bold
|
||||
}
|
||||
|
||||
.vacBox #units{
|
||||
-fx-font-size: 24;
|
||||
}
|
||||
|
||||
.vacBox #name{
|
||||
-fx-font-size: 18;
|
||||
-fx-font-weight: bold
|
||||
}
|
||||
|
||||
.vacBox .namePane{
|
||||
-fx-background-color: lavender
|
||||
}
|
||||
|
||||
.beveled{
|
||||
-fx-border-color: white #676767 #676767 white;
|
||||
-fx-border-style: solid outside line-join bevel;
|
||||
}
|
Loading…
Reference in New Issue
Block a user