Numass control room global update

This commit is contained in:
Alexander Nozik 2017-05-26 22:33:56 +03:00
parent 3987c07040
commit c7e460d43d
50 changed files with 411 additions and 337 deletions

View File

@ -1,5 +1,5 @@
plugins{
id "org.jetbrains.kotlin.jvm" version '1.1.2'
id "org.jetbrains.kotlin.jvm" version '1.1.2-2'
id "application"
id 'com.github.johnrengelman.shadow' version '2.0.0'
}
@ -10,7 +10,7 @@ if (!hasProperty('mainClass')) {
mainClassName = mainClass
version = "0.1.0"
version = "0.2.0"
description = "The control room application for numass slow control"
@ -20,11 +20,12 @@ dependencies {
compile project(':numass-core')
compile project(':numass-control')
compile project(':numass-server')
compile project(':numass-control:cryotemp')
compile 'org.controlsfx:controlsfx:8.40.12'
compile "no.tornado:tornadofx:1.7.4"
compile "org.jetbrains.kotlin:kotlin-stdlib-jre8:1.1.2"
compile "org.jetbrains.kotlin:kotlin-stdlib-jre8"
}
shadowJar{
@ -32,3 +33,12 @@ shadowJar{
}
task debug(dependsOn: classes, type: JavaExec) {
main mainClass
args "--config.resource=/config/server.xml"
classpath = sourceSets.main.runtimeClasspath
description "Start application in debug mode"
group "debug"
}

View File

@ -1,33 +1,90 @@
package inr.numass.control
import hep.dataforge.context.Context
import hep.dataforge.context.Global
import hep.dataforge.control.devices.Device
import hep.dataforge.control.connections.Roles
import hep.dataforge.control.connections.StorageConnection
import hep.dataforge.meta.Meta
import hep.dataforge.server.ServerManager
import hep.dataforge.storage.api.Storage
import hep.dataforge.storage.commons.StorageFactory
import inr.numass.client.ClientUtils
import inr.numass.server.NumassStorageServerObject
import javafx.beans.property.SimpleObjectProperty
import javafx.collections.FXCollections
import javafx.collections.ObservableList
import javafx.scene.Node
import tornadofx.*
import java.util.*
/**
* Created by darksnake on 12-May-17.
*/
class BoardController(val context: Context = Global.instance(), val meta: Meta) : Controller() {
val devices: ObservableList<Pair<Device, Node?>> = FXCollections.observableArrayList<Pair<Device, Node?>>();
class BoardController() : Controller() {
private val serviceLoader = ServiceLoader.load(DeviceViewFactory::class.java);
val storage: Storage? by lazy {
if (meta.hasMeta("storage")) {
val numassRun = ClientUtils.getRunName(meta)
var storage = StorageFactory.buildStorage(context, meta.getMeta("storage"));
if(! numassRun.isEmpty()){
storage = storage.buildShelf(numassRun, Meta.empty());
val devices: ObservableList<DeviceViewConnection<*>> = FXCollections.observableArrayList<DeviceViewConnection<*>>();
val storageProperty = SimpleObjectProperty<Storage>()
var storage by storageProperty
private set
val serverManagerProperty = SimpleObjectProperty<ServerManager>()
var serverManager: ServerManager by serverManagerProperty
private set
fun load(context: Context, meta: Meta) {
devices.clear();
meta.getMetaList("device").forEach {
try {
devices.add(buildDeviceView(context, it));
} catch (ex: Exception) {
context.logger.error("Can't build device view", ex);
}
return@lazy storage;
} else {
return@lazy null;
}
if(meta.hasMeta("storage")){
storage = buildStorage(context, meta);
val storageConnection = StorageConnection(storage);
devices.forEach {
if (it.device.acceptsRole(Roles.STORAGE_ROLE)) {
it.device.connect(storageConnection, Roles.STORAGE_ROLE);
}
}
}
meta.optMeta("server").ifPresent { serverMeta ->
serverManager = context.pluginManager().getOrLoad(ServerManager::class.java);
serverManager.configure(serverMeta)
serverManager.bind(NumassStorageServerObject(serverManager, storage, "numass-storage"));
}
}
private fun buildDeviceView(context: Context, deviceMeta: Meta): DeviceViewConnection<*> {
context.logger.info("Building device with meta: {}", deviceMeta)
val factory = serviceLoader.find {
it.type == deviceMeta.getString("type")
};
if (factory != null) {
val device = factory.build(context, deviceMeta);
val view = factory.buildView(device);
device.connect(view, Roles.VIEW_ROLE, Roles.DEVICE_LISTENER_ROLE)
device.init();
return view;
} else {
throw RuntimeException("Device factory not found");
}
}
private fun buildStorage(context: Context, meta: Meta): Storage {
val storageMeta = meta.getMeta("storage");
context.logger.info("Creating storage for server with meta {}", storageMeta)
var storage = StorageFactory.buildStorage(context, storageMeta);
val numassRun = ClientUtils.getRunName(meta)
if (!numassRun.isEmpty()) {
context.logger.info("Run information found. Selecting run {}", numassRun)
storage = storage.buildShelf(numassRun, Meta.empty());
}
return storage;
}
}

View File

@ -1,21 +1,88 @@
package inr.numass.control
import javafx.scene.layout.VBox
import hep.dataforge.control.devices.Device
import hep.dataforge.fx.fragments.FXFragment
import hep.dataforge.fx.fragments.FragmentWindow
import inr.numass.control.NumassControlUtils.getDFIcon
import javafx.geometry.Orientation
import javafx.geometry.Pos
import javafx.scene.control.Hyperlink
import javafx.scene.image.ImageView
import javafx.scene.layout.Priority
import tornadofx.*
/**
* Created by darksnake on 11-May-17.
*/
class BoardView : View("Numass control board") {
private var deviceList: VBox by singleAssign();
class BoardView : View("Numass control board", ImageView(getDFIcon())) {
private val controller: BoardController by inject();
override val root = borderpane {
prefHeight = 200.0
prefWidth = 200.0
center {
deviceList = vbox {
bindChildren(controller.devices) { DeviceInfoView(it).root }
vbox {
hbox {
alignment = Pos.CENTER
vgrow = Priority.ALWAYS;
prefHeight = 40.0
text("Server") // TODO add fancy style here
separator(Orientation.VERTICAL)
var serverLabel: Hyperlink by singleAssign();
togglebutton("Start") {
isSelected = false
disableProperty().bind(controller.serverManagerProperty.isNull)
action {
if (isSelected) {
text = "Stop"
controller.serverManager.startServer()
serverLabel.text = controller.serverManager.link;
} else {
text = "Start"
controller.serverManager.stopServer()
serverLabel.text = ""
}
}
}
indicator {
bind(controller.serverManager.isStarted)
}
serverLabel = hyperlink {
action {
hostServices.showDocument(controller.serverManager.link);
}
}
}
separator(Orientation.HORIZONTAL)
hbox {
alignment = Pos.CENTER
vgrow = Priority.ALWAYS;
prefHeight = 40.0
text("Storage")
separator(Orientation.VERTICAL)
label(stringBinding(controller.storage) {
controller.storage.fullPath
})
}
separator(Orientation.HORIZONTAL)
vbox {
vgrow = Priority.ALWAYS;
prefHeight = 40.0
bindChildren(controller.devices) { connection ->
hbox {
alignment = Pos.CENTER
vgrow = Priority.ALWAYS;
text("Device: " + connection.device.name)
separator(Orientation.VERTICAL)
indicator {
bind(connection, Device.INITIALIZED_STATE)
}
val viewButton = togglebutton("View")
FragmentWindow(FXFragment.buildFromNode(connection.device.name) { connection.fxNode }).bindTo(viewButton)
}
}
}
}
}
}
}

View File

@ -0,0 +1,82 @@
package inr.numass.control
import hep.dataforge.values.Value
import javafx.beans.value.ObservableValue
import javafx.event.EventTarget
import javafx.scene.paint.Color
import javafx.scene.paint.Paint
import javafx.scene.shape.Circle
import javafx.scene.shape.StrokeType
import tornadofx.*
/**
* A pin like indicator fx node
*/
class Indicator(radius: Double = 10.0) : Circle(radius, Color.GRAY) {
private var binding: ObservableValue<*>? = null;
init {
stroke = Color.BLACK;
strokeType = StrokeType.INSIDE;
tooltip { }
}
/**
* bind this indicator color to given observable
*/
fun <T> bind(observable: ObservableValue<T>, transform: (T) -> Paint) {
if (binding != null) {
throw RuntimeException("Indicator already bound");
} else {
binding = observable;
}
observable.addListener { _, _, value ->
fill = transform(value);
}
}
/**
* bind indicator to the boolean value using default colours
*/
fun bind(booleanValue: ObservableValue<Boolean>) {
bind(booleanValue) {
if (it) {
Color.GREEN;
} else {
Color.RED;
}
}
}
fun unbind() {
this.binding = null;
neutralize();
}
/**
* return indicator to the neutral state but do not unbind
*/
fun neutralize() {
fill = Color.GRAY;
}
}
fun EventTarget.indicator(radius: Double = 10.0, op: (Indicator.() -> Unit)? = null) = opcr(this, Indicator(radius), op)
fun Indicator.bind(connection: DeviceViewConnection<*>, state: String, transform: ((Value) -> Paint)? = null) {
tooltip(state)
if (transform != null) {
bind(connection.getStateBinding(state), transform);
} else {
bind(connection.getStateBinding(state)) {
if (it.isNull) {
Color.GRAY
} else if (it.booleanValue()) {
Color.GREEN;
} else {
Color.RED;
}
}
}
}

View File

@ -1,47 +0,0 @@
package inr.numass.control
import hep.dataforge.control.devices.Device
import hep.dataforge.fx.FXObject
import hep.dataforge.fx.fragments.FXFragment
import hep.dataforge.fx.fragments.FragmentWindow
import javafx.beans.property.SimpleObjectProperty
import javafx.scene.Node
import javafx.scene.control.ToggleButton
import tornadofx.*
/**
* A simple device indicator board
* Created by darksnake on 11-May-17.
*/
class DeviceInfoView(val device: Device, node: Node? = null) : Fragment(device.name) {
constructor(pair: Pair<Device, Node?>) : this(pair.first, pair.second);
val deviceNode = SimpleObjectProperty<Node>();
var viewButton: ToggleButton by singleAssign();
override val root = hbox {
label(device.name)
add(Indicator.build(device, Device.INITIALIZED_STATE).fxNode)
viewButton = togglebutton("View") {
disableProperty().bind(deviceNode.isNull);
}
}
init {
FragmentWindow(FXFragment.buildFromNode(device.name) { deviceNode.get() })
if (node != null) {
deviceNode.set(node);
} else if (device is FXObject) {
deviceNode.set(device.fxNode)
}
}
fun setDeviceView(node: Node) {
deviceNode.set(node);
}
}

View File

@ -1,74 +0,0 @@
package inr.numass.control
import hep.dataforge.control.connections.DeviceConnection
import hep.dataforge.control.devices.Device
import hep.dataforge.control.devices.DeviceListener
import hep.dataforge.fx.FXObject
import hep.dataforge.values.Value
import javafx.beans.binding.ObjectBinding
import javafx.scene.Node
import javafx.scene.paint.Color
import javafx.scene.paint.Paint
import javafx.scene.shape.Circle
/**
* Lamp-like indicator
*
* TODO move to general kotlin FX utils
* Created by darksnake on 12-May-17.
*/
open class Indicator(val state: String) : FXObject, DeviceConnection<Device>(), DeviceListener {
private val color = object : ObjectBinding<Paint>() {
override fun computeValue(): Paint {
val value = device.getState(state);
return compute(value);
}
}
private val indicator = Circle();
init {
indicator.fillProperty().bind(color);
}
protected open fun compute(value: Value): Paint {
if (value.booleanValue()) {
return Color.GREEN;
} else {
return Color.GRAY;
}
}
override fun getFXNode(): Node {
return indicator;
}
override fun notifyDeviceStateChanged(device: Device?, name: String?, value: Value?) {
if (name == state) {
color.invalidate();
}
}
companion object {
/**
* Build an indicator
*/
fun build(device: Device, state: String): Indicator {
val indicator = Indicator(state);
device.connect(indicator);
return indicator;
}
/**
* Build an indicator with the custom color builder
*/
fun build(device: Device, state: String, func: (Value)-> Paint): Indicator {
val indicator = object:Indicator(state){
override fun compute(value: Value): Paint {
return func(value);
}
};
device.connect(indicator);
return indicator;
}
}
}

View File

@ -1,21 +1,31 @@
package inr.numass.control
import hep.dataforge.context.Context
import hep.dataforge.context.Global
import javafx.scene.Scene
import javafx.stage.Stage
import tornadofx.*
/**
* Created by darksnake on 19-May-17.
*/
class ServerApp : App(ServerView::class) {
class ServerApp : App(BoardView::class) {
val controller: BoardController by inject();
var context: Context by singleAssign();
override fun createPrimaryScene(view: UIComponent): Scene {
if (view is ServerView) {
view.context = Global.getContext("NUMASS-SERVER")
NumassControlUtils.getConfig(this).ifPresent { view.configure(it) }
override fun start(stage: Stage) {
NumassControlUtils.getConfig(this).ifPresent {
context = Global.getContext("NUMASS-SERVER");
controller.load(context, it);
}
return super.createPrimaryScene(view)
super.start(stage)
NumassControlUtils.setDFStageIcon(stage)
}
override fun stop() {
controller.devices.forEach {
it.device.shutdown()
}
super.stop()
context.close();
}
}

View File

@ -1,86 +0,0 @@
package inr.numass.control
import hep.dataforge.context.Context
import hep.dataforge.exceptions.StorageException
import hep.dataforge.meta.Meta
import hep.dataforge.server.ServerManager
import hep.dataforge.storage.commons.StorageFactory
import inr.numass.client.ClientUtils
import inr.numass.server.NumassStorageServerObject
import javafx.beans.property.SimpleObjectProperty
import javafx.event.EventHandler
import javafx.scene.control.Hyperlink
import tornadofx.*
/**
* Created by darksnake on 18-May-17.
*/
class ServerView() : View("Numass server controller") {
val contextProperty = SimpleObjectProperty<Context>()
var context by contextProperty
val serverManagerProperty = SimpleObjectProperty<ServerManager>()
var serverManager: ServerManager by serverManagerProperty
var label: Hyperlink by singleAssign();
override val root = borderpane {
center {
hbox {
togglebutton("Server") {
isSelected = false
disableProperty().bind(serverManagerProperty.isNull)
action {
if (isSelected) {
serverManager.startServer()
label.text = serverManager.link;
} else {
serverManager.stopServer()
label.text = ""
}
}
}
label = hyperlink {
action {
hostServices.showDocument(serverManager.link);
}
}
}
}
}
init {
NumassControlUtils.setDFStageIcon(primaryStage)
contextProperty.addListener { _, oldValue, newValue ->
if (oldValue != newValue) {
if (newValue != null) {
serverManager = newValue.pluginManager().getOrLoad(ServerManager::class.java);
} else {
serverManagerProperty.set(null);
}
}
}
primaryStage.onCloseRequest = EventHandler { serverManager.stopServer() }
}
fun configure(meta: Meta) {
meta.optMeta("storage").ifPresent { node ->
context.logger.info("Creating storage for server with meta {}", node)
//building storage in a separate thread
runAsync {
val numassRun = ClientUtils.getRunName(meta)
var storage = StorageFactory.buildStorage(context, node)
if (!numassRun.isEmpty()) {
try {
storage = storage.buildShelf(numassRun, Meta.empty())
} catch (e: StorageException) {
context.logger.error("Failed to build shelf", e)
}
}
serverManager.bind(NumassStorageServerObject(serverManager, storage, "numass-storage"));
}
}
}
}

View File

@ -1,4 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<config>
<server port="8337"/>
<storage path="D:/temp/test"/>
<numass run="serverTest"/>
<device type="numass:pkt8" port = "virtual" abuf = "120">
<!--<connection ip="192.168.111.137" port="4001"/>-->
<channel designation="a" name="a-channel" r0="1000" transformationType="hyperbolic" coefs="[1.0,1.0]"
color="black"/>
<channel designation="b" name="b-channel" r0="1000" transformationType="hyperbolic" coefs="[1.1,1.1]"/>
<channel designation="c" name="c-channel" r0="1000" transformationType="hyperbolic" coefs="[1.2,1.0]"
thickness="2"/>
<channel designation="d" name="d-channel" r0="1000" transformationType="hyperbolic" coefs="[1.3,1.0]"/>
<plotConfig>
<eachPlot thickness="4"/>
<plot name="c-channel" color="magenta"/>
</plotConfig>
</device>
</config>

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package inr.numass.cryotemp;
package inr.numass.control.cryotemp;
import hep.dataforge.control.devices.DeviceFactory;
import hep.dataforge.meta.Meta;
@ -33,7 +33,7 @@ public class PKT8App extends NumassControlApplication<PKT8Device> {
}
@Override
protected DeviceFactory<PKT8Device> getDeviceFactory() {
protected DeviceFactory getDeviceFactory() {
return new PKT8DeviceFactory();
}

View File

@ -14,7 +14,7 @@
* limitations under the License.
*/
package inr.numass.cryotemp;
package inr.numass.control.cryotemp;
import hep.dataforge.meta.Meta;
import hep.dataforge.meta.MetaBuilder;

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package inr.numass.cryotemp;
package inr.numass.control.cryotemp;
import hep.dataforge.context.Context;
import hep.dataforge.control.RoleDef;

View File

@ -0,0 +1,27 @@
package inr.numass.control.cryotemp;
import hep.dataforge.context.Context;
import hep.dataforge.control.devices.Device;
import hep.dataforge.meta.Meta;
import inr.numass.control.DeviceViewConnection;
import inr.numass.control.DeviceViewFactory;
/**
* Created by darksnake on 09-May-17.
*/
public class PKT8DeviceFactory implements DeviceViewFactory {
@Override
public String getType() {
return PKT8Device.PKT8_DEVICE_TYPE;
}
@Override
public PKT8Device build(Context context, Meta meta) {
return new PKT8Device(context, meta);
}
@Override
public DeviceViewConnection buildView(Device device) {
return PKT8View.build();
}
}

View File

@ -1,4 +1,4 @@
package inr.numass.cryotemp;
package inr.numass.control.cryotemp;
import hep.dataforge.control.connections.Roles;
import hep.dataforge.fx.fragments.FXFragment;

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package inr.numass.cryotemp;
package inr.numass.control.cryotemp;
import hep.dataforge.control.measurements.Measurement;
import hep.dataforge.control.measurements.MeasurementListener;

View File

@ -14,7 +14,7 @@
* limitations under the License.
*/
package inr.numass.cryotemp;
package inr.numass.control.cryotemp;
/**
* Created by darksnake on 28-Sep-16.

View File

@ -1,4 +1,4 @@
package inr.numass.cryotemp;
package inr.numass.control.cryotemp;
import hep.dataforge.control.measurements.Measurement;
import hep.dataforge.control.measurements.MeasurementListener;
@ -32,7 +32,7 @@ import java.util.ResourceBundle;
*/
public class PKT8View extends DeviceViewConnection<PKT8Device> implements Initializable, MeasurementListener {
public static PKT8View build(){
public static PKT8View build() {
try {
FXMLLoader loader = new FXMLLoader(PKT8View.class.getResource("/fxml/PKT8Indicator.fxml"));
loader.load();

View File

@ -3,7 +3,7 @@
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package inr.numass.cryotemp;
package inr.numass.control.cryotemp;
import hep.dataforge.control.ports.VirtualPort;
import hep.dataforge.meta.Meta;

View File

@ -1,21 +0,0 @@
package inr.numass.cryotemp;
import hep.dataforge.context.Context;
import hep.dataforge.control.devices.DeviceFactory;
import hep.dataforge.meta.Meta;
/**
* Created by darksnake on 09-May-17.
*/
public class PKT8DeviceFactory implements DeviceFactory<PKT8Device> {
@Override
public String getType() {
return PKT8Device.PKT8_DEVICE_TYPE;
}
@Override
public PKT8Device build(Context context, Meta meta) {
return new PKT8Device(context, meta);
}
}

View File

@ -0,0 +1 @@
inr.numass.control.cryotemp.PKT8DeviceFactory

View File

@ -4,7 +4,7 @@
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.Font?>
<BorderPane fx:id="root" xmlns:fx="http://javafx.com/fxml/1" prefHeight="400.0" prefWidth="400.0"
xmlns="http://javafx.com/javafx/8.0.111" fx:controller="inr.numass.cryotemp.PKT8View">
xmlns="http://javafx.com/javafx/8.0.111" fx:controller="inr.numass.control.cryotemp.PKT8View">
<center>
<TableView fx:id="table" BorderPane.alignment="CENTER">
<columns>

View File

@ -21,7 +21,7 @@ limitations under the License.
<?import javafx.scene.control.ToolBar?>
<?import javafx.scene.layout.*?>
<BorderPane fx:id="root" xmlns:fx="http://javafx.com/fxml/1" prefHeight="600.0" prefWidth="800.0"
xmlns="http://javafx.com/javafx/8.0.111" fx:controller="inr.numass.cryotemp.PKT8PlotView">
xmlns="http://javafx.com/javafx/8.0.111" fx:controller="inr.numass.control.cryotemp.PKT8PlotView">
<center>
<AnchorPane fx:id="plotArea"/>
</center>

View File

@ -343,7 +343,7 @@ public class MspDevice extends SingleMeasurementDevice<MspDevice.PeakJumpMeasure
/**
* The MKS response as two-dimensional array of strings
*/
private static class MspResponse {
static class MspResponse {
private final List<List<String>> data = new ArrayList<>();

View File

@ -1,13 +1,16 @@
package inr.numass.control.msp;
import hep.dataforge.context.Context;
import hep.dataforge.control.devices.DeviceFactory;
import hep.dataforge.control.devices.Device;
import hep.dataforge.meta.Meta;
import inr.numass.control.DeviceViewConnection;
import inr.numass.control.DeviceViewFactory;
import inr.numass.control.msp.fx.MspView;
/**
* Created by darksnake on 09-May-17.
*/
public class MspDeviceFactory implements DeviceFactory<MspDevice> {
public class MspDeviceFactory implements DeviceViewFactory {
@Override
public String getType() {
return MspDevice.MSP_DEVICE_TYPE;
@ -18,4 +21,9 @@ public class MspDeviceFactory implements DeviceFactory<MspDevice> {
MspDevice device = new MspDevice(context,config);
return device;
}
@Override
public DeviceViewConnection buildView(Device device) {
return MspView.build();
}
}

View File

@ -32,7 +32,7 @@ public class MspApp extends NumassControlApplication<MspDevice> {
@Override
protected DeviceViewConnection<MspDevice> buildView() {
return MspViewController.build();
return MspView.build();
}
@Override

View File

@ -58,11 +58,11 @@ import java.util.ResourceBundle;
*
* @author darksnake
*/
public class MspViewController extends DeviceViewConnection<MspDevice> implements DeviceListener, Initializable, NamedValueListener {
public class MspView extends DeviceViewConnection<MspDevice> implements DeviceListener, Initializable, NamedValueListener {
public static MspViewController build() {
public static MspView build() {
try {
FXMLLoader loader = new FXMLLoader(MspViewController.class.getResource("/fxml/MspView.fxml"));
FXMLLoader loader = new FXMLLoader(MspView.class.getResource("/fxml/MspView.fxml"));
loader.load();
return loader.getController();
} catch (IOException e) {

View File

@ -0,0 +1 @@
inr.numass.control.msp.MspDeviceFactory

View File

@ -23,7 +23,7 @@ limitations under the License.
<?import javafx.scene.layout.Pane?>
<?import javafx.scene.shape.Circle?>
<?import org.controlsfx.control.ToggleSwitch?>
<BorderPane fx:id="root" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="400.0" minWidth="600.0" xmlns="http://javafx.com/javafx/8.0.111" xmlns:fx="http://javafx.com/fxml/1" fx:controller="inr.numass.control.msp.fx.MspViewController">
<BorderPane fx:id="root" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="400.0" minWidth="600.0" xmlns="http://javafx.com/javafx/8.0.111" xmlns:fx="http://javafx.com/fxml/1" fx:controller="inr.numass.control.msp.fx.MspView">
<top>
<ToolBar prefHeight="50.0" prefWidth="200.0">
<ToggleButton fx:id="connectButton" mnemonicParsing="false" text="Connect" />

View File

@ -23,7 +23,7 @@ public abstract class DeviceViewConnection<D extends Device> extends DeviceConne
* @param state
* @return
*/
protected ObjectBinding<Value> getStateBinding(String state) {
public ObjectBinding<Value> getStateBinding(String state) {
return bindings.computeIfAbsent(state, stateName ->
new ObjectBinding<Value>() {
@Override

View File

@ -0,0 +1,12 @@
package inr.numass.control;
import hep.dataforge.control.devices.Device;
import hep.dataforge.control.devices.DeviceFactory;
public interface DeviceViewFactory extends DeviceFactory {
/**
* Create but do not connect view connection for the device
* @return
*/
DeviceViewConnection buildView(Device device);
}

View File

@ -36,8 +36,8 @@ public abstract class NumassControlApplication<D extends Device> extends Applica
primaryStage.show();
device = setupDevice(controller);
NumassControlUtils.setDFStageIcon(primaryStage);
setupStage(primaryStage, device);
NumassControlUtils.setDFStageIcon(primaryStage);
}
/**
@ -52,7 +52,7 @@ public abstract class NumassControlApplication<D extends Device> extends Applica
*
* @return
*/
protected abstract DeviceFactory<D> getDeviceFactory();
protected abstract DeviceFactory getDeviceFactory();
protected abstract void setupStage(Stage stage, D device);
@ -68,7 +68,7 @@ public abstract class NumassControlApplication<D extends Device> extends Applica
try {
D d = getDeviceFactory().build(ctx, deviceConfig);
D d = (D) getDeviceFactory().build(ctx, deviceConfig);
d.init();
NumassControlUtils.connectStorage(d, config);
Platform.runLater(() -> {

View File

@ -106,7 +106,10 @@ public class NumassControlUtils {
}
public static void setDFStageIcon(Stage stage) {
stage.getIcons().add(new Image(NumassControlUtils.class.getResourceAsStream("/img/df.png")));
stage.getIcons().add(getDFIcon());
}
public static Image getDFIcon(){
return new Image(NumassControlUtils.class.getResourceAsStream("/img/df.png"));
}
}

View File

@ -3,7 +3,7 @@
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package inr.numass.readvac;
package inr.numass.control.readvac;
import hep.dataforge.context.Context;
import hep.dataforge.control.devices.Device;

View File

@ -3,7 +3,7 @@
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package inr.numass.readvac;
package inr.numass.control.readvac;
import hep.dataforge.context.Context;
import hep.dataforge.control.devices.Device;

View File

@ -3,7 +3,7 @@
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package inr.numass.readvac;
package inr.numass.control.readvac;
import hep.dataforge.context.Context;
import hep.dataforge.control.devices.Device;

View File

@ -3,7 +3,7 @@
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package inr.numass.readvac;
package inr.numass.control.readvac;
import hep.dataforge.context.Context;
import hep.dataforge.control.devices.Device;

View File

@ -3,7 +3,7 @@
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package inr.numass.readvac;
package inr.numass.control.readvac;
import hep.dataforge.context.Context;
import hep.dataforge.control.RoleDef;

View File

@ -1,9 +1,12 @@
package inr.numass.readvac;
package inr.numass.control.readvac;
import hep.dataforge.context.Context;
import hep.dataforge.control.devices.DeviceFactory;
import hep.dataforge.control.devices.Device;
import hep.dataforge.control.measurements.Sensor;
import hep.dataforge.meta.Meta;
import inr.numass.control.DeviceViewConnection;
import inr.numass.control.DeviceViewFactory;
import inr.numass.control.readvac.fx.VacCollectorView;
import java.util.List;
import java.util.stream.Collectors;
@ -12,7 +15,7 @@ import java.util.stream.Collectors;
* A factory for vacuum measurements collector
* Created by darksnake on 16-May-17.
*/
public class VacDeviceFactory implements DeviceFactory<VacCollectorDevice> {
public class VacDeviceFactory implements DeviceViewFactory {
@Override
public String getType() {
return "numass:vac";
@ -42,4 +45,9 @@ public class VacDeviceFactory implements DeviceFactory<VacCollectorDevice> {
collector.setSensors(sensors);
return collector;
}
@Override
public DeviceViewConnection buildView(Device device) {
return VacCollectorView.build();
}
}

View File

@ -1,4 +1,4 @@
package inr.numass.readvac.fx;
package inr.numass.control.readvac.fx;
import hep.dataforge.control.measurements.Sensor;
import org.apache.commons.cli.CommandLine;

View File

@ -3,7 +3,7 @@
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package inr.numass.readvac.fx;
package inr.numass.control.readvac.fx;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;

View File

@ -3,14 +3,14 @@
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package inr.numass.readvac.fx;
package inr.numass.control.readvac.fx;
import hep.dataforge.control.devices.DeviceFactory;
import hep.dataforge.meta.Meta;
import inr.numass.control.DeviceViewConnection;
import inr.numass.control.NumassControlApplication;
import inr.numass.readvac.VacCollectorDevice;
import inr.numass.readvac.VacDeviceFactory;
import inr.numass.control.readvac.VacCollectorDevice;
import inr.numass.control.readvac.VacDeviceFactory;
import javafx.stage.Stage;
import java.util.Objects;

View File

@ -3,12 +3,12 @@
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package inr.numass.readvac.fx;
package inr.numass.control.readvac.fx;
import hep.dataforge.control.connections.Roles;
import hep.dataforge.control.measurements.Sensor;
import hep.dataforge.control.virtual.Virtual;
import inr.numass.readvac.VacCollectorDevice;
import inr.numass.control.readvac.VacCollectorDevice;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;

View File

@ -3,7 +3,7 @@
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package inr.numass.readvac.fx;
package inr.numass.control.readvac.fx;
import hep.dataforge.control.connections.Roles;
import hep.dataforge.control.devices.Device;
@ -24,7 +24,7 @@ import hep.dataforge.plots.jfreechart.JFreeChartFrame;
import hep.dataforge.tables.DataPoint;
import hep.dataforge.values.Value;
import inr.numass.control.DeviceViewConnection;
import inr.numass.readvac.VacCollectorDevice;
import inr.numass.control.readvac.VacCollectorDevice;
import javafx.application.Platform;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;

View File

@ -3,7 +3,7 @@
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package inr.numass.readvac.fx;
package inr.numass.control.readvac.fx;
import hep.dataforge.control.devices.Device;
import hep.dataforge.control.measurements.Measurement;

View File

@ -0,0 +1 @@
inr.numass.control.readvac.VacDeviceFactory

View File

@ -4,7 +4,7 @@
<?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.readvac.fx.VacCollectorView">
<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.fx.VacCollectorView">
<stylesheets>
<URL value="@/styles/vacstyles.css" />
</stylesheets>

View File

@ -1,4 +1,4 @@
package inr.numass.readvac
package inr.numass.control.readvac
import spock.lang.Specification

View File

@ -1,19 +1,19 @@
/*
* 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.readvac;
/*
* 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.readvac;
/**
*

View File

@ -1,19 +1,19 @@
/*
* 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.readvac;
/*
* 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.readvac;
/**
*

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package inr.numass.readvac;
package inr.numass.control.readvac;
import hep.dataforge.utils.DateTimeUtils;