Default behavior for reference registry changed to strong references. PKT8 test for numass is working.

This commit is contained in:
Alexander Nozik 2017-11-15 14:21:32 +03:00
parent d77051b54f
commit f0fc22c9ec
6 changed files with 96 additions and 245 deletions

View File

@ -7,6 +7,7 @@ syntax: glob
build/* build/*
target/* target/*
private/* private/*
out/*
.gradle/* .gradle/*
.nb-gradle/* .nb-gradle/*
.idea/ .idea/

View File

@ -3,16 +3,17 @@ package inr.numass.control
import hep.dataforge.context.Context import hep.dataforge.context.Context
import hep.dataforge.context.Global import hep.dataforge.context.Global
import hep.dataforge.control.DeviceManager import hep.dataforge.control.DeviceManager
import hep.dataforge.control.connections.Roles
import hep.dataforge.control.devices.Device import hep.dataforge.control.devices.Device
import hep.dataforge.kodex.useMeta import hep.dataforge.kodex.useMeta
import hep.dataforge.kodex.useMetaList import hep.dataforge.kodex.useMetaList
import hep.dataforge.meta.Meta import hep.dataforge.meta.Meta
import hep.dataforge.server.ServerManager import hep.dataforge.server.ServerManager
import hep.dataforge.storage.api.Storage
import hep.dataforge.storage.commons.StorageConnection import hep.dataforge.storage.commons.StorageConnection
import hep.dataforge.storage.commons.StorageManager import hep.dataforge.storage.commons.StorageManager
import inr.numass.client.ClientUtils import inr.numass.client.ClientUtils
import javafx.beans.property.SimpleObjectProperty import javafx.beans.property.SimpleObjectProperty
import javafx.beans.property.SimpleStringProperty
import javafx.collections.FXCollections import javafx.collections.FXCollections
import javafx.collections.ObservableList import javafx.collections.ObservableList
import tornadofx.* import tornadofx.*
@ -25,32 +26,9 @@ class BoardController() : Controller(), AutoCloseable {
val contextProperty = SimpleObjectProperty<Context>(Global.instance()) val contextProperty = SimpleObjectProperty<Context>(Global.instance())
var context: Context by contextProperty var context: Context by contextProperty
// val metaProperty = SimpleObjectProperty<Meta>(Meta.empty())
// var meta: Meta by metaProperty
val numassRunProperty = SimpleStringProperty("")
var numassRun: String by numassRunProperty
private set private set
val storageProperty = nonNullObjectBinding(contextProperty, numassRunProperty) { val storageProperty = SimpleObjectProperty<Storage>(null)
val rootStorage = context.pluginManager.getOrLoad(StorageManager::class.java).defaultStorage
if (!numassRun.isEmpty()) {
context.logger.info("Run information found. Selecting run {}", numassRun)
rootStorage.buildShelf(numassRun, Meta.empty());
} else {
rootStorage
}
}.apply {
onChange {
val connection = StorageConnection(value)
devices.forEach { device ->
device.forEachConnection(StorageConnection::class.java) { device.disconnect(it) }//removing all ald storage connections
device.connect(connection)
}
}
}
val serverManagerProperty = objectBinding(contextProperty) { val serverManagerProperty = objectBinding(contextProperty) {
context.optFeature(ServerManager::class.java).orElse(null) context.optFeature(ServerManager::class.java).orElse(null)
@ -58,52 +36,37 @@ class BoardController() : Controller(), AutoCloseable {
val devices: ObservableList<Device> = FXCollections.observableArrayList(); val devices: ObservableList<Device> = FXCollections.observableArrayList();
val deviceManagerProperty = objectBinding(contextProperty) {
context.optFeature(DeviceManager::class.java).orElse(null)
}.apply {
onChange {
value?.let {
devices.setAll(it.devices.toList());
}
}
}
// val deviceViews: ObservableList<DeviceDisplay<*>> = object : ListBinding<DeviceDisplay<*>>() {
// init {
// bind(devices)
// }
//
// override fun computeValue(): ObservableList<DeviceDisplay<*>> {
// val manager = deviceManagerProperty.value
// return if (manager == null) {
// FXCollections.emptyObservableList();
// } else {
// manager.deviceNames()
// .filter { it.length == 1 } // select top level devices
// .map { manager.optDevice(it) }
// .filter { it.isPresent }
// .map { it.get().getDisplay() }
// .toList().observable()
// }
// }
// }
fun configure(meta: Meta) { fun configure(meta: Meta) {
Context.build("NUMASS", Global.instance(), meta.getMeta("context", meta)).apply { Context.build("NUMASS", Global.instance(), meta.getMeta("context", meta)).apply {
val numassRun = meta.optMeta("numass").map { ClientUtils.getRunName(it) }.orElse("")
meta.useMeta("storage") { meta.useMeta("storage") {
pluginManager.getOrLoad(StorageManager::class.java).configure(it); pluginManager.getOrLoad(StorageManager::class.java).configure(it);
} }
val rootStorage = pluginManager.getOrLoad(StorageManager::class.java).defaultStorage
val storage = if (!numassRun.isEmpty()) {
logger.info("Run information found. Selecting run {}", numassRun)
rootStorage.buildShelf(numassRun, Meta.empty());
} else {
rootStorage
}
val connection = StorageConnection(storage)
val deviceManager = pluginManager.getOrLoad(DeviceManager::class.java)
meta.useMetaList("device") { meta.useMetaList("device") {
it.forEach { it.forEach {
pluginManager.getOrLoad(DeviceManager::class.java).buildDevice(it) deviceManager.buildDevice(it)
} }
} }
meta.useMeta("numass") { deviceManager.devices.forEach { it.connect(connection, Roles.STORAGE_ROLE, Roles.MEASUREMENT_LISTENER_ROLE) }
numassRun = ClientUtils.getRunName(it)
}
}.also { }.also {
runLater { runLater {
context = it context = it
devices.setAll(context.getFeature(DeviceManager::class.java).devices.toList());
} }
} }
} }
@ -112,89 +75,4 @@ class BoardController() : Controller(), AutoCloseable {
context.close() context.close()
//Global.terminate() //Global.terminate()
} }
// val devices: ObservableList<DeviceDisplay<*>> = FXCollections.observableArrayList<DeviceDisplay<*>>();
//
// val contextProperty = SimpleObjectProperty<Context>(Global.instance())
// var context: Context by contextProperty
// private set
//
// val storageProperty = SimpleObjectProperty<Storage>()
// var storage: Storage? by storageProperty
// private set
//
// val serverManagerProperty = SimpleObjectProperty<ServerManager>()
// var serverManager: ServerManager? by serverManagerProperty
// private set
//
// fun load(app: Application) {
// runAsync {
// getConfig(app).ifPresent {
// val context = Context.build("NUMASS", Global.instance(), it)
// load(context, it)
// }
// }
//
// }
//
// private fun load(context: Context, meta: Meta) {
// this.context = context;
// devices.clear();
// meta.getMetaList("device").forEach {
// try {
// Platform.runLater { devices.add(buildDeviceView(context, it)) };
// } catch (ex: Exception) {
// context.logger.error("Can't build device view", ex);
// }
// }
//
// if (meta.hasMeta("storage")) {
// val st = buildStorage(context, meta);
// val storageConnection = StorageConnection(storage);
// devices.forEach {
// if (it.device.acceptsRole(Roles.STORAGE_ROLE)) {
// it.device.connect(storageConnection, Roles.STORAGE_ROLE);
// }
// }
// Platform.runLater {
// storage = st
// meta.optMeta("server").ifPresent { serverMeta ->
// val sm = context.getPluginManager().getOrLoad(ServerManager::class.java);
// sm.configure(serverMeta)
//
// sm.bind(NumassStorageServerObject(serverManager, storage, "numass-storage"));
// serverManager = sm
// }
// }
// }
// }
//
// private fun buildDeviceView(context: Context, deviceMeta: Meta): DeviceDisplay<*> {
// context.logger.info("Building device with meta: {}", deviceMeta)
// val device = context.loadFeature("devices", DeviceManager::class.java).buildDevice(deviceMeta)
// device.init();
// return device.getDisplay();
// }
//
// private fun buildStorage(context: Context, meta: Meta): Storage {
// val storageMeta = meta.getMeta("storage").builder
// .putValue("readOnly", false)
// .putValue("monitor", true)
//
// context.logger.info("Creating storage for server with meta {}", storageMeta)
// var storage = StorageFactory.buildStorage(context, storageMeta);
//
// val numassRun = ClientUtils.getRunName(meta)
// if (!numassRun.isEmpty()) {
// context.logger.info("Run information found. Selecting run {}", numassRun)
// storage = storage.buildShelf(numassRun, Meta.empty());
// }
// return storage;
// }
//
// override fun close() {
// devices.forEach {
// it.close()
// }
// context.close();
// }
} }

View File

@ -22,9 +22,8 @@ import hep.dataforge.meta.Metoid
import hep.dataforge.names.Named import hep.dataforge.names.Named
internal fun createChannel(name: String): PKT8Channel { internal fun createChannel(name: String): PKT8Channel =
return PKT8Channel(MetaBuilder("channel").putValue("name", name)) { d -> d } PKT8Channel(MetaBuilder("channel").putValue("name", name)) { d -> d }
}
internal fun createChannel(meta: Meta): PKT8Channel { internal fun createChannel(meta: Meta): PKT8Channel {
val transformationType = meta.getString("transformationType", "default") val transformationType = meta.getString("transformationType", "default")

View File

@ -42,7 +42,6 @@ import inr.numass.control.DeviceView
import inr.numass.control.StorageHelper import inr.numass.control.StorageHelper
import java.time.Duration import java.time.Duration
import java.util.* import java.util.*
import kotlin.streams.toList
/** /**
@ -61,14 +60,14 @@ class PKT8Device(context: Context, meta: Meta) : PortSensor<PKT8Result>(context,
/** /**
* The key is the letter (a,b,c,d...) as in measurements * The key is the letter (a,b,c,d...) as in measurements
*/ */
private val channels = LinkedHashMap<String, PKT8Channel>() val channels = LinkedHashMap<String, PKT8Channel>()
private var collector: RegularPointCollector? = null private var collector: RegularPointCollector? = null
private var storageHelper: StorageHelper? = null private var storageHelper: StorageHelper? = null
/** /**
* Cached values * Cached values
*/ */
private var format: TableFormat? = null //private var format: TableFormat? = null
private// Building data format private// Building data format
@ -76,15 +75,12 @@ class PKT8Device(context: Context, meta: Meta) : PortSensor<PKT8Result>(context,
val tableFormatBuilder = TableFormatBuilder() val tableFormatBuilder = TableFormatBuilder()
.addTime("timestamp") .addTime("timestamp")
for (channel in channels.values) { for (channel in this.channels.values) {
tableFormatBuilder.addNumber(channel.name) tableFormatBuilder.addNumber(channel.name)
} }
tableFormatBuilder.build() tableFormatBuilder.build()
} }
val chanels: Collection<PKT8Channel>
get() = this.channels.values
val sps: String val sps: String
get() = getState(SPS).stringValue() get() = getState(SPS).stringValue()
@ -119,7 +115,7 @@ class PKT8Device(context: Context, meta: Meta) : PortSensor<PKT8Result>(context,
} else { } else {
//set default channel configuration //set default channel configuration
for (designation in CHANNEL_DESIGNATIONS) { for (designation in CHANNEL_DESIGNATIONS) {
channels.put(designation, createChannel(designation)) this.channels.put(designation, createChannel(designation))
} }
logger.warn("No channels defined in configuration") logger.warn("No channels defined in configuration")
} }
@ -143,12 +139,9 @@ class PKT8Device(context: Context, meta: Meta) : PortSensor<PKT8Result>(context,
// setting up the collector // setting up the collector
storageHelper = StorageHelper(this) { connection: StorageConnection -> this.buildLoader(connection) } storageHelper = StorageHelper(this) { connection: StorageConnection -> this.buildLoader(connection) }
val duration = Duration.parse(meta().getString("averagingDuration", "PT30S")) val duration = Duration.parse(meta().getString("averagingDuration", "PT30S"))
collector = RegularPointCollector( collector = RegularPointCollector(duration, this.channels.values.map { it.name }) { dp: Values ->
duration,
channels.values.stream().map { it.name }.toList()
) { dp: Values ->
logger.debug("Point measurement complete. Pushing...") logger.debug("Point measurement complete. Pushing...")
storageHelper!!.push(dp) storageHelper?.push(dp)
} }
} }
@ -162,13 +155,12 @@ class PKT8Device(context: Context, meta: Meta) : PortSensor<PKT8Result>(context,
@Throws(ControlException::class) @Throws(ControlException::class)
override fun buildHandler(portName: String): PortHandler { override fun buildHandler(portName: String): PortHandler {
val handler: PortHandler
//setup connection //setup connection
if ("virtual" == portName) { val handler: PortHandler = if ("virtual" == portName) {
logger.info("Starting {} using virtual debug port", name) logger.info("Starting {} using virtual debug port", name)
handler = PKT8VirtualPort("PKT8", meta().getMetaOrEmpty("debug")) PKT8VirtualPort("PKT8", meta().getMetaOrEmpty("debug"))
} else { } else {
handler = super.buildHandler(portName) super.buildHandler(portName)
} }
handler.setDelimiter("\n") handler.setDelimiter("\n")
@ -209,17 +201,17 @@ class PKT8Device(context: Context, meta: Meta) : PortSensor<PKT8Result>(context,
* @return * @return
*/ */
private fun spsToStr(sps: Int): String { private fun spsToStr(sps: Int): String {
when (sps) { return when (sps) {
0 -> return "2.5 SPS" 0 -> "2.5 SPS"
1 -> return "5 SPS" 1 -> "5 SPS"
2 -> return "10 SPS" 2 -> "10 SPS"
3 -> return "25 SPS" 3 -> "25 SPS"
4 -> return "50 SPS" 4 -> "50 SPS"
5 -> return "100 SPS" 5 -> "100 SPS"
6 -> return "500 SPS" 6 -> "500 SPS"
7 -> return "1 kSPS" 7 -> "1 kSPS"
8 -> return "3.75 kSPS" 8 -> "3.75 kSPS"
else -> return "unknown value" else -> "unknown value"
} }
} }
@ -231,15 +223,15 @@ class PKT8Device(context: Context, meta: Meta) : PortSensor<PKT8Result>(context,
* @return * @return
*/ */
private fun pgaToStr(pga: Int): String { private fun pgaToStr(pga: Int): String {
when (pga) { return when (pga) {
0 -> return "± 5 V" 0 -> "± 5 V"
1 -> return "± 2,5 V" 1 -> "± 2,5 V"
2 -> return "± 1,25 V" 2 -> "± 1,25 V"
3 -> return "± 0,625 V" 3 -> "± 0,625 V"
4 -> return "± 312.5 mV" 4 -> "± 312.5 mV"
5 -> return "± 156.25 mV" 5 -> "± 156.25 mV"
6 -> return "± 78.125 mV" 6 -> "± 78.125 mV"
else -> return "unknown value" else -> "unknown value"
} }
} }
@ -256,7 +248,7 @@ class PKT8Device(context: Context, meta: Meta) : PortSensor<PKT8Result>(context,
updateState(SPS, Integer.parseInt(response.substring(4))) updateState(SPS, Integer.parseInt(response.substring(4)))
// getLogger().info("successfully sampling rate to {}", spsToStr(this.sps)); // getLogger().info("successfully sampling rate to {}", spsToStr(this.sps));
} else { } else {
logger.error("Setting sps failsed with message: " + response) logger.error("Setting sps failed with message: " + response)
} }
} }
@ -309,7 +301,7 @@ class PKT8Device(context: Context, meta: Meta) : PortSensor<PKT8Result>(context,
try { try {
logger.info("Starting measurement") logger.info("Starting measurement")
handler.holdBy(this) handler.holdBy(this)
handler.send(this,"s") handler.send(this, "s")
afterStart() afterStart()
} catch (ex: ControlException) { } catch (ex: ControlException) {
portError("Failed to start measurement", ex) portError("Failed to start measurement", ex)
@ -332,9 +324,8 @@ class PKT8Device(context: Context, meta: Meta) : PortSensor<PKT8Result>(context,
error(ex) error(ex)
false false
} finally { } finally {
if (collector != null) { collector?.clear()
collector!!.clear() logger.debug("Removing port lock")
}
handler.unholdBy(this) handler.unholdBy(this)
} }
} }
@ -351,13 +342,11 @@ class PKT8Device(context: Context, meta: Meta) : PortSensor<PKT8Result>(context,
val designation = trimmed.substring(0, 1) val designation = trimmed.substring(0, 1)
val rawValue = java.lang.Double.parseDouble(trimmed.substring(1)) / 100 val rawValue = java.lang.Double.parseDouble(trimmed.substring(1)) / 100
val channel = channels[designation] val channel = this@PKT8Device.channels[designation]
if (channel != null) { if (channel != null) {
result(channel.evaluate(rawValue)) result(channel.evaluate(rawValue))
if (collector != null) { collector?.put(channel.name, channel.getTemperature(rawValue))
collector!!.put(channel.getName(), channel.getTemperature(rawValue))
}
} else { } else {
result(PKT8Result(designation, rawValue, -1.0)) result(PKT8Result(designation, rawValue, -1.0))
} }
@ -381,3 +370,11 @@ class PKT8Device(context: Context, meta: Meta) : PortSensor<PKT8Result>(context,
} }
} }
data class PKT8Result(val channel: String, val rawValue: Double, val temperature: Double) {
val rawString: String = String.format("%.2f", rawValue)
val temperatureString: String = String.format("%.2f", temperature)
}

View File

@ -7,6 +7,7 @@ import hep.dataforge.fx.bindWindow
import hep.dataforge.fx.fragments.LogFragment import hep.dataforge.fx.fragments.LogFragment
import hep.dataforge.fx.plots.PlotContainer import hep.dataforge.fx.plots.PlotContainer
import hep.dataforge.meta.Meta import hep.dataforge.meta.Meta
import hep.dataforge.plots.Plot
import hep.dataforge.plots.PlotFrame import hep.dataforge.plots.PlotFrame
import hep.dataforge.plots.PlotUtils import hep.dataforge.plots.PlotUtils
import hep.dataforge.plots.data.TimePlot import hep.dataforge.plots.data.TimePlot
@ -135,16 +136,14 @@ class PKT8Display : DeviceDisplay<PKT8Device>(), MeasurementListener {
} }
inner class CryoPlotView : View("PKT8 temperature plot") { inner class CryoPlotView : View("PKT8 temperature plot") {
val plotFrameMeta: Meta = device.meta.getMetaOrEmpty("plotConfig") private val plotFrameMeta: Meta = device.meta.getMetaOrEmpty("plotConfig")
val plotFrame: PlotFrame by lazy { private val plotFrame: PlotFrame by lazy {
JFreeChartFrame(plotFrameMeta).apply { JFreeChartFrame(plotFrameMeta).apply {
PlotUtils.setXAxis(this, "timestamp", null, "time") PlotUtils.setXAxis(this, "timestamp", null, "time")
} }
} }
private val plottables = plotFrame.plots
var rawDataButton: ToggleButton by singleAssign() var rawDataButton: ToggleButton by singleAssign()
override val root: Parent = borderpane { override val root: Parent = borderpane {
@ -169,39 +168,43 @@ class PKT8Display : DeviceDisplay<PKT8Device>(), MeasurementListener {
} }
init { init {
val channels = device.chanels
//frame config from device configuration
//Do not use view config here, it is applyed separately
channels.stream()
.filter { channel -> !plottables.has(channel.name) }
.forEachOrdered { channel ->
//frame config from device configuration
val plot = TimePlot(channel.name)
plot.configure(channel.meta())
plottables.add(plot)
plotFrame.add(plot)
}
if (device.meta().hasMeta("plotConfig")) { if (device.meta().hasMeta("plotConfig")) {
plottables.configure(device.meta().getMeta("plotConfig")) with(plotFrame.plots) {
TimePlot.setMaxItems(plottables, 1000) configure(device.meta().getMeta("plotConfig"))
TimePlot.setPrefItems(plottables, 400) TimePlot.setMaxItems(this, 1000)
TimePlot.setPrefItems(this, 400)
}
} }
table.addListener(MapChangeListener { change -> table.addListener(MapChangeListener { change ->
if (change.wasAdded()) { if (change.wasAdded()) {
change.valueAdded.apply { change.valueAdded.apply {
getPlot(channel)?.apply {
if (rawDataButton.isSelected) { if (rawDataButton.isSelected) {
plottables.opt(channel).ifPresent { TimePlot.put(it, rawValue) } TimePlot.put(this, rawValue)
} else { } else {
plottables.opt(channel).ifPresent { TimePlot.put(it, temperature) } TimePlot.put(this, temperature)
}
} }
} }
} }
}) })
} }
fun clearPlot() { private fun getPlot(channelName: String): Plot? {
plottables.clear() return if (plotFrame.plots.has(channelName)) {
plotFrame.get(channelName)
} else {
device.channels.values.find { it.name == channelName }?.let {
TimePlot(it.name).apply {
configure(it.meta())
plotFrame.add(this)
}
}
}
}
private fun clearPlot() {
plotFrame.clear()
} }
} }
} }

View File

@ -1,27 +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.cryotemp
/**
* Created by darksnake on 28-Sep-16.
*/
data class PKT8Result(var channel: String, var rawValue: Double, var temperature: Double) {
val rawString: String = String.format("%.2f", rawValue)
val temperatureString: String = String.format("%.2f", temperature)
}