Numass control update
This commit is contained in:
parent
af54525d41
commit
98ef7688d5
@ -16,6 +16,7 @@
|
|||||||
package inr.numass.control.cryotemp
|
package inr.numass.control.cryotemp
|
||||||
|
|
||||||
import hep.dataforge.meta.Meta
|
import hep.dataforge.meta.Meta
|
||||||
|
import hep.dataforge.meta.MetaUtils
|
||||||
import inr.numass.control.NumassControlApplication
|
import inr.numass.control.NumassControlApplication
|
||||||
import javafx.stage.Stage
|
import javafx.stage.Stage
|
||||||
|
|
||||||
@ -32,9 +33,7 @@ class PKT8App : NumassControlApplication<PKT8Device>() {
|
|||||||
stage.minWidth = 400.0
|
stage.minWidth = 400.0
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun acceptDevice(meta: Meta): Boolean {
|
override fun getDeviceMeta(config: Meta): Meta {
|
||||||
return meta.getString("type") == "PKT8"
|
return MetaUtils.findNode(config,"device"){it.getString("name") == "numass.temp"}.orElseThrow{RuntimeException("Temperature measurement configuration not found")}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -274,7 +274,7 @@ class PKT8Device(context: Context, meta: Meta) : PortSensor(context, meta) {
|
|||||||
//send start signal
|
//send start signal
|
||||||
it.send("s")
|
it.send("s")
|
||||||
notifyMeasurementState(MeasurementState.IN_PROGRESS)
|
notifyMeasurementState(MeasurementState.IN_PROGRESS)
|
||||||
} ?: notifyError("Not connected")
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@ apply plugin: 'application'
|
|||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
|
|
||||||
if (!hasProperty('mainClass')) {
|
if (!hasProperty('mainClass')) {
|
||||||
ext.mainClass = 'inr.numass.control.magnet.fx.MagnetControllerApp'
|
ext.mainClass = 'inr.numass.control.magnet.fx.MagnetApp'
|
||||||
}
|
}
|
||||||
mainClassName = mainClass
|
mainClassName = mainClass
|
||||||
|
|
||||||
@ -21,4 +21,12 @@ task talkToServer(type: JavaExec) {
|
|||||||
classpath = sourceSets.main.runtimeClasspath
|
classpath = sourceSets.main.runtimeClasspath
|
||||||
standardInput = System.in
|
standardInput = System.in
|
||||||
standardOutput = System.out
|
standardOutput = System.out
|
||||||
|
}
|
||||||
|
|
||||||
|
task emulate(type: JavaExec){
|
||||||
|
group = "application"
|
||||||
|
main = mainClassName
|
||||||
|
description = "Test magnet controller with virtual device configuration"
|
||||||
|
classpath = sourceSets.main.runtimeClasspath
|
||||||
|
args = ["--config.resource=debug.xml"]
|
||||||
}
|
}
|
@ -26,16 +26,20 @@ class LambdaHub(context: Context, meta: Meta) : DeviceHub, AbstractDevice(contex
|
|||||||
|
|
||||||
init {
|
init {
|
||||||
meta.useEachMeta("magnet") {
|
meta.useEachMeta("magnet") {
|
||||||
magnets.add(LambdaMagnet(context, it, controller))
|
magnets.add(LambdaMagnet(controller, it))
|
||||||
|
}
|
||||||
|
|
||||||
|
meta.useEachMeta("bind") {
|
||||||
|
TODO("add binding")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun buildPort(): Port{
|
private fun buildPort(): Port {
|
||||||
val portName = meta.getString("port");
|
val portMeta = meta.getMetaOrEmpty("port")
|
||||||
return if(portName.startsWith("virtual")){
|
return if(portMeta.getString("type") == "debug"){
|
||||||
VirtualLambdaPort(meta)
|
VirtualLambdaPort(portMeta)
|
||||||
} else{
|
} else{
|
||||||
PortFactory.build(portName);
|
PortFactory.build(portMeta)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@ import hep.dataforge.control.ports.PortFactory
|
|||||||
import hep.dataforge.description.ValueDef
|
import hep.dataforge.description.ValueDef
|
||||||
import hep.dataforge.exceptions.ControlException
|
import hep.dataforge.exceptions.ControlException
|
||||||
import hep.dataforge.exceptions.PortException
|
import hep.dataforge.exceptions.PortException
|
||||||
|
import hep.dataforge.kodex.buildMeta
|
||||||
import hep.dataforge.meta.Meta
|
import hep.dataforge.meta.Meta
|
||||||
import hep.dataforge.states.StateDef
|
import hep.dataforge.states.StateDef
|
||||||
import hep.dataforge.states.StateDefs
|
import hep.dataforge.states.StateDefs
|
||||||
@ -29,9 +30,6 @@ 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 kotlinx.coroutines.experimental.runBlocking
|
import kotlinx.coroutines.experimental.runBlocking
|
||||||
import org.slf4j.LoggerFactory
|
|
||||||
import java.text.DecimalFormat
|
|
||||||
import java.time.Duration
|
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
import java.time.temporal.ChronoUnit
|
import java.time.temporal.ChronoUnit
|
||||||
import java.util.concurrent.Future
|
import java.util.concurrent.Future
|
||||||
@ -41,7 +39,7 @@ import java.util.concurrent.TimeUnit
|
|||||||
/**
|
/**
|
||||||
* @author Polina
|
* @author Polina
|
||||||
*/
|
*/
|
||||||
@ValueDef(name = "timeout", type = [NUMBER], def = "400", info = "A timeout for port response")
|
|
||||||
@StateDefs(
|
@StateDefs(
|
||||||
StateDef(value = ValueDef(name = "current", type = arrayOf(NUMBER), def = "0", info = "Current current")),
|
StateDef(value = ValueDef(name = "current", type = arrayOf(NUMBER), def = "0", info = "Current current")),
|
||||||
StateDef(value = ValueDef(name = "voltage", type = arrayOf(NUMBER), def = "0", info = "Current voltage")),
|
StateDef(value = ValueDef(name = "voltage", type = arrayOf(NUMBER), def = "0", info = "Current voltage")),
|
||||||
@ -51,9 +49,10 @@ import java.util.concurrent.TimeUnit
|
|||||||
StateDef(value = ValueDef(name = "lastUpdate", type = arrayOf(TIME), def = "0", info = "Time of the last update"), writable = true),
|
StateDef(value = ValueDef(name = "lastUpdate", type = arrayOf(TIME), def = "0", info = "Time of the last update"), 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 = "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 Amper 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"))
|
||||||
)
|
)
|
||||||
open class LambdaMagnet(context: Context, meta: Meta, private val controller: LambdaPortController) : AbstractDevice(context, meta) {
|
class LambdaMagnet(private val controller: LambdaPortController, meta: Meta) : AbstractDevice(controller.context, meta) {
|
||||||
|
|
||||||
private var closePortOnShutDown = false
|
private var closePortOnShutDown = false
|
||||||
|
|
||||||
@ -67,25 +66,23 @@ open class LambdaMagnet(context: Context, meta: Meta, private val controller: La
|
|||||||
|
|
||||||
//var listener: MagnetStateListener? = null
|
//var listener: MagnetStateListener? = null
|
||||||
// private volatile double current = 0;
|
// private volatile double current = 0;
|
||||||
private val timeout: Duration = meta.optString("timeout").map<Duration> { Duration.parse(it) }.orElse(Duration.ofMillis(200))
|
|
||||||
private var monitorTask: Future<*>? = null
|
private var monitorTask: Future<*>? = null
|
||||||
private var updateTask: Future<*>? = null
|
private var updateTask: Future<*>? = null
|
||||||
|
|
||||||
var lastUpdate by valueState("lastUpdate", getter = {0}).timeDelegate
|
var lastUpdate by valueState("lastUpdate", getter = { 0 }).timeDelegate
|
||||||
private set
|
private set
|
||||||
|
|
||||||
// read-only values of current output
|
// read-only values of current output
|
||||||
val current = valueState("current", getter = { controller.talk(address, timeout) { s2d(getParameter("MC")) } })
|
val current = valueState("current", getter = { s2d(controller.getParameter(address, "MC")) })
|
||||||
// val current by current.double
|
|
||||||
|
|
||||||
val voltage = valueState("voltage", getter = { controller.talk(address, timeout) { s2d(getParameter("MV")) } })
|
val voltage = valueState("voltage", getter = { s2d(controller.getParameter(address, "MV")) })
|
||||||
// val voltage by voltage.double
|
|
||||||
|
|
||||||
var target = valueState("target")
|
var target = valueState("target")
|
||||||
|
|
||||||
//output values of current and voltage
|
//output values of current and voltage
|
||||||
private var outCurrent by valueState("outCurrent", getter = { controller.talk(address, timeout) { s2d(getParameter("PC")) } }) { _, value ->
|
private var outCurrent by valueState("outCurrent", getter = { s2d(controller.getParameter(address, "PC")) }) { _, value ->
|
||||||
if (setParameter("PC", value.doubleValue())) {
|
if (controller.setParameter(address, "PC", value.doubleValue())) {
|
||||||
lastUpdate = DateTimeUtils.now()
|
lastUpdate = DateTimeUtils.now()
|
||||||
} else {
|
} else {
|
||||||
notifyError("Can't set the target current")
|
notifyError("Can't set the target current")
|
||||||
@ -93,18 +90,21 @@ open class LambdaMagnet(context: Context, meta: Meta, private val controller: La
|
|||||||
return@valueState value
|
return@valueState value
|
||||||
}.doubleDelegate
|
}.doubleDelegate
|
||||||
|
|
||||||
private val outVoltage = valueState("outVoltage", getter = { controller.talk(address, timeout) { s2d(getParameter("PV")) } }) { _, value ->
|
private val outVoltage = valueState("outVoltage", getter = { s2d(controller.getParameter(address, "PV")) }) { _, value ->
|
||||||
if (!setParameter("PV", value.doubleValue())) {
|
if (!controller.setParameter(address, "PV", value.doubleValue())) {
|
||||||
notifyError("Can't set the target voltage")
|
notifyError("Can't set the target voltage")
|
||||||
}
|
}
|
||||||
return@valueState value
|
return@valueState value
|
||||||
}
|
}
|
||||||
|
|
||||||
val output = valueState("output", getter = { controller.talk(address, timeout) { talk("OUT?") == "OK" } }) { _, value ->
|
val output = valueState("output", getter = { controller.talk(address, "OUT?") == "OK" }) { _, value ->
|
||||||
setOutputMode(value.booleanValue())
|
setOutputMode(value.booleanValue())
|
||||||
|
if (!value.booleanValue()) {
|
||||||
|
state = MagnetState.OFF
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var monitoring =valueState("monitoring", getter = { monitorTask != null }) { _, value ->
|
var monitoring = valueState("monitoring", getter = { monitorTask != null }) { _, value ->
|
||||||
if (value.booleanValue()) {
|
if (value.booleanValue()) {
|
||||||
startMonitorTask()
|
startMonitorTask()
|
||||||
} else {
|
} else {
|
||||||
@ -113,6 +113,9 @@ open class LambdaMagnet(context: Context, meta: Meta, private val controller: La
|
|||||||
return@valueState value
|
return@valueState value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
var updating = valueState("updating", getter = { updateTask != null }) { _, value ->
|
var updating = valueState("updating", getter = { updateTask != null }) { _, value ->
|
||||||
if (value.booleanValue()) {
|
if (value.booleanValue()) {
|
||||||
startUpdateTask()
|
startUpdateTask()
|
||||||
@ -124,11 +127,20 @@ open class LambdaMagnet(context: Context, meta: Meta, private val controller: La
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* current change speed in Amper per minute
|
* current change speed in Ampere per minute
|
||||||
*
|
*
|
||||||
* @param speed
|
* @param speed
|
||||||
*/
|
*/
|
||||||
var speed = MAX_SPEED
|
var speed by valueState("speed").doubleDelegate
|
||||||
|
|
||||||
|
|
||||||
|
var state by valueState("state").enumDelegate<MagnetState>()
|
||||||
|
private set
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The binding limit for magnet current
|
||||||
|
*/
|
||||||
|
var bound: (Double) -> Boolean = { it < meta.getDouble("maxCurrent") }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A setup for single magnet controller
|
* A setup for single magnet controller
|
||||||
@ -138,10 +150,12 @@ open class LambdaMagnet(context: Context, meta: Meta, private val controller: La
|
|||||||
* @throws ControlException
|
* @throws ControlException
|
||||||
*/
|
*/
|
||||||
@Throws(ControlException::class)
|
@Throws(ControlException::class)
|
||||||
constructor(context: Context, meta: Meta) : this(context, meta, LambdaPortController(context, PortFactory.build(meta.getString("port")))) {
|
constructor(context: Context, meta: Meta) : this(LambdaPortController(context, PortFactory.build(meta.getString("port"))), meta) {
|
||||||
closePortOnShutDown = true
|
closePortOnShutDown = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
constructor(context: Context, port: Port, address: Int) : this(LambdaPortController(context, port), buildMeta { "address" to address })
|
||||||
|
|
||||||
@Throws(ControlException::class)
|
@Throws(ControlException::class)
|
||||||
override fun init() {
|
override fun init() {
|
||||||
super.init()
|
super.init()
|
||||||
@ -162,46 +176,6 @@ open class LambdaMagnet(context: Context, meta: Meta, private val controller: La
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// private fun reportError(errorMessage: String, error: Throwable?) {
|
|
||||||
// listener?.error(name, errorMessage, error) ?: LoggerFactory.getLogger(javaClass).error(errorMessage, error)
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
|
|
||||||
@Throws(PortException::class)
|
|
||||||
private fun talk(request: String): String {
|
|
||||||
return try {
|
|
||||||
controller.send(request + "\r")
|
|
||||||
controller.waitFor(timeout).trim()
|
|
||||||
} catch (tex: Port.PortTimeoutException) {
|
|
||||||
//Single retry on timeout
|
|
||||||
LoggerFactory.getLogger(javaClass).warn("A timeout exception for request '$request'. Making another attempt.")
|
|
||||||
controller.send(request + "\r")
|
|
||||||
controller.waitFor(timeout).trim()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// private fun update(key: String, value: String) {
|
|
||||||
// when (key) {
|
|
||||||
// "OUT" -> updateState("output", value == "ON")
|
|
||||||
// "MC" -> updateState("current", s2d(value))
|
|
||||||
// "PC" -> updateState("outCurrent", s2d(value))
|
|
||||||
// "MV" -> updateState("voltage", s2d(value))
|
|
||||||
// "PV" -> updateState("outVoltage", s2d(value))
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
@Throws(PortException::class)
|
|
||||||
private fun getParameter(name: String): String = talk("$name?")
|
|
||||||
|
|
||||||
@Throws(PortException::class)
|
|
||||||
private fun setParameter(key: String, state: String): Boolean = "OK" == talk("$key $state")
|
|
||||||
|
|
||||||
@Throws(PortException::class)
|
|
||||||
private fun setParameter(key: String, state: Int): Boolean = setParameter(key, state.toString())
|
|
||||||
|
|
||||||
@Throws(PortException::class)
|
|
||||||
private fun setParameter(key: String, state: Double): Boolean = setParameter(key, d2s(state))
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extract number from LAMBDA response
|
* Extract number from LAMBDA response
|
||||||
*
|
*
|
||||||
@ -232,10 +206,15 @@ open class LambdaMagnet(context: Context, meta: Meta, private val controller: La
|
|||||||
try {
|
try {
|
||||||
val measuredI = current.doubleValue
|
val measuredI = current.doubleValue
|
||||||
val targetI = target.doubleValue
|
val targetI = target.doubleValue
|
||||||
updateState("current",measuredI)
|
updateState("current", measuredI)
|
||||||
if (Math.abs(measuredI - targetI) > CURRENT_PRECISION) {
|
if (Math.abs(measuredI - targetI) > CURRENT_PRECISION) {
|
||||||
val nextI = nextI(measuredI, targetI)
|
val nextI = nextI(measuredI, targetI)
|
||||||
outCurrent = nextI
|
if (bound(nextI)) {
|
||||||
|
outCurrent = nextI
|
||||||
|
state = MagnetState.OK
|
||||||
|
} else {
|
||||||
|
state = MagnetState.BOUND
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
stopUpdateTask()
|
stopUpdateTask()
|
||||||
}
|
}
|
||||||
@ -253,7 +232,7 @@ open class LambdaMagnet(context: Context, meta: Meta, private val controller: La
|
|||||||
@Throws(PortException::class)
|
@Throws(PortException::class)
|
||||||
private fun setOutputMode(out: Boolean) {
|
private fun setOutputMode(out: Boolean) {
|
||||||
val outState: Int = if (out) 1 else 0
|
val outState: Int = if (out) 1 else 0
|
||||||
if (!setParameter("OUT", outState)) {
|
if (!controller.setParameter(address, "OUT", outState)) {
|
||||||
notifyError("Can't set output mode")
|
notifyError("Can't set output mode")
|
||||||
} else {
|
} else {
|
||||||
updateState("output", out)
|
updateState("output", out)
|
||||||
@ -261,7 +240,6 @@ open class LambdaMagnet(context: Context, meta: Meta, private val controller: La
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun nextI(measuredI: Double, targetI: Double): Double {
|
private fun nextI(measuredI: Double, targetI: Double): Double {
|
||||||
// assert(measuredI != target)
|
|
||||||
|
|
||||||
var step = if (lastUpdate == Instant.EPOCH) {
|
var step = if (lastUpdate == Instant.EPOCH) {
|
||||||
MIN_UP_STEP_SIZE
|
MIN_UP_STEP_SIZE
|
||||||
@ -325,9 +303,26 @@ open class LambdaMagnet(context: Context, meta: Meta, private val controller: La
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add symmetric non-blocking conditions to ensure currents in two magnets have difference within given value.
|
||||||
|
* @param controller
|
||||||
|
* @param difference
|
||||||
|
*/
|
||||||
|
fun bindTo(controller: LambdaMagnet, difference: Double) {
|
||||||
|
this.bound = { i -> Math.abs(controller.current.doubleValue - i) <= difference }
|
||||||
|
controller.bound = { i -> Math.abs(this.current.doubleValue - i) <= difference }
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class MagnetState {
|
||||||
|
INIT, // no information
|
||||||
|
OFF, // Magnet output is off
|
||||||
|
OK, // Magnet ouput is on
|
||||||
|
ERROR, // Some error
|
||||||
|
BOUND // Magnet in bound mode
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
private val LAMBDA_FORMAT = DecimalFormat("###.##")
|
|
||||||
const val CURRENT_PRECISION = 0.05
|
const val CURRENT_PRECISION = 0.05
|
||||||
const val DEFAULT_DELAY = 1
|
const val DEFAULT_DELAY = 1
|
||||||
const val DEFAULT_MONITOR_DELAY = 2000
|
const val DEFAULT_MONITOR_DELAY = 2000
|
||||||
@ -336,13 +331,6 @@ open class LambdaMagnet(context: Context, meta: Meta, private val controller: La
|
|||||||
const val MIN_DOWN_STEP_SIZE = 0.05
|
const val MIN_DOWN_STEP_SIZE = 0.05
|
||||||
const val MAX_SPEED = 5.0 // 5 A per minute
|
const val MAX_SPEED = 5.0 // 5 A per minute
|
||||||
|
|
||||||
/**
|
|
||||||
* Method converts double to LAMBDA string
|
|
||||||
*
|
|
||||||
* @param d double that should be converted to string
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
private fun d2s(d: Double): String = LAMBDA_FORMAT.format(d)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,11 +3,17 @@ package inr.numass.control.magnet
|
|||||||
import hep.dataforge.context.Context
|
import hep.dataforge.context.Context
|
||||||
import hep.dataforge.control.ports.GenericPortController
|
import hep.dataforge.control.ports.GenericPortController
|
||||||
import hep.dataforge.control.ports.Port
|
import hep.dataforge.control.ports.Port
|
||||||
|
import hep.dataforge.exceptions.PortException
|
||||||
|
import org.slf4j.LoggerFactory
|
||||||
|
import java.text.DecimalFormat
|
||||||
import java.time.Duration
|
import java.time.Duration
|
||||||
|
|
||||||
|
//@ValueDef(name = "timeout", type = [(ValueType.NUMBER)], def = "400", info = "A timeout for port response")
|
||||||
class LambdaPortController(context: Context, port: Port) : GenericPortController(context, port) {
|
class LambdaPortController(context: Context, port: Port) : GenericPortController(context, port) {
|
||||||
private var currentAddress: Int = -1;
|
private var currentAddress: Int = -1;
|
||||||
|
|
||||||
|
private val timeout: Duration = port.meta.optString("timeout").map<Duration> { Duration.parse(it) }.orElse(Duration.ofMillis(200))
|
||||||
|
|
||||||
private fun setAddress(address: Int, timeout: Duration) {
|
private fun setAddress(address: Int, timeout: Duration) {
|
||||||
val response = sendAndWait("ADR $address\r", timeout) { true }.trim()
|
val response = sendAndWait("ADR $address\r", timeout) { true }.trim()
|
||||||
if (response == "OK") {
|
if (response == "OK") {
|
||||||
@ -20,10 +26,47 @@ class LambdaPortController(context: Context, port: Port) : GenericPortController
|
|||||||
/**
|
/**
|
||||||
* perform series of synchronous actions ensuring that all of them have the same address
|
* perform series of synchronous actions ensuring that all of them have the same address
|
||||||
*/
|
*/
|
||||||
fun <R> talk(address: Int, timeout: Duration, action: (GenericPortController) -> R): R {
|
private fun <R> talk(address: Int, action: GenericPortController.() -> R): R {
|
||||||
synchronized(this) {
|
synchronized(this) {
|
||||||
setAddress(address, timeout)
|
setAddress(address, timeout)
|
||||||
return action(this)
|
return this.action()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Throws(PortException::class)
|
||||||
|
fun talk(addres: Int, request: String): String {
|
||||||
|
return talk(addres) {
|
||||||
|
try {
|
||||||
|
send(request + "\r")
|
||||||
|
waitFor(timeout).trim()
|
||||||
|
} catch (tex: Port.PortTimeoutException) {
|
||||||
|
//Single retry on timeout
|
||||||
|
LoggerFactory.getLogger(javaClass).warn("A timeout exception for request '$request'. Making another attempt.")
|
||||||
|
send(request + "\r")
|
||||||
|
waitFor(timeout).trim()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getParameter(address: Int, name: String): String = talk(address, "$name?")
|
||||||
|
|
||||||
|
fun setParameter(address: Int, key: String, state: String): Boolean = "OK" == talk(address, "$key $state")
|
||||||
|
|
||||||
|
fun setParameter(address: Int, key: String, state: Int): Boolean = setParameter(address, key, state.toString())
|
||||||
|
|
||||||
|
fun setParameter(address: Int, key: String, state: Double): Boolean = setParameter(address, key, d2s(state))
|
||||||
|
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val LAMBDA_FORMAT = DecimalFormat("###.##")
|
||||||
|
/**
|
||||||
|
* Method converts double to LAMBDA string
|
||||||
|
*
|
||||||
|
* @param d double that should be converted to string
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
private fun d2s(d: Double): String = LAMBDA_FORMAT.format(d)
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,54 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2015 Alexander Nozik.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package inr.numass.control.magnet
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author Alexander Nozik
|
|
||||||
*/
|
|
||||||
interface MagnetStateListener {
|
|
||||||
|
|
||||||
fun acceptStatus(name: String, state: MagnetStatus)
|
|
||||||
|
|
||||||
fun acceptNextI(name: String, nextI: Double)
|
|
||||||
|
|
||||||
fun acceptMeasuredI(name: String, measuredI: Double)
|
|
||||||
|
|
||||||
open fun displayState(state: String) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
open fun error(name: String, errorMessage: String, throwable: Throwable?) {
|
|
||||||
throw RuntimeException(errorMessage, throwable)
|
|
||||||
}
|
|
||||||
|
|
||||||
open fun monitorTaskStateChanged(name: String, monitorTaskRunning: Boolean) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
open fun updateTaskStateChanged(name: String, updateTaskRunning: Boolean) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
open fun outputModeChanged(name: String, out: Boolean) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
fun addressChanged(name: String, address: Int) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,63 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2015 Alexander Nozik.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package inr.numass.control.magnet
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author Polina
|
|
||||||
*/
|
|
||||||
class MagnetStatus(
|
|
||||||
/**
|
|
||||||
* @return the isOut
|
|
||||||
*/
|
|
||||||
val isOutputOn: Boolean,
|
|
||||||
/**
|
|
||||||
* @return the measuredCurrent
|
|
||||||
*/
|
|
||||||
val measuredCurrent: Double,
|
|
||||||
/**
|
|
||||||
* @return the setCurrent
|
|
||||||
*/
|
|
||||||
val setCurrent: Double,
|
|
||||||
/**
|
|
||||||
* @return the measuredVoltage
|
|
||||||
*/
|
|
||||||
val measuredVoltage: Double,
|
|
||||||
/**
|
|
||||||
* @return the setVoltage
|
|
||||||
*/
|
|
||||||
val setVoltage: Double) {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the isOn
|
|
||||||
*/
|
|
||||||
var isOn: Boolean = false
|
|
||||||
private set
|
|
||||||
|
|
||||||
init {
|
|
||||||
this.isOn = true
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
|
|
||||||
fun off(): MagnetStatus {
|
|
||||||
val res = MagnetStatus(false, 0.0, 0.0, 0.0, 0.0)
|
|
||||||
res.isOn = false
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,90 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2015 Alexander Nozik.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package inr.numass.control.magnet
|
|
||||||
|
|
||||||
import hep.dataforge.context.Context
|
|
||||||
import hep.dataforge.exceptions.PortException
|
|
||||||
import hep.dataforge.meta.Meta
|
|
||||||
import org.slf4j.LoggerFactory
|
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author Polina
|
|
||||||
*/
|
|
||||||
class SafeLambdaMagnet(context: Context, meta: Meta, controller: LambdaPortController) :
|
|
||||||
LambdaMagnet(context, meta, controller) {
|
|
||||||
|
|
||||||
private val safeConditions = HashSet<SafeMagnetCondition>()
|
|
||||||
|
|
||||||
// public SafeLambdaMagnet(String name, Port port, int address, int timeout, SafeMagnetCondition... safeConditions) {
|
|
||||||
// super(name, port, address, timeout);
|
|
||||||
// this.safeConditions.addAll(Arrays.asList(safeConditions));
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// public SafeLambdaMagnet(String name, Port port, int address, SafeMagnetCondition... safeConditions) {
|
|
||||||
// super(name, port, address);
|
|
||||||
// this.safeConditions.addAll(Arrays.asList(safeConditions));
|
|
||||||
// }
|
|
||||||
|
|
||||||
fun addSafeCondition(isBlocking: Boolean, condition: (Double) -> Boolean) {
|
|
||||||
this.safeConditions.add(object : SafeMagnetCondition {
|
|
||||||
|
|
||||||
override fun isBlocking(): Boolean = isBlocking
|
|
||||||
|
|
||||||
override fun isSafe(address: Int, current: Double): Boolean = condition(current)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add symmetric non-blocking conditions to ensure currents in two magnets have difference within given tolerance.
|
|
||||||
* @param controller
|
|
||||||
* @param tolerance
|
|
||||||
*/
|
|
||||||
fun bindTo(controller: SafeLambdaMagnet, tolerance: Double) {
|
|
||||||
this.addSafeCondition(false) { I -> Math.abs(controller.current - I) <= tolerance }
|
|
||||||
controller.addSafeCondition(false) { I -> Math.abs(this.current - I) <= tolerance }
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Throws(PortException::class)
|
|
||||||
override fun setCurrent(current: Double) {
|
|
||||||
safeConditions
|
|
||||||
.filterNot { it.isSafe(address, current) }
|
|
||||||
.forEach {
|
|
||||||
if (it.isBlocking()) {
|
|
||||||
it.onFail()
|
|
||||||
throw RuntimeException("Can't set current. Condition not satisfied.")
|
|
||||||
} else {
|
|
||||||
listener?.displayState("BOUND")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
super.current = current
|
|
||||||
}
|
|
||||||
|
|
||||||
interface SafeMagnetCondition {
|
|
||||||
|
|
||||||
fun isBlocking(): Boolean = true
|
|
||||||
|
|
||||||
fun isSafe(address: Int, current: Double): Boolean
|
|
||||||
|
|
||||||
fun onFail() {
|
|
||||||
LoggerFactory.getLogger(javaClass).error("Can't set current. Condition not satisfied.")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,90 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2015 Alexander Nozik.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package inr.numass.control.magnet
|
|
||||||
|
|
||||||
import hep.dataforge.control.ports.Port
|
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author Alexander Nozik
|
|
||||||
*/
|
|
||||||
object TestController {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param args the command line arguments
|
|
||||||
* @throws java.lang.Exception
|
|
||||||
*/
|
|
||||||
@Throws(Exception::class)
|
|
||||||
@JvmStatic
|
|
||||||
fun main(args: Array<String>) {
|
|
||||||
Locale.setDefault(Locale.US)// чтобы отделение десятичных знаков было точкой
|
|
||||||
// ch.qos.logback.classic.Logger rootLogger = (ch.qos.logback.classic.Logger) LoggerFactory.getLogger(ch.qos.logback.classic.Logger.ROOT_LOGGER_NAME);
|
|
||||||
// rootLogger.setLevel(Level.INFO);
|
|
||||||
|
|
||||||
val handler: Port
|
|
||||||
val firstController: LambdaMagnet
|
|
||||||
val secondController: LambdaMagnet
|
|
||||||
|
|
||||||
// String comName = "COM12";
|
|
||||||
// handler = new ComPort(comName);
|
|
||||||
handler = VirtualLambdaPort("COM12", 1, 2, 3, 4)
|
|
||||||
|
|
||||||
firstController = LambdaMagnet(handler, 1)
|
|
||||||
// secondController = new LambdaMagnet(handler, 4);
|
|
||||||
secondController = SafeLambdaMagnet("TEST", handler, 4, { address: Int, current: Double -> current < 1.0 })
|
|
||||||
|
|
||||||
val listener = object : MagnetStateListener {
|
|
||||||
|
|
||||||
override fun acceptStatus(name: String, state: MagnetStatus) {
|
|
||||||
System.out.printf("%s (%s): Im = %f, Um = %f, Is = %f, Us = %f;%n",
|
|
||||||
name,
|
|
||||||
state.isOutputOn,
|
|
||||||
state.measuredCurrent,
|
|
||||||
state.measuredVoltage,
|
|
||||||
state.setCurrent,
|
|
||||||
state.setVoltage
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun acceptNextI(name: String, nextI: Double) {
|
|
||||||
System.out.printf("%s: nextI = %f;%n", name, nextI)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun acceptMeasuredI(name: String, measuredI: Double) {
|
|
||||||
System.out.printf("%s: measuredI = %f;%n", name, measuredI)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
firstController.listener = listener
|
|
||||||
secondController.listener = listener
|
|
||||||
|
|
||||||
try {
|
|
||||||
firstController.startMonitorTask(2000)
|
|
||||||
secondController.startMonitorTask(2000)
|
|
||||||
secondController.setOutputMode(true)
|
|
||||||
secondController.startUpdateTask(2.0, 1000)
|
|
||||||
System.`in`.read()
|
|
||||||
firstController.stopMonitorTask()
|
|
||||||
secondController.stopMonitorTask()
|
|
||||||
secondController.stopUpdateTask()
|
|
||||||
secondController.setOutputMode(false)
|
|
||||||
} finally {
|
|
||||||
// handler.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,114 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2015 Alexander Nozik.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package inr.numass.control.magnet
|
|
||||||
|
|
||||||
import ch.qos.logback.classic.Level
|
|
||||||
import hep.dataforge.control.ports.Port
|
|
||||||
import org.slf4j.LoggerFactory
|
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author Alexander Nozik
|
|
||||||
*/
|
|
||||||
object TestSynch {
|
|
||||||
|
|
||||||
private val firstCurrent = 0.0
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param args the command line arguments
|
|
||||||
* @throws java.lang.Exception
|
|
||||||
*/
|
|
||||||
@Throws(Exception::class)
|
|
||||||
@JvmStatic
|
|
||||||
fun main(args: Array<String>) {
|
|
||||||
Locale.setDefault(Locale.US)// чтобы отделение десятичных знаков было точкой
|
|
||||||
val rootLogger = LoggerFactory.getLogger(ch.qos.logback.classic.Logger.ROOT_LOGGER_NAME) as ch.qos.logback.classic.Logger
|
|
||||||
rootLogger.level = Level.INFO
|
|
||||||
|
|
||||||
val handler: Port
|
|
||||||
val firstController: LambdaMagnet
|
|
||||||
val secondController: LambdaMagnet
|
|
||||||
|
|
||||||
// String comName = "COM12";
|
|
||||||
// handler = new ComPort(comName);
|
|
||||||
handler = VirtualLambdaPort("COM12", 1, 2, 3, 4)
|
|
||||||
|
|
||||||
firstController = LambdaMagnet(handler, 1)
|
|
||||||
// secondController = new LambdaMagnet(handler, 2);
|
|
||||||
secondController = SafeLambdaMagnet("TEST", handler, 2,
|
|
||||||
object : SafeLambdaMagnet.SafeMagnetCondition {
|
|
||||||
|
|
||||||
// @Override
|
|
||||||
// public boolean isBlocking() {
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
override fun onFail() {
|
|
||||||
java.awt.Toolkit.getDefaultToolkit().beep()
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun isSafe(address: Int, current: Double): Boolean {
|
|
||||||
return Math.abs(current - firstCurrent) <= 0.2
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
val listener = object : MagnetStateListener {
|
|
||||||
|
|
||||||
override fun acceptStatus(name: String, state: MagnetStatus) {
|
|
||||||
System.out.printf("%s (%s): Im = %f, Um = %f, Is = %f, Us = %f;%n",
|
|
||||||
name,
|
|
||||||
state.isOutputOn,
|
|
||||||
state.measuredCurrent,
|
|
||||||
state.measuredVoltage,
|
|
||||||
state.setCurrent,
|
|
||||||
state.setVoltage
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun acceptNextI(name: String, nextI: Double) {
|
|
||||||
System.out.printf("%s: nextI = %f;%n", name, nextI)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun acceptMeasuredI(name: String, measuredI: Double) {
|
|
||||||
System.out.printf("%s: measuredI = %f;%n", name, measuredI)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
firstController.listener = listener
|
|
||||||
secondController.listener = listener
|
|
||||||
|
|
||||||
try {
|
|
||||||
firstController.startMonitorTask(2000)
|
|
||||||
secondController.startMonitorTask(2000)
|
|
||||||
secondController.setOutputMode(true)
|
|
||||||
firstController.setOutputMode(true)
|
|
||||||
firstController.startUpdateTask(1.0, 10)
|
|
||||||
secondController.startUpdateTask(2.0, 10)
|
|
||||||
System.`in`.read()
|
|
||||||
firstController.stopMonitorTask()
|
|
||||||
secondController.stopMonitorTask()
|
|
||||||
secondController.stopUpdateTask()
|
|
||||||
firstController.stopUpdateTask()
|
|
||||||
secondController.setOutputMode(false)
|
|
||||||
firstController.setOutputMode(false)
|
|
||||||
System.exit(0)
|
|
||||||
} finally {
|
|
||||||
// handler.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -16,7 +16,7 @@
|
|||||||
package inr.numass.control.magnet
|
package inr.numass.control.magnet
|
||||||
|
|
||||||
import hep.dataforge.control.ports.VirtualPort
|
import hep.dataforge.control.ports.VirtualPort
|
||||||
import hep.dataforge.exceptions.PortException
|
import hep.dataforge.kodex.useEachMeta
|
||||||
import hep.dataforge.meta.Meta
|
import hep.dataforge.meta.Meta
|
||||||
import org.slf4j.LoggerFactory
|
import org.slf4j.LoggerFactory
|
||||||
import java.time.Duration
|
import java.time.Duration
|
||||||
@ -30,29 +30,17 @@ class VirtualLambdaPort(meta: Meta) : VirtualPort(meta) {
|
|||||||
|
|
||||||
@Volatile private var currentAddress = -1
|
@Volatile private var currentAddress = -1
|
||||||
private val magnets = HashMap<Int, VirtualMagnetStatus>()
|
private val magnets = HashMap<Int, VirtualMagnetStatus>()
|
||||||
private val virtualPortName: String = meta.getString("name", "virtual::numass.lambda")
|
override val name: String = meta.getString("name", "virtual::numass.lambda")
|
||||||
|
|
||||||
// constructor(portName: String, magnets: Map<Int, Double>) {
|
|
||||||
// this.virtualPortName = portName
|
|
||||||
// magnets.forEach { key, value -> this.magnets.put(key, VirtualMagnetStatus(value)) }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// constructor(portName: String, vararg magnets: Int) {
|
|
||||||
// this.virtualPortName = portName
|
|
||||||
// for (magnet in magnets) {
|
|
||||||
// this.magnets.put(magnet, VirtualMagnetStatus(0.01))
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
init {
|
init {
|
||||||
meta.useEachMeta("magnet") {
|
meta.useEachMeta("magnet") {
|
||||||
val num = it.getInt("address", 1)
|
val num = it.getInt("address", 1)
|
||||||
val resistance = it.getDouble("resistance", 1.0)
|
val resistance = it.getDouble("resistance", 1.0)
|
||||||
magnets.put(num, VirtualMagnetStatus(resistance))
|
magnets[num] = VirtualMagnetStatus(resistance)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun toString(): String = virtualPortName
|
override fun toString(): String = name
|
||||||
|
|
||||||
override fun evaluateRequest(request: String) {
|
override fun evaluateRequest(request: String) {
|
||||||
val command: String
|
val command: String
|
||||||
@ -67,8 +55,7 @@ class VirtualLambdaPort(meta: Meta) : VirtualPort(meta) {
|
|||||||
try {
|
try {
|
||||||
evaluateRequest(command.trim { it <= ' ' }, value.trim { it <= ' ' })
|
evaluateRequest(command.trim { it <= ' ' }, value.trim { it <= ' ' })
|
||||||
} catch (ex: RuntimeException) {
|
} catch (ex: RuntimeException) {
|
||||||
|
receive("FAIL".toByteArray())//TODO какая команда правильная?
|
||||||
receivePhrase("FAIL")//TODO какая команда правильная?
|
|
||||||
LoggerFactory.getLogger(javaClass).error("Request evaluation failure", ex)
|
LoggerFactory.getLogger(javaClass).error("Request evaluation failure", ex)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,14 +112,14 @@ class VirtualLambdaPort(meta: Meta) : VirtualPort(meta) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
"PV?" -> {
|
"PV?" -> {
|
||||||
planResponse(java.lang.Double.toString(currentMagnet().getVoltage()), latency)
|
planResponse(java.lang.Double.toString(currentMagnet().voltage), latency)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
"MV?" -> {
|
"MV?" -> {
|
||||||
planResponse(java.lang.Double.toString(currentMagnet().getVoltage()), latency)
|
planResponse(java.lang.Double.toString(currentMagnet().voltage), latency)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
else -> LoggerFactory.getLogger(javaClass).warn("Unknown comand {}", comand)
|
else -> LoggerFactory.getLogger(javaClass).warn("Unknown command {}", comand)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,28 +130,15 @@ class VirtualLambdaPort(meta: Meta) : VirtualPort(meta) {
|
|||||||
return magnets[currentAddress]!!
|
return magnets[currentAddress]!!
|
||||||
}
|
}
|
||||||
|
|
||||||
@Throws(Exception::class)
|
|
||||||
override fun close() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Throws(PortException::class)
|
|
||||||
override fun open() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun isOpen(): Boolean = true
|
|
||||||
|
|
||||||
private inner class VirtualMagnetStatus(val resistance: Double,
|
private inner class VirtualMagnetStatus(val resistance: Double,
|
||||||
var on: Boolean = true,
|
var on: Boolean = true,
|
||||||
var out: Boolean = false,
|
var out: Boolean = false,
|
||||||
var current: Double = 0.0) {
|
var current: Double = 0.0) {
|
||||||
|
|
||||||
fun getVoltage() = current * resistance
|
val voltage get() = current * resistance
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
private val latency = Duration.ofMillis(50)
|
private val latency = Duration.ofMillis(50)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,32 @@
|
|||||||
|
package inr.numass.control.magnet.fx
|
||||||
|
|
||||||
|
import hep.dataforge.context.Context
|
||||||
|
import hep.dataforge.control.devices.Device
|
||||||
|
import hep.dataforge.control.devices.DeviceFactory
|
||||||
|
import hep.dataforge.meta.Meta
|
||||||
|
import hep.dataforge.meta.MetaUtils
|
||||||
|
import inr.numass.control.NumassControlApplication
|
||||||
|
import inr.numass.control.magnet.LambdaHub
|
||||||
|
import javafx.stage.Stage
|
||||||
|
|
||||||
|
class MagnetApp: NumassControlApplication<LambdaHub>() {
|
||||||
|
|
||||||
|
override val deviceFactory: DeviceFactory = object :DeviceFactory{
|
||||||
|
override fun getType(): String {
|
||||||
|
return "numass.lambda"
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun build(context: Context, meta: Meta): Device {
|
||||||
|
return LambdaHub(context, meta)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setupStage(stage: Stage, device: LambdaHub) {
|
||||||
|
stage.title = "Numass magnet control"
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getDeviceMeta(config: Meta): Meta {
|
||||||
|
return MetaUtils.findNode(config,"device"){it.getString("name") == "numass.magnets"}.orElseThrow{RuntimeException("Magnet configuration not found")}
|
||||||
|
}
|
||||||
|
}
|
@ -15,127 +15,109 @@
|
|||||||
*/
|
*/
|
||||||
package inr.numass.control.magnet.fx
|
package inr.numass.control.magnet.fx
|
||||||
|
|
||||||
import ch.qos.logback.classic.Level
|
import tornadofx.*
|
||||||
import ch.qos.logback.classic.spi.ILoggingEvent
|
|
||||||
import ch.qos.logback.core.FileAppender
|
|
||||||
import hep.dataforge.exceptions.ControlException
|
|
||||||
import hep.dataforge.io.MetaFileReader
|
|
||||||
import inr.numass.control.magnet.LambdaHub
|
|
||||||
import javafx.application.Application
|
|
||||||
import javafx.scene.Scene
|
|
||||||
import javafx.scene.layout.VBox
|
|
||||||
import javafx.stage.Stage
|
|
||||||
import org.slf4j.LoggerFactory
|
|
||||||
import java.io.IOException
|
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author Alexander Nozik
|
* @author Alexander Nozik
|
||||||
*/
|
*/
|
||||||
class MagnetControllerApp : Application() {
|
class MagnetControllerApp : App() {
|
||||||
|
|
||||||
// internal var handler: Port
|
|
||||||
// internal var sourceController: SafeLambdaMagnet
|
|
||||||
// internal var pinchController: SafeLambdaMagnet
|
|
||||||
// internal var conusController: SafeLambdaMagnet
|
|
||||||
// internal var detectorController: SafeLambdaMagnet
|
|
||||||
// internal var controllers: MutableList<SafeLambdaMagnet> = ArrayList()
|
|
||||||
|
|
||||||
private lateinit var device: LambdaHub
|
|
||||||
|
|
||||||
@Throws(IOException::class, ControlException::class)
|
|
||||||
override fun start(stage: Stage) {
|
|
||||||
Locale.setDefault(Locale.US)// чтобы отделение десятичных знаков было точкой
|
|
||||||
val rootLogger = LoggerFactory.getLogger(ch.qos.logback.classic.Logger.ROOT_LOGGER_NAME) as ch.qos.logback.classic.Logger
|
|
||||||
|
|
||||||
val logLevel = parameters.named.getOrDefault("logLevel", "INFO")
|
|
||||||
|
|
||||||
rootLogger.level = Level.valueOf(logLevel)
|
|
||||||
|
|
||||||
val logFile = parameters.named["logFile"]
|
|
||||||
|
|
||||||
if (logFile != null) {
|
|
||||||
val appender = FileAppender<ILoggingEvent>()
|
|
||||||
appender.file = logFile
|
|
||||||
appender.context = rootLogger.loggerContext
|
|
||||||
appender.start()
|
|
||||||
rootLogger.addAppender(appender)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
val config = MetaFileReader.instance().read(context,)
|
|
||||||
|
|
||||||
// val portName = (parameters.named as java.util.Map<String, String>).getOrDefault("port", "virtual")
|
|
||||||
//
|
//
|
||||||
// if (portName == "virtual") {
|
// private lateinit var device: LambdaHub
|
||||||
// handler = VirtualLambdaPort("COM12", 1, 2, 3, 4)
|
//
|
||||||
// } else {
|
// @Throws(IOException::class, ControlException::class)
|
||||||
// handler = PortFactory.getPort(portName)
|
// override fun start(stage: Stage) {
|
||||||
// //TODO add meta reader here
|
// Locale.setDefault(Locale.US)// чтобы отделение десятичных знаков было точкой
|
||||||
|
// val rootLogger = LoggerFactory.getLogger(ch.qos.logback.classic.Logger.ROOT_LOGGER_NAME) as ch.qos.logback.classic.Logger
|
||||||
|
//
|
||||||
|
// val logLevel = parameters.named.getOrDefault("logLevel", "INFO")
|
||||||
|
//
|
||||||
|
// rootLogger.level = Level.valueOf(logLevel)
|
||||||
|
//
|
||||||
|
// val logFile = parameters.named["logFile"]
|
||||||
|
//
|
||||||
|
// if (logFile != null) {
|
||||||
|
// val appender = FileAppender<ILoggingEvent>()
|
||||||
|
// appender.file = logFile
|
||||||
|
// appender.context = rootLogger.loggerContext
|
||||||
|
// appender.start()
|
||||||
|
// rootLogger.addAppender(appender)
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// sourceController = SafeLambdaMagnet("SOURCE", handler, 1)
|
|
||||||
// pinchController = SafeLambdaMagnet("PINCH", handler, 2)
|
|
||||||
// conusController = SafeLambdaMagnet("CONUS", handler, 3)
|
|
||||||
// detectorController = SafeLambdaMagnet("DETECTOR", handler, 4)
|
|
||||||
//
|
//
|
||||||
// conusController.bindTo(pinchController, 30.0)
|
// val configFileName = parameters.named
|
||||||
|
// val config = MetaFileReader.instance().read(context,)
|
||||||
//
|
//
|
||||||
// controllers.add(sourceController)
|
//// val portName = (parameters.named as java.util.Map<String, String>).getOrDefault("port", "virtual")
|
||||||
// sourceController.speed = 4.0
|
////
|
||||||
// controllers.add(pinchController)
|
//// if (portName == "virtual") {
|
||||||
// controllers.add(conusController)
|
//// handler = VirtualLambdaPort("COM12", 1, 2, 3, 4)
|
||||||
// controllers.add(detectorController)
|
//// } else {
|
||||||
|
//// handler = PortFactory.getPort(portName)
|
||||||
|
//// //TODO add meta reader here
|
||||||
val showConfirmation = java.lang.Boolean.parseBoolean((parameters.named as java.util.Map<String, String>).getOrDefault("confirmOut", "false"))
|
//// }
|
||||||
|
////
|
||||||
val vbox = VBox(5.0)
|
//// sourceController = SafeLambdaMagnet("SOURCE", handler, 1)
|
||||||
var height = 0.0
|
//// pinchController = SafeLambdaMagnet("PINCH", handler, 2)
|
||||||
var width = 0.0
|
//// conusController = SafeLambdaMagnet("CONUS", handler, 3)
|
||||||
for (controller in controllers) {
|
//// detectorController = SafeLambdaMagnet("DETECTOR", handler, 4)
|
||||||
val comp = MagnetControllerComponent.build(controller)
|
////
|
||||||
width = Math.max(width, comp.prefWidth)
|
//// conusController.bindTo(pinchController, 30.0)
|
||||||
height += comp.prefHeight + 5
|
////
|
||||||
if (!showConfirmation) {
|
//// controllers.add(sourceController)
|
||||||
comp.setShowConfirmation(showConfirmation)
|
//// sourceController.speed = 4.0
|
||||||
}
|
//// controllers.add(pinchController)
|
||||||
vbox.children.add(comp)
|
//// controllers.add(conusController)
|
||||||
}
|
//// controllers.add(detectorController)
|
||||||
|
//
|
||||||
val scene = Scene(vbox, width, height)
|
//
|
||||||
|
// val showConfirmation = java.lang.Boolean.parseBoolean((parameters.named as java.util.Map<String, String>).getOrDefault("confirmOut", "false"))
|
||||||
|
//
|
||||||
stage.title = "Numass magnet view"
|
// val vbox = VBox(5.0)
|
||||||
stage.scene = scene
|
// var height = 0.0
|
||||||
stage.isResizable = false
|
// var width = 0.0
|
||||||
stage.show()
|
// for (controller in controllers) {
|
||||||
}
|
// val comp = MagnetControllerComponent.build(controller)
|
||||||
|
// width = Math.max(width, comp.prefWidth)
|
||||||
@Throws(Exception::class)
|
// height += comp.prefHeight + 5
|
||||||
override fun stop() {
|
// if (!showConfirmation) {
|
||||||
super.stop() //To change body of generated methods, choose Tools | Templates.
|
// comp.setShowConfirmation(showConfirmation)
|
||||||
for (magnet in controllers) {
|
// }
|
||||||
magnet.stopMonitorTask()
|
// vbox.children.add(comp)
|
||||||
magnet.stopUpdateTask()
|
// }
|
||||||
}
|
//
|
||||||
if (handler.isOpen) {
|
// val scene = Scene(vbox, width, height)
|
||||||
handler.close()
|
//
|
||||||
}
|
//
|
||||||
System.exit(0)
|
// stage.title = "Numass magnet view"
|
||||||
}
|
// stage.scene = scene
|
||||||
|
// stage.isResizable = false
|
||||||
companion object {
|
// stage.show()
|
||||||
|
// }
|
||||||
/**
|
//
|
||||||
* @param args the command line arguments
|
// @Throws(Exception::class)
|
||||||
*/
|
// override fun stop() {
|
||||||
@JvmStatic
|
// super.stop() //To change body of generated methods, choose Tools | Templates.
|
||||||
fun main(args: Array<String>) {
|
// for (magnet in controllers) {
|
||||||
Application.launch(*args)
|
// magnet.stopMonitorTask()
|
||||||
}
|
// magnet.stopUpdateTask()
|
||||||
}
|
// }
|
||||||
|
// if (handler.isOpen) {
|
||||||
|
// handler.close()
|
||||||
|
// }
|
||||||
|
// System.exit(0)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// companion object {
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * @param args the command line arguments
|
||||||
|
// */
|
||||||
|
// @JvmStatic
|
||||||
|
// fun main(args: Array<String>) {
|
||||||
|
// Application.launch(*args)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -20,8 +20,6 @@ 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.event.ActionEvent
|
|
||||||
import javafx.fxml.FXML
|
|
||||||
import javafx.fxml.Initializable
|
import javafx.fxml.Initializable
|
||||||
import javafx.scene.control.*
|
import javafx.scene.control.*
|
||||||
import javafx.scene.layout.AnchorPane
|
import javafx.scene.layout.AnchorPane
|
||||||
@ -40,9 +38,9 @@ class MagnetDisplay : DeviceDisplayFX<LambdaMagnet>() {
|
|||||||
return MagnetControllerComponent(device)
|
return MagnetControllerComponent(device)
|
||||||
}
|
}
|
||||||
|
|
||||||
val current by lazy { valueBinding(device.voltage)}
|
val current by lazy { valueBinding(device.voltage) }
|
||||||
|
|
||||||
val voltage by lazy { valueBinding(device.current)}
|
val voltage by lazy { valueBinding(device.current) }
|
||||||
|
|
||||||
var target by device.target.doubleDelegate
|
var target by device.target.doubleDelegate
|
||||||
|
|
||||||
@ -103,7 +101,7 @@ class MagnetDisplay : DeviceDisplayFX<LambdaMagnet>() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
valueBinding(device.output).onChange{
|
valueBinding(device.output).onChange {
|
||||||
Platform.runLater {
|
Platform.runLater {
|
||||||
if (it?.booleanValue() == true) {
|
if (it?.booleanValue() == true) {
|
||||||
this.statusLabel.text = "OK"
|
this.statusLabel.text = "OK"
|
||||||
@ -114,22 +112,43 @@ class MagnetDisplay : DeviceDisplayFX<LambdaMagnet>() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
valueBinding(device.updating).onChange {
|
||||||
|
val updateTaskRunning = it?.booleanValue() ?: false
|
||||||
|
runLater {
|
||||||
|
this.setButton.isSelected = updateTaskRunning
|
||||||
|
targetIField.isDisable = updateTaskRunning
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
valueBinding(device.monitoring).onChange {
|
||||||
|
runLater {
|
||||||
|
monitorButton.isScaleShape = it?.booleanValue() ?: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setButton.selectedProperty().onChange {
|
||||||
|
try {
|
||||||
|
setOutput(it)
|
||||||
|
} catch (ex: PortException) {
|
||||||
|
displayError(this.device.name, null, ex)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
monitorButton.selectedProperty().onChange {
|
||||||
|
if (it) {
|
||||||
|
monitoring = true
|
||||||
|
} else {
|
||||||
|
monitoring = false
|
||||||
|
this.labelU.text = "----"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setShowConfirmation(showConfirmation: Boolean) {
|
fun setShowConfirmation(showConfirmation: Boolean) {
|
||||||
this.showConfirmation = showConfirmation
|
this.showConfirmation = showConfirmation
|
||||||
}
|
}
|
||||||
|
|
||||||
@FXML
|
|
||||||
private fun onOutToggle(event: ActionEvent) {
|
|
||||||
try {
|
|
||||||
setOutput(setButton.isSelected)
|
|
||||||
} catch (ex: PortException) {
|
|
||||||
displayError(this.device.name, null, ex)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Throws(PortException::class)
|
@Throws(PortException::class)
|
||||||
private fun setOutput(outputOn: Boolean) {
|
private fun setOutput(outputOn: Boolean) {
|
||||||
if (outputOn) {
|
if (outputOn) {
|
||||||
@ -178,17 +197,6 @@ class MagnetDisplay : DeviceDisplayFX<LambdaMagnet>() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@FXML
|
|
||||||
private fun onMonitorToggle(event: ActionEvent) {
|
|
||||||
device
|
|
||||||
if (monitorButton.isSelected) {
|
|
||||||
monitoring = true
|
|
||||||
} else {
|
|
||||||
monitoring = false
|
|
||||||
this.labelU.text = "----"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun displayError(name: String, errorMessage: String?, throwable: Throwable) {
|
fun displayError(name: String, errorMessage: String?, throwable: Throwable) {
|
||||||
Platform.runLater {
|
Platform.runLater {
|
||||||
this.statusLabel.text = "ERROR"
|
this.statusLabel.text = "ERROR"
|
||||||
@ -198,57 +206,9 @@ class MagnetDisplay : DeviceDisplayFX<LambdaMagnet>() {
|
|||||||
// MagnetStateListener.super.error(address, errorMessage, throwable); //To change body of generated methods, choose Tools | Templates.
|
// MagnetStateListener.super.error(address, errorMessage, throwable); //To change body of generated methods, choose Tools | Templates.
|
||||||
}
|
}
|
||||||
|
|
||||||
// /**
|
fun displayState(state: String) {
|
||||||
// * @param lambdaMagnet the device to set
|
|
||||||
// */
|
|
||||||
// private fun setLambdaMagnet(lambdaMagnet: LambdaMagnet) {
|
|
||||||
// this.device = lambdaMagnet
|
|
||||||
// lambdaMagnet.listener = this
|
|
||||||
// magnetName.text = lambdaMagnet.name
|
|
||||||
//
|
|
||||||
// magnetSpeedField.text = java.lang.Double.toString(this.device.speed)
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
|
|
||||||
override fun updateTaskStateChanged(name: String, updateTaskRunning: Boolean) {
|
|
||||||
this.setButton.isSelected = updateTaskRunning
|
|
||||||
targetIField.isDisable = updateTaskRunning
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun monitorTaskStateChanged(name: String, monitorTaskRunning: Boolean) {
|
|
||||||
this.monitorButton.isScaleShape = monitorTaskRunning
|
|
||||||
}
|
|
||||||
|
|
||||||
// /**
|
|
||||||
// * @param logger the logger to set
|
|
||||||
// */
|
|
||||||
// public void setLogger(PrintStream logger) {
|
|
||||||
// this.logger = logger;
|
|
||||||
// }
|
|
||||||
override fun displayState(state: String) {
|
|
||||||
Platform.runLater { this.statusLabel.text = state }
|
Platform.runLater { this.statusLabel.text = state }
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
|
||||||
|
|
||||||
// fun build(lambdaMagnet: LambdaMagnet): MagnetControllerComponent {
|
|
||||||
// val component = MagnetControllerComponent()
|
|
||||||
// val loader = FXMLLoader(lambdaMagnet.javaClass.getResource("/fxml/SingleMagnet.fxml"))
|
|
||||||
//
|
|
||||||
// loader.setRoot(component)
|
|
||||||
// loader.setController(component)
|
|
||||||
//
|
|
||||||
// try {
|
|
||||||
// loader.load<Any>()
|
|
||||||
// } catch (ex: Exception) {
|
|
||||||
// LoggerFactory.getLogger("FX").error("Error during fxml initialization", ex)
|
|
||||||
// throw Error(ex)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// component.setLambdaMagnet(lambdaMagnet)
|
|
||||||
// return component
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,87 +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.magnet.fx
|
|
||||||
|
|
||||||
import ch.qos.logback.classic.Level
|
|
||||||
import ch.qos.logback.classic.Logger
|
|
||||||
import hep.dataforge.context.Global
|
|
||||||
import hep.dataforge.control.ports.GenericPortController
|
|
||||||
import hep.dataforge.control.ports.Port
|
|
||||||
import hep.dataforge.control.ports.PortFactory
|
|
||||||
import hep.dataforge.exceptions.PortException
|
|
||||||
import hep.dataforge.utils.DateTimeUtils
|
|
||||||
import org.slf4j.LoggerFactory
|
|
||||||
import java.io.BufferedReader
|
|
||||||
import java.io.InputStreamReader
|
|
||||||
import java.time.Duration
|
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author darksnake
|
|
||||||
*/
|
|
||||||
object TestApp {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param args the command line arguments
|
|
||||||
*/
|
|
||||||
@JvmStatic
|
|
||||||
fun main(args: Array<String>) {
|
|
||||||
MagnetControllerApp.main(arrayOf("--port=192.168.111.31:4001"))
|
|
||||||
//MagnetControllerApp.main(new String[]{"--port=192.168.111.31:4001", "--logLevel=DEBUG"});
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Alexander Nozik
|
|
||||||
*/
|
|
||||||
object Talk {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param args the command line arguments
|
|
||||||
*/
|
|
||||||
@Throws(Exception::class)
|
|
||||||
@JvmStatic
|
|
||||||
fun main(args: Array<String>) {
|
|
||||||
Locale.setDefault(Locale.US)
|
|
||||||
val rootLogger = LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME) as ch.qos.logback.classic.Logger
|
|
||||||
rootLogger.level = Level.INFO
|
|
||||||
|
|
||||||
var portName = "/dev/ttyr00"
|
|
||||||
|
|
||||||
if (args.size > 0) {
|
|
||||||
portName = args[0]
|
|
||||||
}
|
|
||||||
val handler: Port
|
|
||||||
handler = PortFactory.build(portName)
|
|
||||||
val controller = GenericPortController(Global,handler,"\r")
|
|
||||||
|
|
||||||
// LambdaMagnet controller = new LambdaMagnet(handler, 1);
|
|
||||||
val reader = BufferedReader(InputStreamReader(System.`in`))
|
|
||||||
|
|
||||||
System.out.printf("INPUT > ")
|
|
||||||
var nextString = reader.readLine()
|
|
||||||
|
|
||||||
while ("exit" != nextString) {
|
|
||||||
try {
|
|
||||||
val start = DateTimeUtils.now()
|
|
||||||
val answer = controller.sendAndWait(nextString + "\r", Duration.ofSeconds(1))
|
|
||||||
//String answer = controller.request(nextString);
|
|
||||||
System.out.printf("ANSWER (latency = %s): %s;%n", Duration.between(start, DateTimeUtils.now()), answer.trim { it <= ' ' })
|
|
||||||
} catch (ex: PortException) {
|
|
||||||
ex.printStackTrace()
|
|
||||||
}
|
|
||||||
|
|
||||||
System.out.printf("INPUT > ")
|
|
||||||
nextString = reader.readLine()
|
|
||||||
}
|
|
||||||
|
|
||||||
handler.close()
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
* 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.magnet.test
|
||||||
|
|
||||||
|
import ch.qos.logback.classic.Level
|
||||||
|
import ch.qos.logback.classic.Logger
|
||||||
|
import hep.dataforge.context.Global
|
||||||
|
import hep.dataforge.control.ports.GenericPortController
|
||||||
|
import hep.dataforge.control.ports.Port
|
||||||
|
import hep.dataforge.control.ports.PortFactory
|
||||||
|
import hep.dataforge.exceptions.PortException
|
||||||
|
import hep.dataforge.utils.DateTimeUtils
|
||||||
|
import org.slf4j.LoggerFactory
|
||||||
|
import java.io.BufferedReader
|
||||||
|
import java.io.InputStreamReader
|
||||||
|
import java.time.Duration
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param args the command line arguments
|
||||||
|
*/
|
||||||
|
|
||||||
|
fun main(args: Array<String>) {
|
||||||
|
Locale.setDefault(Locale.US)
|
||||||
|
val rootLogger = LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME) as ch.qos.logback.classic.Logger
|
||||||
|
rootLogger.level = Level.INFO
|
||||||
|
|
||||||
|
var portName = "/dev/ttyr00"
|
||||||
|
|
||||||
|
if (args.isNotEmpty()) {
|
||||||
|
portName = args[0]
|
||||||
|
}
|
||||||
|
val handler: Port
|
||||||
|
handler = PortFactory.build(portName)
|
||||||
|
val controller = GenericPortController(Global, handler, "\r")
|
||||||
|
|
||||||
|
// LambdaMagnet controller = new LambdaMagnet(handler, 1);
|
||||||
|
val reader = BufferedReader(InputStreamReader(System.`in`))
|
||||||
|
|
||||||
|
System.out.printf("INPUT > ")
|
||||||
|
var nextString = reader.readLine()
|
||||||
|
|
||||||
|
while ("exit" != nextString) {
|
||||||
|
try {
|
||||||
|
val start = DateTimeUtils.now()
|
||||||
|
val answer = controller.sendAndWait(nextString + "\r", Duration.ofSeconds(1))
|
||||||
|
//String answer = controller.request(nextString);
|
||||||
|
System.out.printf("ANSWER (latency = %s): %s;%n", Duration.between(start, DateTimeUtils.now()), answer.trim { it <= ' ' })
|
||||||
|
} catch (ex: PortException) {
|
||||||
|
ex.printStackTrace()
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.printf("INPUT > ")
|
||||||
|
nextString = reader.readLine()
|
||||||
|
}
|
||||||
|
|
||||||
|
handler.close()
|
||||||
|
|
||||||
|
}
|
@ -13,9 +13,11 @@
|
|||||||
* 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.control.magnet
|
package inr.numass.control.magnet.test
|
||||||
|
|
||||||
|
import hep.dataforge.context.Global
|
||||||
import hep.dataforge.control.ports.ComPort
|
import hep.dataforge.control.ports.ComPort
|
||||||
|
import inr.numass.control.magnet.LambdaMagnet
|
||||||
import jssc.SerialPortException
|
import jssc.SerialPortException
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -34,14 +36,15 @@ object SetCurrent {
|
|||||||
throw IllegalArgumentException("Wrong number of parameters")
|
throw IllegalArgumentException("Wrong number of parameters")
|
||||||
}
|
}
|
||||||
val comName = args[0]
|
val comName = args[0]
|
||||||
val lambdaaddress = Integer.valueOf(args[1])!!
|
val lambdaaddress = args[1].toInt()
|
||||||
val current = java.lang.Double.valueOf(args[2])
|
val current = args[2].toDouble()
|
||||||
|
|
||||||
val handler = ComPort(comName)
|
val port = ComPort.create(comName)
|
||||||
|
|
||||||
val controller = LambdaMagnet(handler, lambdaaddress)
|
val magnet = LambdaMagnet(Global, port, lambdaaddress)
|
||||||
|
magnet.target.set(current)
|
||||||
|
magnet.output.set(true)
|
||||||
|
|
||||||
controller.startUpdateTask(current, 500)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,7 +1,15 @@
|
|||||||
<?xml version="1.0" encoding="utf-8" ?>
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
<magnets port="virtual">
|
<config>
|
||||||
<magnet name="SOURCE" address="1" resistance="0.02"/>
|
<device name = "numass.magnets">
|
||||||
<magnet name="PINCH" address="2" resistance="0.01"/>
|
<magnet name="SOURCE" address="1"/>
|
||||||
<magnet name="CONUS" address="3" resistance="0.005"/>
|
<magnet name="PINCH" address="2"/>
|
||||||
<magnet name="DETECTOR" address="4" resistance="0.007"/>
|
<magnet name="CONUS" address="3"/>
|
||||||
</magnets>
|
<magnet name="DETECTOR" address="4"/>
|
||||||
|
<port type="debug">
|
||||||
|
<magnet name="SOURCE" address="1" resistance="0.02"/>
|
||||||
|
<magnet name="PINCH" address="2" resistance="0.01"/>
|
||||||
|
<magnet name="CONUS" address="3" resistance="0.005"/>
|
||||||
|
<magnet name="DETECTOR" address="4" resistance="0.007"/>
|
||||||
|
</port>
|
||||||
|
</device>
|
||||||
|
</config>
|
@ -16,6 +16,7 @@
|
|||||||
package inr.numass.control.msp
|
package inr.numass.control.msp
|
||||||
|
|
||||||
import hep.dataforge.meta.Meta
|
import hep.dataforge.meta.Meta
|
||||||
|
import hep.dataforge.meta.MetaUtils
|
||||||
import inr.numass.control.NumassControlApplication
|
import inr.numass.control.NumassControlApplication
|
||||||
import javafx.stage.Stage
|
import javafx.stage.Stage
|
||||||
|
|
||||||
@ -33,9 +34,8 @@ class MspApp : NumassControlApplication<MspDevice>() {
|
|||||||
stage.minWidth = 600.0
|
stage.minWidth = 600.0
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun acceptDevice(meta: Meta): Boolean {
|
override fun getDeviceMeta(config: Meta): Meta {
|
||||||
return meta.getString("name") == "msp"
|
return MetaUtils.findNode(config,"device"){it.getString("name") == "numass.msp"}.orElseThrow{RuntimeException("Mass-spectrometer configuration not found")}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -132,12 +132,12 @@ class MspDisplay() : DeviceDisplayFX<MspDevice>(), DeviceListener, NamedValueLis
|
|||||||
cellFormat {
|
cellFormat {
|
||||||
text = "Filament $it"
|
text = "Filament $it"
|
||||||
}
|
}
|
||||||
disableProperty().bind(getBooleanBinding(PortSensor.CONNECTED_STATE).not())
|
disableProperty().bind(booleanBinding(PortSensor.CONNECTED_STATE).not())
|
||||||
}
|
}
|
||||||
switch {
|
switch {
|
||||||
padding = Insets(5.0, 0.0, 0.0, 0.0)
|
padding = Insets(5.0, 0.0, 0.0, 0.0)
|
||||||
disableProperty()
|
disableProperty()
|
||||||
.bind(getBooleanBinding(PortSensor.CONNECTED_STATE))
|
.bind(booleanBinding(PortSensor.CONNECTED_STATE))
|
||||||
bindBooleanToState("filamentOn", selectedProperty())
|
bindBooleanToState("filamentOn", selectedProperty())
|
||||||
}
|
}
|
||||||
deviceStateIndicator(this@MspDisplay, "filamentStatus", false) {
|
deviceStateIndicator(this@MspDisplay, "filamentStatus", false) {
|
||||||
@ -152,13 +152,13 @@ class MspDisplay() : DeviceDisplayFX<MspDevice>(), DeviceListener, NamedValueLis
|
|||||||
|
|
||||||
togglebutton("Measure") {
|
togglebutton("Measure") {
|
||||||
isSelected = false
|
isSelected = false
|
||||||
disableProperty().bind(getBooleanBinding(PortSensor.CONNECTED_STATE).not())
|
disableProperty().bind(booleanBinding(PortSensor.CONNECTED_STATE).not())
|
||||||
|
|
||||||
bindBooleanToState(Sensor.MEASURING_STATE, selectedProperty())
|
bindBooleanToState(Sensor.MEASURING_STATE, selectedProperty())
|
||||||
}
|
}
|
||||||
togglebutton("Store") {
|
togglebutton("Store") {
|
||||||
isSelected = false
|
isSelected = false
|
||||||
disableProperty().bind(getBooleanBinding(Sensor.MEASURING_STATE).not())
|
disableProperty().bind(booleanBinding(Sensor.MEASURING_STATE).not())
|
||||||
bindBooleanToState("storing", selectedProperty())
|
bindBooleanToState("storing", selectedProperty())
|
||||||
}
|
}
|
||||||
separator(Orientation.VERTICAL)
|
separator(Orientation.VERTICAL)
|
||||||
|
@ -1,159 +0,0 @@
|
|||||||
package inr.numass.control
|
|
||||||
|
|
||||||
import hep.dataforge.connections.Connection
|
|
||||||
import hep.dataforge.control.connections.Roles
|
|
||||||
import hep.dataforge.control.devices.Device
|
|
||||||
import hep.dataforge.control.devices.DeviceListener
|
|
||||||
import hep.dataforge.control.devices.PortSensor
|
|
||||||
import hep.dataforge.control.devices.Sensor
|
|
||||||
import hep.dataforge.exceptions.NameNotFoundException
|
|
||||||
import hep.dataforge.fx.bindWindow
|
|
||||||
import hep.dataforge.states.State
|
|
||||||
import hep.dataforge.states.ValueState
|
|
||||||
import hep.dataforge.values.Value
|
|
||||||
import javafx.beans.binding.BooleanBinding
|
|
||||||
import javafx.beans.binding.ObjectBinding
|
|
||||||
import javafx.beans.property.BooleanProperty
|
|
||||||
import javafx.beans.property.SimpleObjectProperty
|
|
||||||
import javafx.geometry.Pos
|
|
||||||
import javafx.scene.Parent
|
|
||||||
import javafx.scene.layout.HBox
|
|
||||||
import javafx.scene.layout.Priority
|
|
||||||
import tornadofx.*
|
|
||||||
import java.util.*
|
|
||||||
import kotlin.reflect.KClass
|
|
||||||
import kotlin.reflect.full.createInstance
|
|
||||||
|
|
||||||
|
|
||||||
@Target(AnnotationTarget.CLASS)
|
|
||||||
@Retention(AnnotationRetention.RUNTIME)
|
|
||||||
@MustBeDocumented
|
|
||||||
annotation class DeviceView(val value: KClass<out DeviceDisplay<*>>)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get existing view connection or create a new one
|
|
||||||
*/
|
|
||||||
fun Device.getDisplay(): DeviceDisplay<*> {
|
|
||||||
val type = (this::class.annotations.find { it is DeviceView } as DeviceView?)?.value ?: DefaultDisplay::class
|
|
||||||
return optConnection(Roles.VIEW_ROLE, DeviceDisplay::class.java).orElseGet {
|
|
||||||
type.createInstance().also {
|
|
||||||
connect(it, Roles.VIEW_ROLE, Roles.DEVICE_LISTENER_ROLE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* An FX View to represent the device
|
|
||||||
* Created by darksnake on 14-May-17.
|
|
||||||
*/
|
|
||||||
abstract class DeviceDisplay<D : Device> : Component(), Connection, DeviceListener {
|
|
||||||
|
|
||||||
private val bindings = HashMap<String, ObjectBinding<*>>()
|
|
||||||
|
|
||||||
private val deviceProperty = SimpleObjectProperty<D>(this, "device", null)
|
|
||||||
val device: D by deviceProperty
|
|
||||||
|
|
||||||
// private val viewProperty = SimpleObjectProperty<UIComponent>(this, "view", null)
|
|
||||||
val view: UIComponent? by lazy {
|
|
||||||
buildView(device)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun isOpen(): Boolean = 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() {
|
|
||||||
if (isOpen) {
|
|
||||||
view?.close()
|
|
||||||
deviceProperty.set(null)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract fun buildView(device: D): UIComponent?;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a binding for specific state and register it in update listener
|
|
||||||
*/
|
|
||||||
private fun <T : Any> bindState(state: State<T>): ObjectBinding<T> {
|
|
||||||
val binding = object : ObjectBinding<T>() {
|
|
||||||
override fun computeValue(): T {
|
|
||||||
return state.value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
bindings.putIfAbsent(state.name, binding)
|
|
||||||
return binding
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getValueBinding(stateName: String): ObjectBinding<Value> {
|
|
||||||
val state: ValueState = device.states.filterIsInstance(ValueState::class.java).find { it.name == stateName }
|
|
||||||
?: throw NameNotFoundException("State with name $stateName not found")
|
|
||||||
return bindState(state)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getBooleanBinding(stateName: String): BooleanBinding{
|
|
||||||
return getValueBinding(stateName).booleanBinding{it?.booleanValue()?:false}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Bind existing boolean property to writable device state
|
|
||||||
|
|
||||||
* @param state
|
|
||||||
* @param property
|
|
||||||
*/
|
|
||||||
protected fun bindBooleanToState(state: String, property: BooleanProperty) {
|
|
||||||
getValueBinding(state).addListener { _, oldValue, newValue ->
|
|
||||||
if (isOpen && oldValue != newValue) {
|
|
||||||
runLater { property.value = newValue.booleanValue() }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
property.addListener { _, oldValue, newValue ->
|
|
||||||
if (isOpen && oldValue != newValue) {
|
|
||||||
device.states[state] = newValue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun notifyStateChanged(device: Device, name: String, state: Any) {
|
|
||||||
bindings[name]?.invalidate()
|
|
||||||
}
|
|
||||||
|
|
||||||
open fun getBoardView(): Parent {
|
|
||||||
return HBox().apply {
|
|
||||||
alignment = Pos.CENTER_LEFT
|
|
||||||
vgrow = Priority.ALWAYS;
|
|
||||||
deviceStateIndicator(this@DeviceDisplay, Device.INITIALIZED_STATE)
|
|
||||||
deviceStateIndicator(this@DeviceDisplay, PortSensor.CONNECTED_STATE)
|
|
||||||
deviceStateIndicator(this@DeviceDisplay, Sensor.MEASURING_STATE)
|
|
||||||
deviceStateIndicator(this@DeviceDisplay, "storing")
|
|
||||||
pane {
|
|
||||||
hgrow = Priority.ALWAYS
|
|
||||||
}
|
|
||||||
togglebutton("View") {
|
|
||||||
isSelected = false
|
|
||||||
if (view == null) {
|
|
||||||
isDisable = true
|
|
||||||
}
|
|
||||||
view?.bindWindow(selectedProperty())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Default display shows only board pane and nothing else
|
|
||||||
*/
|
|
||||||
class DefaultDisplay() : DeviceDisplay<Device>() {
|
|
||||||
override fun buildView(device: Device): UIComponent? = null
|
|
||||||
}
|
|
||||||
|
|
@ -76,9 +76,9 @@ fun EventTarget.indicator(radius: Double = 10.0, op: (Indicator.() -> Unit) = {}
|
|||||||
fun Indicator.bind(connection: DeviceDisplayFX<*>, state: String, transform: ((Value) -> Paint)? = null) {
|
fun Indicator.bind(connection: DeviceDisplayFX<*>, state: String, transform: ((Value) -> Paint)? = null) {
|
||||||
tooltip(state)
|
tooltip(state)
|
||||||
if (transform != null) {
|
if (transform != null) {
|
||||||
bind(connection.getValueBinding(state), transform);
|
bind(connection.valueBinding(state), transform);
|
||||||
} else {
|
} else {
|
||||||
bind(connection.getValueBinding(state)) {
|
bind(connection.valueBinding(state)) {
|
||||||
when {
|
when {
|
||||||
it.isNull -> Color.GRAY
|
it.isNull -> Color.GRAY
|
||||||
it.booleanValue() -> Color.GREEN
|
it.booleanValue() -> Color.GREEN
|
||||||
@ -117,7 +117,7 @@ fun Node.deviceStateToggle(connection: DeviceDisplayFX<*>, state: String, title:
|
|||||||
connection.device.states[state] = newValue
|
connection.device.states[state] = newValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
connection.getValueBinding(state).onChange {
|
connection.valueBinding(state).onChange {
|
||||||
isSelected = it?.booleanValue() ?: false
|
isSelected = it?.booleanValue() ?: false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,23 +17,23 @@ import java.util.*
|
|||||||
* Created by darksnake on 14-May-17.
|
* Created by darksnake on 14-May-17.
|
||||||
*/
|
*/
|
||||||
abstract class NumassControlApplication<in D : Device> : App() {
|
abstract class NumassControlApplication<in D : Device> : App() {
|
||||||
private var device: D by singleAssign()
|
private var device: D? = null
|
||||||
|
|
||||||
override fun start(stage: Stage) {
|
override fun start(stage: Stage) {
|
||||||
Locale.setDefault(Locale.US)// чтобы отделение десятичных знаков было точкой
|
Locale.setDefault(Locale.US)// чтобы отделение десятичных знаков было точкой
|
||||||
val rootLogger = LoggerFactory.getLogger(ch.qos.logback.classic.Logger.ROOT_LOGGER_NAME) as ch.qos.logback.classic.Logger
|
val rootLogger = LoggerFactory.getLogger(ch.qos.logback.classic.Logger.ROOT_LOGGER_NAME) as ch.qos.logback.classic.Logger
|
||||||
rootLogger.level = Level.INFO
|
rootLogger.level = Level.INFO
|
||||||
|
|
||||||
device = setupDevice()
|
device = setupDevice().also {
|
||||||
|
val controller = it.getDisplay()
|
||||||
|
it.connect(controller, Roles.VIEW_ROLE, Roles.DEVICE_LISTENER_ROLE)
|
||||||
|
val scene = Scene(controller.view?.root ?: controller.getBoardView())
|
||||||
|
stage.scene = scene
|
||||||
|
|
||||||
val controller = device.getDisplay()
|
stage.show()
|
||||||
device.connect(controller, Roles.VIEW_ROLE, Roles.DEVICE_LISTENER_ROLE)
|
setupStage(stage, it)
|
||||||
val scene = Scene(controller.view?.root ?: controller.getBoardView())
|
setDFStageIcon(stage)
|
||||||
stage.scene = scene
|
}
|
||||||
|
|
||||||
stage.show()
|
|
||||||
setupStage(stage, device)
|
|
||||||
setDFStageIcon(stage)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -45,14 +45,14 @@ abstract class NumassControlApplication<in D : Device> : App() {
|
|||||||
|
|
||||||
protected abstract fun setupStage(stage: Stage, device: D)
|
protected abstract fun setupStage(stage: Stage, device: D)
|
||||||
|
|
||||||
protected abstract fun acceptDevice(meta: Meta): Boolean
|
|
||||||
|
abstract fun getDeviceMeta(config: Meta): Meta
|
||||||
|
|
||||||
private fun setupDevice(): D {
|
private fun setupDevice(): D {
|
||||||
val config = getConfig(this).optional.orElseGet { readResourceMeta("/config/devices.xml") }
|
val config = getConfig(this).optional.orElseGet { readResourceMeta("/config/devices.xml") }
|
||||||
|
|
||||||
val ctx = setupContext(config)
|
val ctx = setupContext(config)
|
||||||
val deviceConfig = findDeviceMeta(config) { this.acceptDevice(it) }
|
val deviceConfig = getDeviceMeta(config)
|
||||||
?: throw RuntimeException("Device configuration not found")
|
|
||||||
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -70,11 +70,10 @@ abstract class NumassControlApplication<in D : Device> : App() {
|
|||||||
|
|
||||||
override fun stop() {
|
override fun stop() {
|
||||||
try {
|
try {
|
||||||
device.shutdown()
|
device?.shutdown()
|
||||||
} catch (ex: Exception) {
|
} catch (ex: Exception) {
|
||||||
LoggerFactory.getLogger(javaClass).error("Failed to shutdown application", ex);
|
LoggerFactory.getLogger(javaClass).error("Failed to shutdown application", ex);
|
||||||
} finally {
|
} finally {
|
||||||
device.context.close()
|
|
||||||
super.stop()
|
super.stop()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,10 +16,8 @@ import inr.numass.client.ClientUtils
|
|||||||
import javafx.application.Application
|
import javafx.application.Application
|
||||||
import javafx.stage.Stage
|
import javafx.stage.Stage
|
||||||
import org.slf4j.LoggerFactory
|
import org.slf4j.LoggerFactory
|
||||||
import java.io.IOException
|
|
||||||
import java.nio.file.Files
|
import java.nio.file.Files
|
||||||
import java.nio.file.Paths
|
import java.nio.file.Paths
|
||||||
import java.text.ParseException
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by darksnake on 08-May-17.
|
* Created by darksnake on 08-May-17.
|
||||||
@ -59,16 +57,15 @@ fun connectStorage(device: Device, config: Meta) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun readResourceMeta(path: String): Meta {
|
fun readResourceMeta(path: String): Meta {
|
||||||
try {
|
val resource = Global.io.optResource(path).nullable
|
||||||
return XMLMetaReader().read(Global::class.java.getResourceAsStream(path))
|
if (resource != null) {
|
||||||
} catch (e: IOException) {
|
return XMLMetaReader().read(resource.stream)
|
||||||
throw RuntimeException(e)
|
} else {
|
||||||
} catch (e: ParseException) {
|
throw RuntimeException("Resource $path not found")
|
||||||
throw RuntimeException(e)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fun getConfig(app: Application): Meta? {
|
fun getConfig(app: Application): Meta? {
|
||||||
val debugConfig = app.parameters.named["config.resource"]
|
val debugConfig = app.parameters.named["config.resource"]
|
||||||
if (debugConfig != null) {
|
if (debugConfig != null) {
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
package inr.numass.control.readvac
|
package inr.numass.control.readvac
|
||||||
|
|
||||||
import hep.dataforge.meta.Meta
|
import hep.dataforge.meta.Meta
|
||||||
|
import hep.dataforge.meta.MetaUtils
|
||||||
import inr.numass.control.NumassControlApplication
|
import inr.numass.control.NumassControlApplication
|
||||||
import javafx.stage.Stage
|
import javafx.stage.Stage
|
||||||
|
|
||||||
@ -20,8 +21,8 @@ class ReadVac : NumassControlApplication<VacCollectorDevice>() {
|
|||||||
stage.title = "Numass vacuum measurements"
|
stage.title = "Numass vacuum measurements"
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun acceptDevice(meta: Meta): Boolean {
|
override fun getDeviceMeta(config: Meta): Meta {
|
||||||
return meta.getString("type", "") == "numass:vac"
|
return MetaUtils.findNode(config,"device"){it.getString("name") == "numass.vac"}.orElseThrow{RuntimeException("Vacuum measurement configuration not found")}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user