Updating control

This commit is contained in:
Alexander Nozik 2018-04-06 10:02:28 +03:00
parent 68fa5c715b
commit 794929890a
6 changed files with 145 additions and 147 deletions

View File

@ -12,14 +12,20 @@ import hep.dataforge.meta.Meta
import hep.dataforge.names.Name import hep.dataforge.names.Name
import hep.dataforge.states.StateDef import hep.dataforge.states.StateDef
import hep.dataforge.values.ValueType import hep.dataforge.values.ValueType
import inr.numass.control.DeviceDisplayFX
import inr.numass.control.DeviceView
import inr.numass.control.getDisplay
import javafx.scene.Parent
import tornadofx.*
import java.util.* import java.util.*
import java.util.stream.Stream import java.util.stream.Stream
import kotlin.collections.ArrayList import kotlin.collections.ArrayList
@StateDef(value = ValueDef(name = "address", type = arrayOf(ValueType.NUMBER), info = "Current active magnet")) @StateDef(value = ValueDef(name = "address", type = arrayOf(ValueType.NUMBER), info = "Current active magnet"))
@DeviceView(LambdaHubDisplay::class)
class LambdaHub(context: Context, meta: Meta) : DeviceHub, AbstractDevice(context, meta) { class LambdaHub(context: Context, meta: Meta) : DeviceHub, AbstractDevice(context, meta) {
private val magnets = ArrayList<LambdaMagnet>(); val magnets = ArrayList<LambdaMagnet>();
private val port: Port = buildPort() private val port: Port = buildPort()
private val controller = LambdaPortController(context, port) private val controller = LambdaPortController(context, port)
@ -60,4 +66,17 @@ class LambdaHub(context: Context, meta: Meta) : DeviceHub, AbstractDevice(contex
override val deviceNames: Stream<Name> override val deviceNames: Stream<Name>
get() = magnets.stream().map { Name.ofSingle(it.name) } get() = magnets.stream().map { Name.ofSingle(it.name) }
}
class LambdaHubDisplay: DeviceDisplayFX<LambdaHub>() {
override fun buildView(device: LambdaHub): UIComponent? {
return object: View() {
override val root: Parent = vbox {
device.magnets.forEach {
this.add(it.getDisplay().view!!)
}
}
}
}
} }

View File

@ -29,6 +29,8 @@ import hep.dataforge.states.StateDefs
import hep.dataforge.states.valueState import hep.dataforge.states.valueState
import hep.dataforge.utils.DateTimeUtils import hep.dataforge.utils.DateTimeUtils
import hep.dataforge.values.ValueType.* import hep.dataforge.values.ValueType.*
import inr.numass.control.DeviceView
import inr.numass.control.magnet.fx.MagnetDisplay
import kotlinx.coroutines.experimental.runBlocking import kotlinx.coroutines.experimental.runBlocking
import java.time.Instant import java.time.Instant
import java.time.temporal.ChronoUnit import java.time.temporal.ChronoUnit
@ -50,8 +52,9 @@ import java.util.concurrent.TimeUnit
StateDef(value = ValueDef(name = "updating", type = arrayOf(BOOLEAN), def = "false", info = "Shows if current ramping in progress"), writable = true), StateDef(value = ValueDef(name = "updating", type = arrayOf(BOOLEAN), def = "false", info = "Shows if current ramping in progress"), writable = true),
StateDef(value = ValueDef(name = "monitoring", type = arrayOf(BOOLEAN), def = "false", info = "Shows if monitoring task is running"), writable = true), StateDef(value = ValueDef(name = "monitoring", type = arrayOf(BOOLEAN), def = "false", info = "Shows if monitoring task is running"), writable = true),
StateDef(value = ValueDef(name = "speed", type = arrayOf(NUMBER), info = "Current change speed in Ampere per minute"), writable = true), StateDef(value = ValueDef(name = "speed", type = arrayOf(NUMBER), info = "Current change speed in Ampere per minute"), writable = true),
StateDef(ValueDef(name = "state", type = [STRING], def = "INIT", enumeration = LambdaMagnet.MagnetState::class, info = "Current state of magnet operation")) StateDef(ValueDef(name = "status", type = [STRING], def = "INIT", enumeration = LambdaMagnet.MagnetStatus::class, info = "Current state of magnet operation"))
) )
@DeviceView(MagnetDisplay::class)
class LambdaMagnet(private val controller: LambdaPortController, meta: Meta) : AbstractDevice(controller.context, meta) { class LambdaMagnet(private val controller: LambdaPortController, meta: Meta) : AbstractDevice(controller.context, meta) {
private var closePortOnShutDown = false private var closePortOnShutDown = false
@ -100,7 +103,7 @@ class LambdaMagnet(private val controller: LambdaPortController, meta: Meta) : A
val output = valueState("output", getter = { controller.talk(address, "OUT?") == "OK" }) { _, value -> val output = valueState("output", getter = { controller.talk(address, "OUT?") == "OK" }) { _, value ->
setOutputMode(value.booleanValue()) setOutputMode(value.booleanValue())
if (!value.booleanValue()) { if (!value.booleanValue()) {
state = MagnetState.OFF status = MagnetStatus.OFF
} }
} }
@ -134,7 +137,7 @@ class LambdaMagnet(private val controller: LambdaPortController, meta: Meta) : A
var speed by valueState("speed").doubleDelegate var speed by valueState("speed").doubleDelegate
var state by valueState("state").enumDelegate<MagnetState>() var status by valueState("status").enumDelegate<MagnetStatus>()
private set private set
/** /**
@ -211,9 +214,9 @@ class LambdaMagnet(private val controller: LambdaPortController, meta: Meta) : A
val nextI = nextI(measuredI, targetI) val nextI = nextI(measuredI, targetI)
if (bound(nextI)) { if (bound(nextI)) {
outCurrent = nextI outCurrent = nextI
state = MagnetState.OK status = MagnetStatus.OK
} else { } else {
state = MagnetState.BOUND status = MagnetStatus.BOUND
} }
} else { } else {
stopUpdateTask() stopUpdateTask()
@ -313,7 +316,7 @@ class LambdaMagnet(private val controller: LambdaPortController, meta: Meta) : A
controller.bound = { i -> Math.abs(this.current.doubleValue - i) <= difference } controller.bound = { i -> Math.abs(this.current.doubleValue - i) <= difference }
} }
enum class MagnetState { enum class MagnetStatus {
INIT, // no information INIT, // no information
OFF, // Magnet output is off OFF, // Magnet output is off
OK, // Magnet ouput is on OK, // Magnet ouput is on

View File

@ -20,13 +20,10 @@ import inr.numass.control.DeviceDisplayFX
import inr.numass.control.magnet.LambdaMagnet import inr.numass.control.magnet.LambdaMagnet
import javafx.application.Platform import javafx.application.Platform
import javafx.beans.value.ObservableValue import javafx.beans.value.ObservableValue
import javafx.fxml.Initializable
import javafx.scene.control.* import javafx.scene.control.*
import javafx.scene.layout.AnchorPane import javafx.scene.layout.AnchorPane
import javafx.scene.paint.Color import javafx.scene.paint.Color
import tornadofx.* import tornadofx.*
import java.net.URL
import java.util.*
/** /**
* FXML Controller class * FXML Controller class
@ -38,42 +35,34 @@ class MagnetDisplay : DeviceDisplayFX<LambdaMagnet>() {
return MagnetControllerComponent(device) return MagnetControllerComponent(device)
} }
val current by lazy { valueBinding(device.voltage) }
val voltage by lazy { valueBinding(device.current) } inner class MagnetControllerComponent(val device: LambdaMagnet) : Fragment() {
var target by device.target.doubleDelegate
var output by device.output.booleanDelegate
var monitoring by device.monitoring.booleanDelegate
var updating by device.updating.booleanDelegate
inner class MagnetControllerComponent(val device: LambdaMagnet) : Fragment(), Initializable {
override val root: AnchorPane by fxml("/fxml/SingleMagnet.fxml") override val root: AnchorPane by fxml("/fxml/SingleMagnet.fxml")
private var showConfirmation = true var showConfirmation = true
val labelI: Label by fxml()
val labelU: Label by fxml()
val targetIField: TextField by fxml()
val magnetName: Label by fxml()
val monitorButton: ToggleButton by fxml()
val statusLabel: Label by fxml()
val setButton: ToggleButton by fxml()
val magnetSpeedField: TextField by fxml()
/** val current = valueBinding(device.voltage)
* Initializes the controller class. val voltage = valueBinding(device.current)
* var target by device.target.doubleDelegate
* @param url var output by device.output.booleanDelegate
* @param rb var monitoring by device.monitoring.booleanDelegate
*/ var updating by device.updating.booleanDelegate
override fun initialize(url: URL, rb: ResourceBundle) { //TODO add status
val labelI: Label by fxid()
val labelU: Label by fxid()
val targetIField: TextField by fxid()
val magnetName: Label by fxid()
val monitorButton: ToggleButton by fxid()
val statusLabel: Label by fxid()
val setButton: ToggleButton by fxid()
val magnetSpeedField: TextField by fxid()
init{
targetIField.textProperty().addListener { observable: ObservableValue<out String>, oldValue: String, newValue: String -> targetIField.textProperty().addListener { observable: ObservableValue<out String>, oldValue: String, newValue: String ->
if (!newValue.matches("\\d*(\\.)?\\d*".toRegex())) { if (!newValue.matches("\\d*(\\.)?\\d*".toRegex())) {
targetIField.text = oldValue targetIField.text = oldValue
@ -129,7 +118,7 @@ class MagnetDisplay : DeviceDisplayFX<LambdaMagnet>() {
setButton.selectedProperty().onChange { setButton.selectedProperty().onChange {
try { try {
setOutput(it) setOutputOn(it)
} catch (ex: PortException) { } catch (ex: PortException) {
displayError(this.device.name, null, ex) displayError(this.device.name, null, ex)
} }
@ -145,12 +134,10 @@ class MagnetDisplay : DeviceDisplayFX<LambdaMagnet>() {
} }
} }
fun setShowConfirmation(showConfirmation: Boolean) {
this.showConfirmation = showConfirmation
}
@Throws(PortException::class) @Throws(PortException::class)
private fun setOutput(outputOn: Boolean) { private fun setOutputOn(outputOn: Boolean) {
if (outputOn) { if (outputOn) {
if (showConfirmation) { if (showConfirmation) {
val alert = Alert(Alert.AlertType.WARNING) val alert = Alert(Alert.AlertType.WARNING)

View File

@ -16,110 +16,98 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
--> -->
<?import javafx.scene.text.*?>
<?import javafx.scene.shape.*?>
<?import javafx.geometry.*?> <?import javafx.geometry.*?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?> <?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?> <?import javafx.scene.layout.*?>
<?import javafx.scene.text.*?>
<fx:root id="SingleMagnetPanel" minHeight="-Infinity" minWidth="-Infinity" prefHeight="175.0" prefWidth="280.0" type="AnchorPane" xmlns="http://javafx.com/javafx/8.0.40" xmlns:fx="http://javafx.com/fxml/1"> <AnchorPane id="SingleMagnetPanel" minHeight="-Infinity" minWidth="-Infinity" prefHeight="175.0" prefWidth="280.0"
<children> xmlns="http://javafx.com/javafx/8.0.40" xmlns:fx="http://javafx.com/fxml/1">
<VBox prefHeight="175.0" prefWidth="270.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0"> <VBox prefHeight="175.0" prefWidth="270.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0"
<children> AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<HBox alignment="CENTER" style="-fx-background-color: LIGHTGREEN;"> <padding>
<children> <Insets bottom="1.0" left="1.0" right="1.0" top="1.0"/>
<Label fx:id="magnetName" alignment="CENTER" contentDisplay="CENTER" layoutX="74.0" prefHeight="28.0" prefWidth="167.0" text="Name"> </padding>
<font> <HBox alignment="CENTER" style="-fx-background-color: LIGHTGREEN;">
<Font name="System Bold" size="18.0" /> <Label fx:id="magnetName" alignment="CENTER" contentDisplay="CENTER" layoutX="74.0" prefHeight="28.0"
</font> prefWidth="167.0" text="Name">
</Label> <font>
</children> <Font name="System Bold" size="18.0"/>
</HBox> </font>
<Separator prefWidth="200.0" /> </Label>
<Pane prefHeight="35.0" prefWidth="250.0"> </HBox>
<children> <Separator prefWidth="200.0"/>
<Label layoutX="14.0" layoutY="8.0" text="Status:"> <Pane prefHeight="35.0" prefWidth="250.0">
<font> <Label layoutX="14.0" layoutY="8.0" text="Status:">
<Font size="14.0" /> <font>
</font> <Font size="14.0"/>
</Label> </font>
<Label fx:id="statusLabel" alignment="CENTER" layoutX="67.0" layoutY="4.0" prefHeight="27.0" prefWidth="80.0" text="INIT" textFill="GRAY"> </Label>
<font> <Label fx:id="statusLabel" alignment="CENTER" layoutX="67.0" layoutY="4.0" prefHeight="27.0"
<Font name="System Bold" size="18.0" /> prefWidth="80.0" text="INIT" textFill="GRAY">
</font> <font>
</Label> <Font name="System Bold" size="18.0"/>
<TextField fx:id="magnetSpeedField" layoutX="173.0" layoutY="4.0" prefHeight="26.0" prefWidth="49.0" /> </font>
<Label layoutX="230.0" layoutY="9.0" text="A/min" /> </Label>
</children> <TextField fx:id="magnetSpeedField" layoutX="173.0" layoutY="4.0" prefHeight="26.0" prefWidth="49.0"/>
<Label layoutX="230.0" layoutY="9.0" text="A/min"/>
</Pane>
<Separator prefWidth="200.0"/>
<HBox prefHeight="50.0" prefWidth="250.0">
<Pane prefHeight="50.0" prefWidth="135.0" style="-fx-border-color: RED; -fx-border-radius: 6;">
<HBox.margin>
<Insets/>
</HBox.margin>
<Label layoutX="14.0" layoutY="13.0" text="I">
<font>
<Font name="System Bold" size="16.0"/>
</font>
</Label>
<Label fx:id="labelI" alignment="CENTER_RIGHT" layoutX="40.0" layoutY="13.0" prefHeight="25.0"
prefWidth="80.0" text="?" textFill="RED">
<font>
<Font name="System Bold" size="16.0"/>
</font>
</Label>
</Pane> </Pane>
<Separator prefWidth="200.0" /> <Separator orientation="VERTICAL" prefHeight="200.0">
<HBox prefHeight="50.0" prefWidth="250.0"> <padding>
<children> <Insets right="1.0"/>
<Pane prefHeight="50.0" prefWidth="135.0" style="-fx-border-color: RED; -fx-border-radius: 6;"> </padding>
<children> </Separator>
<Label layoutX="14.0" layoutY="13.0" text="I"> <Pane layoutX="10.0" layoutY="10.0" prefHeight="50.0" prefWidth="135.0"
<font> style="-fx-border-color: BLUE; -fx-border-radius: 6;">
<Font name="System Bold" size="16.0" /> <HBox.margin>
</font> <Insets/>
</Label> </HBox.margin>
<Label fx:id="labelI" alignment="CENTER_RIGHT" layoutX="40.0" layoutY="13.0" prefHeight="25.0" prefWidth="80.0" text="?" textFill="RED"> <Label layoutX="14.0" layoutY="13.0" text="U">
<font> <font>
<Font name="System Bold" size="16.0" /> <Font name="System Bold" size="16.0"/>
</font> </font>
</Label> </Label>
</children> <Label fx:id="labelU" alignment="CENTER_RIGHT" layoutX="40.0" layoutY="13.0" prefHeight="25.0"
<HBox.margin> prefWidth="80.0" text="?" textAlignment="JUSTIFY" textFill="BLUE">
<Insets /> <font>
</HBox.margin> <Font name="System Bold" size="16.0"/>
</Pane> </font>
<Separator orientation="VERTICAL" prefHeight="200.0"> </Label>
<padding>
<Insets right="1.0" />
</padding>
</Separator>
<Pane layoutX="10.0" layoutY="10.0" prefHeight="50.0" prefWidth="135.0" style="-fx-border-color: BLUE; -fx-border-radius: 6;">
<children>
<Label layoutX="14.0" layoutY="13.0" text="U">
<font>
<Font name="System Bold" size="16.0" />
</font>
</Label>
<Label fx:id="labelU" alignment="CENTER_RIGHT" layoutX="40.0" layoutY="13.0" prefHeight="25.0" prefWidth="80.0" text="?" textAlignment="JUSTIFY" textFill="BLUE">
<font>
<Font name="System Bold" size="16.0" />
</font>
</Label>
</children>
<HBox.margin>
<Insets />
</HBox.margin>
</Pane>
</children>
</HBox>
<Separator prefWidth="200.0" />
<Pane prefHeight="50.0" prefWidth="250.0" style="-fx-border-color: GREEN; -fx-border-radius: 6;">
<children>
<Label layoutX="9.0" layoutY="15.0" text="I target">
<font>
<Font name="System Bold" size="16.0" />
</font>
</Label>
<TextField fx:id="targetIField" layoutX="83.0" layoutY="13.0" prefHeight="25.0" prefWidth="55.0" text="0.0" />
<ToggleButton fx:id="setButton" layoutX="160.0" layoutY="13.0" mnemonicParsing="false" onAction="#onOutToggle" text="Set" />
<ToggleButton fx:id="monitorButton" contentDisplay="RIGHT" layoutX="199.0" layoutY="13.0" mnemonicParsing="false" onAction="#onMonitorToggle" prefHeight="26.0" prefWidth="70.0" text="Monitor" />
</children>
<VBox.margin>
<Insets />
</VBox.margin>
</Pane> </Pane>
<Separator prefWidth="250.0" /> </HBox>
</children> <Separator prefWidth="200.0"/>
<padding> <Pane prefHeight="50.0" prefWidth="250.0" style="-fx-border-color: GREEN; -fx-border-radius: 6;">
<Insets bottom="1.0" left="1.0" right="1.0" top="1.0" /> <VBox.margin>
</padding> <Insets/>
</VBox> </VBox.margin>
</children> <Label layoutX="9.0" layoutY="15.0" text="I target">
</fx:root> <font>
<Font name="System Bold" size="16.0"/>
</font>
</Label>
<TextField fx:id="targetIField" layoutX="83.0" layoutY="13.0" prefHeight="25.0" prefWidth="55.0"
text="0.0"/>
<ToggleButton fx:id="setButton" layoutX="160.0" layoutY="13.0" mnemonicParsing="false" text="Set"/>
<ToggleButton fx:id="monitorButton" contentDisplay="RIGHT" layoutX="199.0" layoutY="13.0"
mnemonicParsing="false" prefHeight="26.0" prefWidth="70.0" text="Monitor"/>
</Pane>
<Separator prefWidth="250.0"/>
</VBox>
</AnchorPane>

View File

@ -72,6 +72,7 @@ abstract class NumassControlApplication<in D : Device> : App() {
try { try {
device?.shutdown() device?.shutdown()
} catch (ex: Exception) { } catch (ex: Exception) {
device?.context?.close()
LoggerFactory.getLogger(javaClass).error("Failed to shutdown application", ex); LoggerFactory.getLogger(javaClass).error("Failed to shutdown application", ex);
} finally { } finally {
super.stop() super.stop()

View File

@ -22,7 +22,7 @@ import java.nio.file.Paths
/** /**
* Created by darksnake on 08-May-17. * Created by darksnake on 08-May-17.
*/ */
val DEFAULT_CONFIG_LOCATION = "./numass-control.xml" const val DEFAULT_CONFIG_LOCATION = "./numass-control.xml"
//val STORING_STATE = "storing" //val STORING_STATE = "storing"
//val dfIcon: Image = Image(Global::class.java.getResourceAsStream("/img/df.png")) //val dfIcon: Image = Image(Global::class.java.getResourceAsStream("/img/df.png"))