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{ plugins{
id "org.jetbrains.kotlin.jvm" version '1.1.2' id "org.jetbrains.kotlin.jvm" version '1.1.2-2'
id "application" id "application"
id 'com.github.johnrengelman.shadow' version '2.0.0' id 'com.github.johnrengelman.shadow' version '2.0.0'
} }
@ -10,7 +10,7 @@ if (!hasProperty('mainClass')) {
mainClassName = mainClass mainClassName = mainClass
version = "0.1.0" version = "0.2.0"
description = "The control room application for numass slow control" description = "The control room application for numass slow control"
@ -20,11 +20,12 @@ dependencies {
compile project(':numass-core') compile project(':numass-core')
compile project(':numass-control') compile project(':numass-control')
compile project(':numass-server') compile project(':numass-server')
compile project(':numass-control:cryotemp')
compile 'org.controlsfx:controlsfx:8.40.12' compile 'org.controlsfx:controlsfx:8.40.12'
compile "no.tornado:tornadofx:1.7.4" 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{ 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 package inr.numass.control
import hep.dataforge.context.Context import hep.dataforge.context.Context
import hep.dataforge.context.Global import hep.dataforge.control.connections.Roles
import hep.dataforge.control.devices.Device import hep.dataforge.control.connections.StorageConnection
import hep.dataforge.meta.Meta import hep.dataforge.meta.Meta
import hep.dataforge.server.ServerManager
import hep.dataforge.storage.api.Storage import hep.dataforge.storage.api.Storage
import hep.dataforge.storage.commons.StorageFactory import hep.dataforge.storage.commons.StorageFactory
import inr.numass.client.ClientUtils import inr.numass.client.ClientUtils
import inr.numass.server.NumassStorageServerObject
import javafx.beans.property.SimpleObjectProperty
import javafx.collections.FXCollections import javafx.collections.FXCollections
import javafx.collections.ObservableList import javafx.collections.ObservableList
import javafx.scene.Node
import tornadofx.* import tornadofx.*
import java.util.*
/** /**
* Created by darksnake on 12-May-17. * Created by darksnake on 12-May-17.
*/ */
class BoardController(val context: Context = Global.instance(), val meta: Meta) : Controller() { class BoardController() : Controller() {
val devices: ObservableList<Pair<Device, Node?>> = FXCollections.observableArrayList<Pair<Device, Node?>>(); private val serviceLoader = ServiceLoader.load(DeviceViewFactory::class.java);
val storage: Storage? by lazy { val devices: ObservableList<DeviceViewConnection<*>> = FXCollections.observableArrayList<DeviceViewConnection<*>>();
if (meta.hasMeta("storage")) {
val numassRun = ClientUtils.getRunName(meta) val storageProperty = SimpleObjectProperty<Storage>()
var storage = StorageFactory.buildStorage(context, meta.getMeta("storage")); var storage by storageProperty
if(! numassRun.isEmpty()){ private set
storage = storage.buildShelf(numassRun, Meta.empty());
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 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.* import tornadofx.*
/** /**
* Created by darksnake on 11-May-17. * Created by darksnake on 11-May-17.
*/ */
class BoardView : View("Numass control board") { class BoardView : View("Numass control board", ImageView(getDFIcon())) {
private var deviceList: VBox by singleAssign();
private val controller: BoardController by inject(); private val controller: BoardController by inject();
override val root = borderpane { override val root = borderpane {
prefHeight = 200.0
prefWidth = 200.0
center { center {
deviceList = vbox { vbox {
bindChildren(controller.devices) { DeviceInfoView(it).root } 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 package inr.numass.control
import hep.dataforge.context.Context
import hep.dataforge.context.Global import hep.dataforge.context.Global
import javafx.scene.Scene import javafx.stage.Stage
import tornadofx.* import tornadofx.*
/** /**
* Created by darksnake on 19-May-17. * 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 { override fun start(stage: Stage) {
if (view is ServerView) { NumassControlUtils.getConfig(this).ifPresent {
view.context = Global.getContext("NUMASS-SERVER") context = Global.getContext("NUMASS-SERVER");
NumassControlUtils.getConfig(this).ifPresent { view.configure(it) } 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"?> <?xml version="1.0" encoding="utf-8"?>
<config> <config>
<server port="8337"/> <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> </config>

View File

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

View File

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

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package inr.numass.cryotemp; package inr.numass.control.cryotemp;
import hep.dataforge.context.Context; import hep.dataforge.context.Context;
import hep.dataforge.control.RoleDef; 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.control.connections.Roles;
import hep.dataforge.fx.fragments.FXFragment; import hep.dataforge.fx.fragments.FXFragment;

View File

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

View File

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package inr.numass.cryotemp; package inr.numass.control.cryotemp;
/** /**
* Created by darksnake on 28-Sep-16. * 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.Measurement;
import hep.dataforge.control.measurements.MeasurementListener; import hep.dataforge.control.measurements.MeasurementListener;
@ -32,7 +32,7 @@ import java.util.ResourceBundle;
*/ */
public class PKT8View extends DeviceViewConnection<PKT8Device> implements Initializable, MeasurementListener { public class PKT8View extends DeviceViewConnection<PKT8Device> implements Initializable, MeasurementListener {
public static PKT8View build(){ public static PKT8View build() {
try { try {
FXMLLoader loader = new FXMLLoader(PKT8View.class.getResource("/fxml/PKT8Indicator.fxml")); FXMLLoader loader = new FXMLLoader(PKT8View.class.getResource("/fxml/PKT8Indicator.fxml"));
loader.load(); loader.load();

View File

@ -3,7 +3,7 @@
* To change this template file, choose Tools | Templates * To change this template file, choose Tools | Templates
* and open the template in the editor. * 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.control.ports.VirtualPort;
import hep.dataforge.meta.Meta; 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.layout.*?>
<?import javafx.scene.text.Font?> <?import javafx.scene.text.Font?>
<BorderPane fx:id="root" xmlns:fx="http://javafx.com/fxml/1" prefHeight="400.0" prefWidth="400.0" <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> <center>
<TableView fx:id="table" BorderPane.alignment="CENTER"> <TableView fx:id="table" BorderPane.alignment="CENTER">
<columns> <columns>

View File

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

View File

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

View File

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

View File

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

View File

@ -58,11 +58,11 @@ import java.util.ResourceBundle;
* *
* @author darksnake * @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 { try {
FXMLLoader loader = new FXMLLoader(MspViewController.class.getResource("/fxml/MspView.fxml")); FXMLLoader loader = new FXMLLoader(MspView.class.getResource("/fxml/MspView.fxml"));
loader.load(); loader.load();
return loader.getController(); return loader.getController();
} catch (IOException e) { } 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.layout.Pane?>
<?import javafx.scene.shape.Circle?> <?import javafx.scene.shape.Circle?>
<?import org.controlsfx.control.ToggleSwitch?> <?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> <top>
<ToolBar prefHeight="50.0" prefWidth="200.0"> <ToolBar prefHeight="50.0" prefWidth="200.0">
<ToggleButton fx:id="connectButton" mnemonicParsing="false" text="Connect" /> <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 * @param state
* @return * @return
*/ */
protected ObjectBinding<Value> getStateBinding(String state) { public ObjectBinding<Value> getStateBinding(String state) {
return bindings.computeIfAbsent(state, stateName -> return bindings.computeIfAbsent(state, stateName ->
new ObjectBinding<Value>() { new ObjectBinding<Value>() {
@Override @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(); primaryStage.show();
device = setupDevice(controller); device = setupDevice(controller);
NumassControlUtils.setDFStageIcon(primaryStage);
setupStage(primaryStage, device); setupStage(primaryStage, device);
NumassControlUtils.setDFStageIcon(primaryStage);
} }
/** /**
@ -52,7 +52,7 @@ public abstract class NumassControlApplication<D extends Device> extends Applica
* *
* @return * @return
*/ */
protected abstract DeviceFactory<D> getDeviceFactory(); protected abstract DeviceFactory getDeviceFactory();
protected abstract void setupStage(Stage stage, D device); protected abstract void setupStage(Stage stage, D device);
@ -68,7 +68,7 @@ public abstract class NumassControlApplication<D extends Device> extends Applica
try { try {
D d = getDeviceFactory().build(ctx, deviceConfig); D d = (D) getDeviceFactory().build(ctx, deviceConfig);
d.init(); d.init();
NumassControlUtils.connectStorage(d, config); NumassControlUtils.connectStorage(d, config);
Platform.runLater(() -> { Platform.runLater(() -> {

View File

@ -106,7 +106,10 @@ public class NumassControlUtils {
} }
public static void setDFStageIcon(Stage stage) { 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 * To change this template file, choose Tools | Templates
* and open the template in the editor. * and open the template in the editor.
*/ */
package inr.numass.readvac; package inr.numass.control.readvac;
import hep.dataforge.context.Context; import hep.dataforge.context.Context;
import hep.dataforge.control.devices.Device; import hep.dataforge.control.devices.Device;

View File

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

View File

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

View File

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

View File

@ -3,7 +3,7 @@
* To change this template file, choose Tools | Templates * To change this template file, choose Tools | Templates
* and open the template in the editor. * and open the template in the editor.
*/ */
package inr.numass.readvac; package inr.numass.control.readvac;
import hep.dataforge.context.Context; import hep.dataforge.context.Context;
import hep.dataforge.control.RoleDef; 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.context.Context;
import hep.dataforge.control.devices.DeviceFactory; import hep.dataforge.control.devices.Device;
import hep.dataforge.control.measurements.Sensor; import hep.dataforge.control.measurements.Sensor;
import hep.dataforge.meta.Meta; 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.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -12,7 +15,7 @@ import java.util.stream.Collectors;
* A factory for vacuum measurements collector * A factory for vacuum measurements collector
* Created by darksnake on 16-May-17. * Created by darksnake on 16-May-17.
*/ */
public class VacDeviceFactory implements DeviceFactory<VacCollectorDevice> { public class VacDeviceFactory implements DeviceViewFactory {
@Override @Override
public String getType() { public String getType() {
return "numass:vac"; return "numass:vac";
@ -42,4 +45,9 @@ public class VacDeviceFactory implements DeviceFactory<VacCollectorDevice> {
collector.setSensors(sensors); collector.setSensors(sensors);
return collector; 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 hep.dataforge.control.measurements.Sensor;
import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.CommandLine;

View File

@ -3,7 +3,7 @@
* To change this template file, choose Tools | Templates * To change this template file, choose Tools | Templates
* and open the template in the editor. * 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.FXML;
import javafx.fxml.FXMLLoader; import javafx.fxml.FXMLLoader;

View File

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

View File

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

View File

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

View File

@ -3,7 +3,7 @@
* To change this template file, choose Tools | Templates * To change this template file, choose Tools | Templates
* and open the template in the editor. * 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.devices.Device;
import hep.dataforge.control.measurements.Measurement; 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.layout.*?>
<?import javafx.scene.text.Font?> <?import javafx.scene.text.Font?>
<?import java.net.URL?> <?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> <stylesheets>
<URL value="@/styles/vacstyles.css" /> <URL value="@/styles/vacstyles.css" />
</stylesheets> </stylesheets>

View File

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

View File

@ -1,19 +1,19 @@
/* /*
* Copyright 2015 Alexander Nozik. * Copyright 2015 Alexander Nozik.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package inr.numass.readvac; package inr.numass.control.readvac;
/** /**
* *

View File

@ -1,19 +1,19 @@
/* /*
* Copyright 2015 Alexander Nozik. * Copyright 2015 Alexander Nozik.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package inr.numass.readvac; package inr.numass.control.readvac;
/** /**
* *

View File

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