diff --git a/build.gradle.kts b/build.gradle.kts index aebfc4f..b0b93d5 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -5,8 +5,8 @@ plugins { id("space.kscience.gradle.project") } -val dataforgeVersion: String by extra("0.7.1") -val visionforgeVersion by extra("0.3.1") +val dataforgeVersion: String by extra("0.8.0") +val visionforgeVersion by extra("0.4.0") val ktorVersion: String by extra(space.kscience.gradle.KScienceVersions.ktorVersion) val rsocketVersion by extra("0.15.4") val xodusVersion by extra("2.0.1") diff --git a/controls-constructor/src/commonMain/kotlin/space/kscience/controls/constructor/DeviceConstructor.kt b/controls-constructor/src/commonMain/kotlin/space/kscience/controls/constructor/DeviceConstructor.kt index 5dbbe13..5c11f27 100644 --- a/controls-constructor/src/commonMain/kotlin/space/kscience/controls/constructor/DeviceConstructor.kt +++ b/controls-constructor/src/commonMain/kotlin/space/kscience/controls/constructor/DeviceConstructor.kt @@ -5,7 +5,7 @@ import space.kscience.controls.api.PropertyDescriptor import space.kscience.dataforge.context.Context import space.kscience.dataforge.context.Factory import space.kscience.dataforge.meta.Meta -import space.kscience.dataforge.meta.transformations.MetaConverter +import space.kscience.dataforge.meta.MetaConverter import space.kscience.dataforge.names.Name import space.kscience.dataforge.names.asName import kotlin.properties.PropertyDelegateProvider diff --git a/controls-constructor/src/commonMain/kotlin/space/kscience/controls/constructor/DeviceGroup.kt b/controls-constructor/src/commonMain/kotlin/space/kscience/controls/constructor/DeviceGroup.kt index 26b5896..6cdb784 100644 --- a/controls-constructor/src/commonMain/kotlin/space/kscience/controls/constructor/DeviceGroup.kt +++ b/controls-constructor/src/commonMain/kotlin/space/kscience/controls/constructor/DeviceGroup.kt @@ -12,11 +12,7 @@ import space.kscience.controls.manager.install import space.kscience.dataforge.context.Context import space.kscience.dataforge.context.Factory import space.kscience.dataforge.context.request -import space.kscience.dataforge.meta.Laminate -import space.kscience.dataforge.meta.Meta -import space.kscience.dataforge.meta.MutableMeta -import space.kscience.dataforge.meta.get -import space.kscience.dataforge.meta.transformations.MetaConverter +import space.kscience.dataforge.meta.* import space.kscience.dataforge.misc.DFExperimental import space.kscience.dataforge.names.* import kotlin.collections.set diff --git a/controls-constructor/src/commonMain/kotlin/space/kscience/controls/constructor/DeviceState.kt b/controls-constructor/src/commonMain/kotlin/space/kscience/controls/constructor/DeviceState.kt index 672b0a6..1828edd 100644 --- a/controls-constructor/src/commonMain/kotlin/space/kscience/controls/constructor/DeviceState.kt +++ b/controls-constructor/src/commonMain/kotlin/space/kscience/controls/constructor/DeviceState.kt @@ -10,7 +10,7 @@ import space.kscience.controls.spec.DevicePropertySpec import space.kscience.controls.spec.MutableDevicePropertySpec import space.kscience.controls.spec.name import space.kscience.dataforge.meta.Meta -import space.kscience.dataforge.meta.transformations.MetaConverter +import space.kscience.dataforge.meta.MetaConverter import kotlin.time.Duration /** @@ -25,9 +25,9 @@ public interface DeviceState { public companion object } -public val DeviceState.metaFlow: Flow get() = valueFlow.map(converter::objectToMeta) +public val DeviceState.metaFlow: Flow get() = valueFlow.map(converter::convert) -public val DeviceState.valueAsMeta: Meta get() = converter.objectToMeta(value) +public val DeviceState.valueAsMeta: Meta get() = converter.convert(value) /** @@ -38,9 +38,9 @@ public interface MutableDeviceState : DeviceState { } public var MutableDeviceState.valueAsMeta: Meta - get() = converter.objectToMeta(value) + get() = converter.convert(value) set(arg) { - value = converter.metaToObject(arg) + value = converter.read(arg) } /** @@ -98,7 +98,7 @@ private open class BoundDeviceState( override val valueFlow: StateFlow = device.messageFlow.filterIsInstance().filter { it.property == propertyName }.mapNotNull { - converter.metaToObject(it.value) + converter.read(it.value) }.stateIn(device.context, SharingStarted.Eagerly, initialValue) override val value: T get() = valueFlow.value @@ -111,7 +111,7 @@ public suspend fun Device.propertyAsState( propertyName: String, metaConverter: MetaConverter, ): DeviceState { - val initialValue = metaConverter.metaToObject(readProperty(propertyName)) ?: error("Conversion of property failed") + val initialValue = metaConverter.readOrNull(readProperty(propertyName)) ?: error("Conversion of property failed") return BoundDeviceState(metaConverter, this, propertyName, initialValue) } @@ -140,7 +140,7 @@ private class MutableBoundDeviceState( get() = valueFlow.value set(newValue) { device.launch { - device.writeProperty(propertyName, converter.objectToMeta(newValue)) + device.writeProperty(propertyName, converter.convert(newValue)) } } } @@ -155,7 +155,7 @@ public suspend fun Device.mutablePropertyAsState( propertyName: String, metaConverter: MetaConverter, ): MutableDeviceState { - val initialValue = metaConverter.metaToObject(readProperty(propertyName)) ?: error("Conversion of property failed") + val initialValue = metaConverter.readOrNull(readProperty(propertyName)) ?: error("Conversion of property failed") return mutablePropertyAsState(propertyName, metaConverter, initialValue) } diff --git a/controls-constructor/src/commonMain/kotlin/space/kscience/controls/constructor/Drive.kt b/controls-constructor/src/commonMain/kotlin/space/kscience/controls/constructor/Drive.kt index c2391c8..8301622 100644 --- a/controls-constructor/src/commonMain/kotlin/space/kscience/controls/constructor/Drive.kt +++ b/controls-constructor/src/commonMain/kotlin/space/kscience/controls/constructor/Drive.kt @@ -9,9 +9,9 @@ import space.kscience.controls.manager.clock import space.kscience.controls.spec.* import space.kscience.dataforge.context.Context import space.kscience.dataforge.context.Factory +import space.kscience.dataforge.meta.MetaConverter import space.kscience.dataforge.meta.double import space.kscience.dataforge.meta.get -import space.kscience.dataforge.meta.transformations.MetaConverter import kotlin.math.pow import kotlin.time.Duration.Companion.milliseconds import kotlin.time.DurationUnit diff --git a/controls-constructor/src/commonMain/kotlin/space/kscience/controls/constructor/Regulator.kt b/controls-constructor/src/commonMain/kotlin/space/kscience/controls/constructor/Regulator.kt index 7495d33..cbe6967 100644 --- a/controls-constructor/src/commonMain/kotlin/space/kscience/controls/constructor/Regulator.kt +++ b/controls-constructor/src/commonMain/kotlin/space/kscience/controls/constructor/Regulator.kt @@ -2,7 +2,7 @@ package space.kscience.controls.constructor import space.kscience.controls.api.Device import space.kscience.controls.spec.* -import space.kscience.dataforge.meta.transformations.MetaConverter +import space.kscience.dataforge.meta.MetaConverter /** diff --git a/controls-constructor/src/commonMain/kotlin/space/kscience/controls/constructor/customState.kt b/controls-constructor/src/commonMain/kotlin/space/kscience/controls/constructor/customState.kt index 6e95ccd..100f755 100644 --- a/controls-constructor/src/commonMain/kotlin/space/kscience/controls/constructor/customState.kt +++ b/controls-constructor/src/commonMain/kotlin/space/kscience/controls/constructor/customState.kt @@ -2,7 +2,7 @@ package space.kscience.controls.constructor import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow -import space.kscience.dataforge.meta.transformations.MetaConverter +import space.kscience.dataforge.meta.MetaConverter /** diff --git a/controls-core/src/commonMain/kotlin/space/kscience/controls/api/Device.kt b/controls-core/src/commonMain/kotlin/space/kscience/controls/api/Device.kt index 89040c0..3226422 100644 --- a/controls-core/src/commonMain/kotlin/space/kscience/controls/api/Device.kt +++ b/controls-core/src/commonMain/kotlin/space/kscience/controls/api/Device.kt @@ -139,7 +139,7 @@ public interface CachingDevice : Device { /** * Get the logical state of property or suspend to read the physical value. */ -public suspend fun Device.requestProperty(propertyName: String): Meta = if (this is CachingDevice) { +public suspend fun Device.getOrReadProperty(propertyName: String): Meta = if (this is CachingDevice) { getProperty(propertyName) ?: readProperty(propertyName) } else { readProperty(propertyName) diff --git a/controls-core/src/commonMain/kotlin/space/kscience/controls/manager/respondMessage.kt b/controls-core/src/commonMain/kotlin/space/kscience/controls/manager/respondMessage.kt index 3a0ac7b..fc6fb5d 100644 --- a/controls-core/src/commonMain/kotlin/space/kscience/controls/manager/respondMessage.kt +++ b/controls-core/src/commonMain/kotlin/space/kscience/controls/manager/respondMessage.kt @@ -16,7 +16,7 @@ public suspend fun Device.respondMessage(deviceTarget: Name, request: DeviceMess is PropertyGetMessage -> { PropertyChangedMessage( property = request.property, - value = requestProperty(request.property), + value = getOrReadProperty(request.property), sourceDevice = deviceTarget, targetDevice = request.sourceDevice ) @@ -26,7 +26,7 @@ public suspend fun Device.respondMessage(deviceTarget: Name, request: DeviceMess writeProperty(request.property, request.value) PropertyChangedMessage( property = request.property, - value = requestProperty(request.property), + value = getOrReadProperty(request.property), sourceDevice = deviceTarget, targetDevice = request.sourceDevice ) diff --git a/controls-core/src/commonMain/kotlin/space/kscience/controls/misc/PropertyHistory.kt b/controls-core/src/commonMain/kotlin/space/kscience/controls/misc/PropertyHistory.kt index 5b58321..96bd8d5 100644 --- a/controls-core/src/commonMain/kotlin/space/kscience/controls/misc/PropertyHistory.kt +++ b/controls-core/src/commonMain/kotlin/space/kscience/controls/misc/PropertyHistory.kt @@ -9,7 +9,7 @@ import space.kscience.controls.api.DeviceMessage import space.kscience.controls.api.PropertyChangedMessage import space.kscience.controls.spec.DevicePropertySpec import space.kscience.controls.spec.name -import space.kscience.dataforge.meta.transformations.MetaConverter +import space.kscience.dataforge.meta.MetaConverter /** * An interface for device property history. @@ -42,7 +42,7 @@ public class CollectedPropertyHistory( private val store: SharedFlow> = eventFlow .filterIsInstance() .filter { it.property == propertyName } - .map { ValueWithTime(converter.metaToObject(it.value), it.time) } + .map { ValueWithTime(converter.read(it.value), it.time) } .shareIn(scope, started = SharingStarted.Eagerly, replay = maxSize) override fun flowHistory(from: Instant, until: Instant): Flow> = diff --git a/controls-core/src/commonMain/kotlin/space/kscience/controls/misc/ValueWithTime.kt b/controls-core/src/commonMain/kotlin/space/kscience/controls/misc/ValueWithTime.kt index 0bf07d3..f25c4f4 100644 --- a/controls-core/src/commonMain/kotlin/space/kscience/controls/misc/ValueWithTime.kt +++ b/controls-core/src/commonMain/kotlin/space/kscience/controls/misc/ValueWithTime.kt @@ -5,10 +5,8 @@ import kotlinx.io.Sink import kotlinx.io.Source import space.kscience.dataforge.io.IOFormat import space.kscience.dataforge.meta.Meta +import space.kscience.dataforge.meta.MetaConverter import space.kscience.dataforge.meta.get -import space.kscience.dataforge.meta.transformations.MetaConverter -import kotlin.reflect.KType -import kotlin.reflect.typeOf /** * A value coupled to a time it was obtained at @@ -36,8 +34,6 @@ public data class ValueWithTime(val value: T, val time: Instant) { } private class ValueWithTimeIOFormat(val valueFormat: IOFormat) : IOFormat> { - override val type: KType get() = typeOf>() - override fun readFrom(source: Source): ValueWithTime { val timestamp = InstantIOFormat.readFrom(source) @@ -56,18 +52,18 @@ private class ValueWithTimeMetaConverter( val valueConverter: MetaConverter, ) : MetaConverter> { - override val type: KType = typeOf>() - override fun metaToObjectOrNull( - meta: Meta, - ): ValueWithTime? = valueConverter.metaToObject(meta[ValueWithTime.META_VALUE_KEY] ?: Meta.EMPTY)?.let { - ValueWithTime(it, meta[ValueWithTime.META_TIME_KEY]?.instant ?: Instant.DISTANT_PAST) + override fun readOrNull( + source: Meta, + ): ValueWithTime? = valueConverter.read(source[ValueWithTime.META_VALUE_KEY] ?: Meta.EMPTY)?.let { + ValueWithTime(it, source[ValueWithTime.META_TIME_KEY]?.instant ?: Instant.DISTANT_PAST) } - override fun objectToMeta(obj: ValueWithTime): Meta = Meta { + override fun convert(obj: ValueWithTime): Meta = Meta { ValueWithTime.META_TIME_KEY put obj.time.toMeta() - ValueWithTime.META_VALUE_KEY put valueConverter.objectToMeta(obj.value) + ValueWithTime.META_VALUE_KEY put valueConverter.convert(obj.value) } } + public fun MetaConverter.withTime(): MetaConverter> = ValueWithTimeMetaConverter(this) \ No newline at end of file diff --git a/controls-core/src/commonMain/kotlin/space/kscience/controls/spec/DeviceBase.kt b/controls-core/src/commonMain/kotlin/space/kscience/controls/spec/DeviceBase.kt index 846815c..dcb48b4 100644 --- a/controls-core/src/commonMain/kotlin/space/kscience/controls/spec/DeviceBase.kt +++ b/controls-core/src/commonMain/kotlin/space/kscience/controls/spec/DeviceBase.kt @@ -21,7 +21,7 @@ import kotlin.coroutines.CoroutineContext */ @OptIn(InternalDeviceAPI::class) private suspend fun MutableDevicePropertySpec.writeMeta(device: D, item: Meta) { - write(device, converter.metaToObject(item) ?: error("Meta $item could not be read with $converter")) + write(device, converter.readOrNull(item) ?: error("Meta $item could not be read with $converter")) } /** @@ -29,16 +29,16 @@ private suspend fun MutableDevicePropertySpec.writeMeta(de */ @OptIn(InternalDeviceAPI::class) private suspend fun DevicePropertySpec.readMeta(device: D): Meta? = - read(device)?.let(converter::objectToMeta) + read(device)?.let(converter::convert) private suspend fun DeviceActionSpec.executeWithMeta( device: D, item: Meta, ): Meta? { - val arg: I = inputConverter.metaToObject(item) ?: error("Failed to convert $item with $inputConverter") + val arg: I = inputConverter.readOrNull(item) ?: error("Failed to convert $item with $inputConverter") val res = execute(device, arg) - return res?.let { outputConverter.objectToMeta(res) } + return res?.let { outputConverter.convert(res) } } @@ -120,7 +120,7 @@ public abstract class DeviceBase( * Notify the device that a property with [spec] value is changed */ protected suspend fun propertyChanged(spec: DevicePropertySpec, value: T) { - propertyChanged(spec.name, spec.converter.objectToMeta(value)) + propertyChanged(spec.name, spec.converter.convert(value)) } /** diff --git a/controls-core/src/commonMain/kotlin/space/kscience/controls/spec/DeviceMetaPropertySpec.kt b/controls-core/src/commonMain/kotlin/space/kscience/controls/spec/DeviceMetaPropertySpec.kt index 809d940..c5fe8b5 100644 --- a/controls-core/src/commonMain/kotlin/space/kscience/controls/spec/DeviceMetaPropertySpec.kt +++ b/controls-core/src/commonMain/kotlin/space/kscience/controls/spec/DeviceMetaPropertySpec.kt @@ -3,9 +3,9 @@ package space.kscience.controls.spec import space.kscience.controls.api.Device import space.kscience.controls.api.PropertyDescriptor import space.kscience.dataforge.meta.Meta -import space.kscience.dataforge.meta.transformations.MetaConverter +import space.kscience.dataforge.meta.MetaConverter -internal object DeviceMetaPropertySpec: DevicePropertySpec { +internal object DeviceMetaPropertySpec : DevicePropertySpec { override val descriptor: PropertyDescriptor = PropertyDescriptor("@meta") override val converter: MetaConverter = MetaConverter.meta diff --git a/controls-core/src/commonMain/kotlin/space/kscience/controls/spec/DevicePropertySpec.kt b/controls-core/src/commonMain/kotlin/space/kscience/controls/spec/DevicePropertySpec.kt index 8e0d6de..edf9f93 100644 --- a/controls-core/src/commonMain/kotlin/space/kscience/controls/spec/DevicePropertySpec.kt +++ b/controls-core/src/commonMain/kotlin/space/kscience/controls/spec/DevicePropertySpec.kt @@ -5,7 +5,7 @@ import kotlinx.coroutines.Job import kotlinx.coroutines.flow.* import kotlinx.coroutines.launch import space.kscience.controls.api.* -import space.kscience.dataforge.meta.transformations.MetaConverter +import space.kscience.dataforge.meta.MetaConverter /** @@ -72,23 +72,23 @@ public interface DeviceActionSpec { public val DeviceActionSpec<*, *, *>.name: String get() = descriptor.name public suspend fun D.read(propertySpec: DevicePropertySpec): T = - propertySpec.converter.metaToObject(readProperty(propertySpec.name)) ?: error("Property read result is not valid") + propertySpec.converter.readOrNull(readProperty(propertySpec.name)) ?: error("Property read result is not valid") /** * Read typed value and update/push event if needed. * Return null if property read is not successful or property is undefined. */ public suspend fun > D.readOrNull(propertySpec: DevicePropertySpec): T? = - readPropertyOrNull(propertySpec.name)?.let(propertySpec.converter::metaToObject) + readPropertyOrNull(propertySpec.name)?.let(propertySpec.converter::readOrNull) -public suspend fun D.request(propertySpec: DevicePropertySpec): T = - propertySpec.converter.metaToObject(requestProperty(propertySpec.name)) +public suspend fun D.getOrRead(propertySpec: DevicePropertySpec): T = + propertySpec.converter.read(getOrReadProperty(propertySpec.name)) /** * Write typed property state and invalidate logical state */ public suspend fun D.write(propertySpec: MutableDevicePropertySpec, value: T) { - writeProperty(propertySpec.name, propertySpec.converter.objectToMeta(value)) + writeProperty(propertySpec.name, propertySpec.converter.convert(value)) } /** @@ -104,7 +104,7 @@ public fun D.writeAsync(propertySpec: MutableDevicePropertySpec< public fun D.propertyFlow(spec: DevicePropertySpec): Flow = messageFlow .filterIsInstance() .filter { it.property == spec.name } - .mapNotNull { spec.converter.metaToObject(it.value) } + .mapNotNull { spec.converter.read(it.value) } /** * A type safe property change listener. Uses the device [CoroutineScope]. @@ -117,7 +117,7 @@ public fun D.onPropertyChange( .filterIsInstance() .filter { it.property == spec.name } .onEach { change -> - val newValue = spec.converter.metaToObject(change.value) + val newValue = spec.converter.read(change.value) if (newValue != null) { change.callback(newValue) } @@ -136,7 +136,7 @@ public fun D.useProperty( .filterIsInstance() .filter { it.property == spec.name } .collect { change -> - val newValue = spec.converter.metaToObject(change.value) + val newValue = spec.converter.readOrNull(change.value) if (newValue != null) { callback(newValue) } diff --git a/controls-core/src/commonMain/kotlin/space/kscience/controls/spec/DeviceSpec.kt b/controls-core/src/commonMain/kotlin/space/kscience/controls/spec/DeviceSpec.kt index 4091921..2f90cb8 100644 --- a/controls-core/src/commonMain/kotlin/space/kscience/controls/spec/DeviceSpec.kt +++ b/controls-core/src/commonMain/kotlin/space/kscience/controls/spec/DeviceSpec.kt @@ -5,20 +5,16 @@ import space.kscience.controls.api.ActionDescriptor import space.kscience.controls.api.Device import space.kscience.controls.api.PropertyDescriptor import space.kscience.dataforge.meta.Meta -import space.kscience.dataforge.meta.transformations.MetaConverter +import space.kscience.dataforge.meta.MetaConverter import kotlin.properties.PropertyDelegateProvider import kotlin.properties.ReadOnlyProperty import kotlin.reflect.KProperty -import kotlin.reflect.KType -import kotlin.reflect.typeOf public object UnitMetaConverter : MetaConverter { - override val type: KType = typeOf() + override fun readOrNull(source: Meta): Unit = Unit - override fun metaToObjectOrNull(meta: Meta): Unit = Unit - - override fun objectToMeta(obj: Unit): Meta = Meta.EMPTY + override fun convert(obj: Unit): Meta = Meta.EMPTY } public val MetaConverter.Companion.unit: MetaConverter get() = UnitMetaConverter diff --git a/controls-core/src/commonMain/kotlin/space/kscience/controls/spec/misc.kt b/controls-core/src/commonMain/kotlin/space/kscience/controls/spec/misc.kt index ee14237..1fc4649 100644 --- a/controls-core/src/commonMain/kotlin/space/kscience/controls/spec/misc.kt +++ b/controls-core/src/commonMain/kotlin/space/kscience/controls/spec/misc.kt @@ -1,9 +1,6 @@ package space.kscience.controls.spec import space.kscience.dataforge.meta.* -import space.kscience.dataforge.meta.transformations.MetaConverter -import kotlin.reflect.KType -import kotlin.reflect.typeOf import kotlin.time.Duration import kotlin.time.DurationUnit import kotlin.time.toDuration @@ -12,16 +9,14 @@ public fun Double.asMeta(): Meta = Meta(asValue()) //TODO to be moved to DF public object DurationConverter : MetaConverter { - override val type: KType = typeOf() - - override fun metaToObjectOrNull(meta: Meta): Duration = meta.value?.double?.toDuration(DurationUnit.SECONDS) + override fun readOrNull(source: Meta): Duration = source.value?.double?.toDuration(DurationUnit.SECONDS) ?: run { - val unit: DurationUnit = meta["unit"].enum() ?: DurationUnit.SECONDS - val value = meta[Meta.VALUE_KEY].double ?: error("No value present for Duration") + val unit: DurationUnit = source["unit"].enum() ?: DurationUnit.SECONDS + val value = source[Meta.VALUE_KEY].double ?: error("No value present for Duration") return@run value.toDuration(unit) } - override fun objectToMeta(obj: Duration): Meta = obj.toDouble(DurationUnit.SECONDS).asMeta() + override fun convert(obj: Duration): Meta = obj.toDouble(DurationUnit.SECONDS).asMeta() } public val MetaConverter.Companion.duration: MetaConverter get() = DurationConverter \ No newline at end of file diff --git a/controls-core/src/commonMain/kotlin/space/kscience/controls/spec/propertySpecDelegates.kt b/controls-core/src/commonMain/kotlin/space/kscience/controls/spec/propertySpecDelegates.kt index 231891c..8bd22b6 100644 --- a/controls-core/src/commonMain/kotlin/space/kscience/controls/spec/propertySpecDelegates.kt +++ b/controls-core/src/commonMain/kotlin/space/kscience/controls/spec/propertySpecDelegates.kt @@ -4,8 +4,8 @@ import space.kscience.controls.api.Device import space.kscience.controls.api.PropertyDescriptor import space.kscience.controls.api.metaDescriptor import space.kscience.dataforge.meta.Meta +import space.kscience.dataforge.meta.MetaConverter import space.kscience.dataforge.meta.ValueType -import space.kscience.dataforge.meta.transformations.MetaConverter import kotlin.properties.PropertyDelegateProvider import kotlin.properties.ReadOnlyProperty import kotlin.reflect.KMutableProperty1 @@ -53,8 +53,8 @@ public fun > DeviceSpec.logicalProperty( converter, descriptorBuilder, name, - read = { propertyName -> getProperty(propertyName)?.let(converter::metaToObject) }, - write = { propertyName, value -> writeProperty(propertyName, converter.objectToMeta(value)) } + read = { propertyName -> getProperty(propertyName)?.let(converter::readOrNull) }, + write = { propertyName, value -> writeProperty(propertyName, converter.convert(value)) } ) diff --git a/controls-jupyter/src/jsMain/kotlin/commonJupyter.kt b/controls-jupyter/src/jsMain/kotlin/commonJupyter.kt index 41711d7..388e1ab 100644 --- a/controls-jupyter/src/jsMain/kotlin/commonJupyter.kt +++ b/controls-jupyter/src/jsMain/kotlin/commonJupyter.kt @@ -1,7 +1,7 @@ +import space.kscience.visionforge.html.runVisionClient import space.kscience.visionforge.jupyter.VFNotebookClient import space.kscience.visionforge.markup.MarkupPlugin import space.kscience.visionforge.plotly.PlotlyPlugin -import space.kscience.visionforge.runVisionClient public fun main(): Unit = runVisionClient { // plugin(DeviceManager) diff --git a/controls-magix/src/commonMain/kotlin/space/kscience/controls/client/DeviceClient.kt b/controls-magix/src/commonMain/kotlin/space/kscience/controls/client/DeviceClient.kt index 31dbd89..51836b9 100644 --- a/controls-magix/src/commonMain/kotlin/space/kscience/controls/client/DeviceClient.kt +++ b/controls-magix/src/commonMain/kotlin/space/kscience/controls/client/DeviceClient.kt @@ -144,7 +144,7 @@ public fun MagixEndpoint.controlsPropertyFlow( .filter { message -> message.sourceDevice == deviceName && message.property == propertySpec.name }.map { - propertySpec.converter.metaToObject(it.value) + propertySpec.converter.read(it.value) } } @@ -157,7 +157,7 @@ public suspend fun MagixEndpoint.sendControlsPropertyChange( ) { val message = PropertySetMessage( property = propertySpec.name, - value = propertySpec.converter.objectToMeta(value), + value = propertySpec.converter.convert(value), targetDevice = deviceName ) send(DeviceManager.magixFormat, message, source = sourceEndpointName, target = targetEndpointName) @@ -177,6 +177,6 @@ public fun MagixEndpoint.controlsPropertyMessageFlow( .filter { message -> message.sourceDevice == deviceName && message.property == propertySpec.name }.map { - it to propertySpec.converter.metaToObject(it.value) + it to propertySpec.converter.read(it.value) } } \ No newline at end of file diff --git a/controls-magix/src/commonMain/kotlin/space/kscience/controls/client/clientPropertyAccess.kt b/controls-magix/src/commonMain/kotlin/space/kscience/controls/client/clientPropertyAccess.kt index 22b0413..20c59e8 100644 --- a/controls-magix/src/commonMain/kotlin/space/kscience/controls/client/clientPropertyAccess.kt +++ b/controls-magix/src/commonMain/kotlin/space/kscience/controls/client/clientPropertyAccess.kt @@ -5,7 +5,7 @@ import kotlinx.coroutines.Job import kotlinx.coroutines.flow.* import kotlinx.coroutines.launch import space.kscience.controls.api.PropertyChangedMessage -import space.kscience.controls.api.requestProperty +import space.kscience.controls.api.getOrReadProperty import space.kscience.controls.spec.DeviceActionSpec import space.kscience.controls.spec.DevicePropertySpec import space.kscience.controls.spec.MutableDevicePropertySpec @@ -17,14 +17,14 @@ import space.kscience.dataforge.meta.Meta * An accessor that allows DeviceClient to connect to any property without type checks */ public suspend fun DeviceClient.read(propertySpec: DevicePropertySpec<*, T>): T = - propertySpec.converter.metaToObject(readProperty(propertySpec.name)) ?: error("Property read result is not valid") + propertySpec.converter.readOrNull(readProperty(propertySpec.name)) ?: error("Property read result is not valid") public suspend fun DeviceClient.request(propertySpec: DevicePropertySpec<*, T>): T = - propertySpec.converter.metaToObject(requestProperty(propertySpec.name)) + propertySpec.converter.read(getOrReadProperty(propertySpec.name)) public suspend fun DeviceClient.write(propertySpec: MutableDevicePropertySpec<*, T>, value: T) { - writeProperty(propertySpec.name, propertySpec.converter.objectToMeta(value)) + writeProperty(propertySpec.name, propertySpec.converter.convert(value)) } public fun DeviceClient.writeAsync(propertySpec: MutableDevicePropertySpec<*, T>, value: T): Job = launch { @@ -34,7 +34,7 @@ public fun DeviceClient.writeAsync(propertySpec: MutableDevicePropertySpec<* public fun DeviceClient.propertyFlow(spec: DevicePropertySpec<*, T>): Flow = messageFlow .filterIsInstance() .filter { it.property == spec.name } - .mapNotNull { spec.converter.metaToObject(it.value) } + .mapNotNull { spec.converter.readOrNull(it.value) } public fun DeviceClient.onPropertyChange( spec: DevicePropertySpec<*, T>, @@ -44,7 +44,7 @@ public fun DeviceClient.onPropertyChange( .filterIsInstance() .filter { it.property == spec.name } .onEach { change -> - val newValue = spec.converter.metaToObject(change.value) + val newValue = spec.converter.readOrNull(change.value) if (newValue != null) { change.callback(newValue) } @@ -60,7 +60,7 @@ public fun DeviceClient.useProperty( .filterIsInstance() .filter { it.property == spec.name } .collect { change -> - val newValue = spec.converter.metaToObject(change.value) + val newValue = spec.converter.readOrNull(change.value) if (newValue != null) { callback(newValue) } @@ -68,12 +68,12 @@ public fun DeviceClient.useProperty( } public suspend fun DeviceClient.execute(actionSpec: DeviceActionSpec<*, I, O>, input: I): O { - val inputMeta = actionSpec.inputConverter.objectToMeta(input) + val inputMeta = actionSpec.inputConverter.convert(input) val res = execute(actionSpec.name, inputMeta) - return actionSpec.outputConverter.metaToObject(res ?: Meta.EMPTY) + return actionSpec.outputConverter.read(res ?: Meta.EMPTY) } public suspend fun DeviceClient.execute(actionSpec: DeviceActionSpec<*, Unit, O>): O { val res = execute(actionSpec.name, Meta.EMPTY) - return actionSpec.outputConverter.metaToObject(res ?: Meta.EMPTY) + return actionSpec.outputConverter.read(res ?: Meta.EMPTY) } \ No newline at end of file diff --git a/controls-magix/src/commonMain/kotlin/space/kscience/controls/client/tangoMagix.kt b/controls-magix/src/commonMain/kotlin/space/kscience/controls/client/tangoMagix.kt index 9c30f8c..d0bdda4 100644 --- a/controls-magix/src/commonMain/kotlin/space/kscience/controls/client/tangoMagix.kt +++ b/controls-magix/src/commonMain/kotlin/space/kscience/controls/client/tangoMagix.kt @@ -6,7 +6,7 @@ import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch import kotlinx.serialization.Serializable import space.kscience.controls.api.get -import space.kscience.controls.api.requestProperty +import space.kscience.controls.api.getOrReadProperty import space.kscience.controls.manager.DeviceManager import space.kscience.dataforge.context.error import space.kscience.dataforge.context.logger @@ -91,7 +91,7 @@ public fun DeviceManager.launchTangoMagix( val device = get(payload.device) when (payload.action) { TangoAction.read -> { - val value = device.requestProperty(payload.name) + val value = device.getOrReadProperty(payload.name) respond(request, payload) { requestPayload -> requestPayload.copy( value = value, @@ -104,7 +104,7 @@ public fun DeviceManager.launchTangoMagix( device.writeProperty(payload.name, value) } //wait for value to be written and return final state - val value = device.requestProperty(payload.name) + val value = device.getOrReadProperty(payload.name) respond(request, payload) { requestPayload -> requestPayload.copy( value = value, diff --git a/controls-opcua/src/main/kotlin/space/kscience/controls/opcua/client/OpcUaDevice.kt b/controls-opcua/src/main/kotlin/space/kscience/controls/opcua/client/OpcUaDevice.kt index 51e6032..08a84b0 100644 --- a/controls-opcua/src/main/kotlin/space/kscience/controls/opcua/client/OpcUaDevice.kt +++ b/controls-opcua/src/main/kotlin/space/kscience/controls/opcua/client/OpcUaDevice.kt @@ -9,8 +9,8 @@ import org.eclipse.milo.opcua.stack.core.types.builtin.* import org.eclipse.milo.opcua.stack.core.types.enumerated.TimestampsToReturn import space.kscience.controls.api.Device import space.kscience.dataforge.meta.Meta +import space.kscience.dataforge.meta.MetaConverter import space.kscience.dataforge.meta.MetaSerializer -import space.kscience.dataforge.meta.transformations.MetaConverter import kotlin.properties.ReadWriteProperty import kotlin.reflect.KProperty @@ -43,7 +43,7 @@ public suspend inline fun OpcUaDevice.readOpcWithTime( else -> error("Incompatible OPC property value $content") } - val res: T = converter.metaToObject(meta) + val res: T = converter.read(meta) return res to time } @@ -69,7 +69,7 @@ public suspend inline fun OpcUaDevice.readOpc( else -> error("Incompatible OPC property value $content") } - return converter.metaToObject(meta) ?: error("Meta $meta could not be converted to ${T::class}") + return converter.readOrNull(meta) ?: error("Meta $meta could not be converted to ${T::class}") } public suspend inline fun OpcUaDevice.writeOpc( @@ -77,7 +77,7 @@ public suspend inline fun OpcUaDevice.writeOpc( converter: MetaConverter, value: T ): StatusCode { - val meta = converter.objectToMeta(value) + val meta = converter.convert(value) return client.writeValue(nodeId, DataValue(Variant(meta))).await() } diff --git a/controls-opcua/src/main/kotlin/space/kscience/controls/opcua/client/OpcUaDeviceBySpec.kt b/controls-opcua/src/main/kotlin/space/kscience/controls/opcua/client/OpcUaDeviceBySpec.kt index 188760e..7debc0e 100644 --- a/controls-opcua/src/main/kotlin/space/kscience/controls/opcua/client/OpcUaDeviceBySpec.kt +++ b/controls-opcua/src/main/kotlin/space/kscience/controls/opcua/client/OpcUaDeviceBySpec.kt @@ -31,7 +31,7 @@ public class MiloConfiguration : Scheme() { public var endpointUrl: String by string { error("Endpoint url is not defined") } - public var username: MiloUsername? by specOrNull(MiloUsername) + public var username: MiloUsername? by schemeOrNull(MiloUsername) public var securityPolicy: SecurityPolicy by enum(SecurityPolicy.None) diff --git a/controls-opcua/src/test/kotlin/space/kscience/controls/opcua/client/OpcUaClientTest.kt b/controls-opcua/src/test/kotlin/space/kscience/controls/opcua/client/OpcUaClientTest.kt index 33aa8fb..b4d63ad 100644 --- a/controls-opcua/src/test/kotlin/space/kscience/controls/opcua/client/OpcUaClientTest.kt +++ b/controls-opcua/src/test/kotlin/space/kscience/controls/opcua/client/OpcUaClientTest.kt @@ -7,7 +7,7 @@ import org.junit.jupiter.api.Test import space.kscience.controls.spec.DeviceSpec import space.kscience.controls.spec.doubleProperty import space.kscience.controls.spec.read -import space.kscience.dataforge.meta.transformations.MetaConverter +import space.kscience.dataforge.meta.MetaConverter import kotlin.test.Ignore class OpcUaClientTest { diff --git a/controls-storage/controls-xodus/src/main/kotlin/space/kscience/controls/xodus/XodusDeviceMessageStorage.kt b/controls-storage/controls-xodus/src/main/kotlin/space/kscience/controls/xodus/XodusDeviceMessageStorage.kt index 35c9b89..559d2a0 100644 --- a/controls-storage/controls-xodus/src/main/kotlin/space/kscience/controls/xodus/XodusDeviceMessageStorage.kt +++ b/controls-storage/controls-xodus/src/main/kotlin/space/kscience/controls/xodus/XodusDeviceMessageStorage.kt @@ -6,8 +6,6 @@ import jetbrains.exodus.entitystore.PersistentEntityStores import jetbrains.exodus.entitystore.StoreTransaction import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.asFlow -import kotlinx.coroutines.flow.filter -import kotlinx.coroutines.flow.map import kotlinx.datetime.Instant import kotlinx.serialization.encodeToString import kotlinx.serialization.json.Json @@ -72,13 +70,13 @@ public class XodusDeviceMessageStorage( DEVICE_MESSAGE_ENTITY_TYPE, DeviceMessage::time.name, true - ).asFlow().map { + ).map { Json.decodeFromString( DeviceMessage.serializer(), it.getBlobString("json") ?: error("No json content found") ) } - } + }.asFlow() override fun read( eventType: String, @@ -90,7 +88,7 @@ public class XodusDeviceMessageStorage( DEVICE_MESSAGE_ENTITY_TYPE, "type", eventType - ).asFlow().filter { + ).filter { it.timeInRange(range) && it.propertyMatchesName(DeviceMessage::sourceDevice.name, sourceDevice) && it.propertyMatchesName(DeviceMessage::targetDevice.name, targetDevice) @@ -100,7 +98,7 @@ public class XodusDeviceMessageStorage( it.getBlobString("json") ?: error("No json content found") ) } - } + }.asFlow() override fun close() { entityStore.close() diff --git a/controls-storage/controls-xodus/src/test/kotlin/PropertyHistoryTest.kt b/controls-storage/controls-xodus/src/test/kotlin/PropertyHistoryTest.kt index 1724079..e7017b1 100644 --- a/controls-storage/controls-xodus/src/test/kotlin/PropertyHistoryTest.kt +++ b/controls-storage/controls-xodus/src/test/kotlin/PropertyHistoryTest.kt @@ -1,5 +1,6 @@ import jetbrains.exodus.entitystore.PersistentEntityStores import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.flow.first import kotlinx.coroutines.test.runTest import kotlinx.datetime.Instant import org.junit.jupiter.api.AfterAll @@ -7,8 +8,8 @@ import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.BeforeAll import org.junit.jupiter.api.Test import space.kscience.controls.api.PropertyChangedMessage +import space.kscience.controls.storage.read import space.kscience.controls.xodus.XodusDeviceMessageStorage -import space.kscience.controls.xodus.query import space.kscience.controls.xodus.writeMessage import space.kscience.dataforge.meta.Meta import space.kscience.dataforge.names.Name @@ -67,7 +68,7 @@ internal class PropertyHistoryTest { XodusDeviceMessageStorage(entityStore).use { storage -> assertEquals( propertyChangedMessages[0], - storage.query( + storage.read( sourceDevice = "virtual-car".asName() ).first { it.property == "speed" } ) diff --git a/controls-storage/src/commonMain/kotlin/space/kscience/controls/storage/propertyHistory.kt b/controls-storage/src/commonMain/kotlin/space/kscience/controls/storage/propertyHistory.kt index 0ca30cc..b52ed2b 100644 --- a/controls-storage/src/commonMain/kotlin/space/kscience/controls/storage/propertyHistory.kt +++ b/controls-storage/src/commonMain/kotlin/space/kscience/controls/storage/propertyHistory.kt @@ -7,7 +7,7 @@ import kotlinx.datetime.Instant import space.kscience.controls.api.PropertyChangedMessage import space.kscience.controls.misc.PropertyHistory import space.kscience.controls.misc.ValueWithTime -import space.kscience.dataforge.meta.transformations.MetaConverter +import space.kscience.dataforge.meta.MetaConverter public fun DeviceMessageStorage.propertyHistory( propertyName: String, @@ -16,5 +16,5 @@ public fun DeviceMessageStorage.propertyHistory( override fun flowHistory(from: Instant, until: Instant): Flow> = read(from..until) .filter { it.property == propertyName } - .map { ValueWithTime(converter.metaToObject(it.value), it.time) } + .map { ValueWithTime(converter.read(it.value), it.time) } } \ No newline at end of file diff --git a/controls-vision/src/commonMain/kotlin/plotExtensions.kt b/controls-vision/src/commonMain/kotlin/plotExtensions.kt index fde716b..6e92165 100644 --- a/controls-vision/src/commonMain/kotlin/plotExtensions.kt +++ b/controls-vision/src/commonMain/kotlin/plotExtensions.kt @@ -149,7 +149,7 @@ private fun Trace.updateFromState( public fun Plot.plotDeviceState( context: Context, state: DeviceState, - extractValue: T.() -> Value = { state.converter.objectToMeta(this).value ?: Null }, + extractValue: T.() -> Value = { state.converter.convert(this).value ?: Null }, maxAge: Duration = defaultMaxAge, maxPoints: Int = defaultMaxPoints, minPoints: Int = defaultMinPoints, diff --git a/controls-vision/src/jsMain/kotlin/ControlsVisionPlugin.js.kt b/controls-vision/src/jsMain/kotlin/ControlsVisionPlugin.js.kt index b34cc44..017989b 100644 --- a/controls-vision/src/jsMain/kotlin/ControlsVisionPlugin.js.kt +++ b/controls-vision/src/jsMain/kotlin/ControlsVisionPlugin.js.kt @@ -7,10 +7,9 @@ import space.kscience.dataforge.context.PluginFactory import space.kscience.dataforge.context.PluginTag import space.kscience.dataforge.meta.Meta import space.kscience.dataforge.names.Name -import space.kscience.visionforge.ElementVisionRenderer import space.kscience.visionforge.Vision -import space.kscience.visionforge.VisionClient import space.kscience.visionforge.VisionPlugin +import space.kscience.visionforge.html.ElementVisionRenderer public actual class ControlVisionPlugin : VisionPlugin(), ElementVisionRenderer { override val tag: PluginTag get() = Companion.tag @@ -21,7 +20,7 @@ public actual class ControlVisionPlugin : VisionPlugin(), ElementVisionRenderer TODO("Not yet implemented") } - override fun render(element: Element, client: VisionClient, name: Name, vision: Vision, meta: Meta) { + override fun render(element: Element, name: Name, vision: Vision, meta: Meta) { TODO("Not yet implemented") } diff --git a/controls-vision/src/jsMain/kotlin/client.kt b/controls-vision/src/jsMain/kotlin/client.kt index a835f9a..78da2e8 100644 --- a/controls-vision/src/jsMain/kotlin/client.kt +++ b/controls-vision/src/jsMain/kotlin/client.kt @@ -1,8 +1,8 @@ package space.kscience.controls.vision +import space.kscience.visionforge.html.runVisionClient import space.kscience.visionforge.markup.MarkupPlugin import space.kscience.visionforge.plotly.PlotlyPlugin -import space.kscience.visionforge.runVisionClient public fun main(): Unit = runVisionClient { plugin(PlotlyPlugin) diff --git a/demo/all-things/build.gradle.kts b/demo/all-things/build.gradle.kts index 6888d35..1496f67 100644 --- a/demo/all-things/build.gradle.kts +++ b/demo/all-things/build.gradle.kts @@ -24,7 +24,7 @@ dependencies { implementation("io.ktor:ktor-client-cio:$ktorVersion") implementation("no.tornado:tornadofx:1.7.20") - implementation("space.kscience:plotlykt-server:0.6.1") + implementation("space.kscience:plotlykt-server:0.7.1") // implementation("com.github.Ricky12Awesome:json-schema-serialization:0.6.6") implementation(spclibs.logback.classic) } diff --git a/demo/all-things/src/main/kotlin/space/kscience/controls/demo/DemoDevice.kt b/demo/all-things/src/main/kotlin/space/kscience/controls/demo/DemoDevice.kt index 657d275..5cf1b28 100644 --- a/demo/all-things/src/main/kotlin/space/kscience/controls/demo/DemoDevice.kt +++ b/demo/all-things/src/main/kotlin/space/kscience/controls/demo/DemoDevice.kt @@ -7,9 +7,9 @@ import space.kscience.controls.spec.* import space.kscience.dataforge.context.Context import space.kscience.dataforge.context.Factory import space.kscience.dataforge.meta.Meta +import space.kscience.dataforge.meta.MetaConverter import space.kscience.dataforge.meta.ValueType import space.kscience.dataforge.meta.descriptors.value -import space.kscience.dataforge.meta.transformations.MetaConverter import java.time.Instant import kotlin.math.cos import kotlin.math.sin diff --git a/demo/car/src/main/kotlin/space/kscience/controls/demo/car/MagixVirtualCar.kt b/demo/car/src/main/kotlin/space/kscience/controls/demo/car/MagixVirtualCar.kt index 2c5d65a..27ea243 100644 --- a/demo/car/src/main/kotlin/space/kscience/controls/demo/car/MagixVirtualCar.kt +++ b/demo/car/src/main/kotlin/space/kscience/controls/demo/car/MagixVirtualCar.kt @@ -22,7 +22,7 @@ class MagixVirtualCar(context: Context, meta: Meta) : VirtualCar(context, meta) (payload as? PropertyChangedMessage)?.let { message -> if (message.sourceDevice == Name.parse("virtual-car")) { when (message.property) { - "acceleration" -> write(IVirtualCar.acceleration, Vector2D.metaToObject(message.value)) + "acceleration" -> write(IVirtualCar.acceleration, Vector2D.read(message.value)) } } } diff --git a/demo/car/src/main/kotlin/space/kscience/controls/demo/car/VirtualCar.kt b/demo/car/src/main/kotlin/space/kscience/controls/demo/car/VirtualCar.kt index 05bb2f0..86564a5 100644 --- a/demo/car/src/main/kotlin/space/kscience/controls/demo/car/VirtualCar.kt +++ b/demo/car/src/main/kotlin/space/kscience/controls/demo/car/VirtualCar.kt @@ -11,34 +11,26 @@ import space.kscience.controls.spec.doRecurring import space.kscience.controls.spec.read import space.kscience.dataforge.context.Context import space.kscience.dataforge.context.Factory -import space.kscience.dataforge.meta.Meta -import space.kscience.dataforge.meta.MetaRepr -import space.kscience.dataforge.meta.double -import space.kscience.dataforge.meta.get -import space.kscience.dataforge.meta.transformations.MetaConverter +import space.kscience.dataforge.meta.* import kotlin.math.pow -import kotlin.reflect.KType -import kotlin.reflect.typeOf import kotlin.time.Duration import kotlin.time.Duration.Companion.milliseconds import kotlin.time.ExperimentalTime data class Vector2D(var x: Double = 0.0, var y: Double = 0.0) : MetaRepr { - override fun toMeta(): Meta = objectToMeta(this) + override fun toMeta(): Meta = convert(this) operator fun div(arg: Double): Vector2D = Vector2D(x / arg, y / arg) companion object CoordinatesMetaConverter : MetaConverter { - override val type: KType = typeOf() - - override fun metaToObjectOrNull(meta: Meta): Vector2D = Vector2D( - meta["x"].double ?: 0.0, - meta["y"].double ?: 0.0 + override fun readOrNull(source: Meta): Vector2D = Vector2D( + source["x"].double ?: 0.0, + source["y"].double ?: 0.0 ) - override fun objectToMeta(obj: Vector2D): Meta = Meta { + override fun convert(obj: Vector2D): Meta = Meta { "x" put obj.x "y" put obj.y } diff --git a/demo/mks-pdr900/src/main/kotlin/center/sciprog/devices/mks/MksPdr900Device.kt b/demo/mks-pdr900/src/main/kotlin/center/sciprog/devices/mks/MksPdr900Device.kt index cb8030c..1d48553 100644 --- a/demo/mks-pdr900/src/main/kotlin/center/sciprog/devices/mks/MksPdr900Device.kt +++ b/demo/mks-pdr900/src/main/kotlin/center/sciprog/devices/mks/MksPdr900Device.kt @@ -10,9 +10,9 @@ import space.kscience.dataforge.context.Context import space.kscience.dataforge.context.Factory import space.kscience.dataforge.context.request import space.kscience.dataforge.meta.Meta +import space.kscience.dataforge.meta.MetaConverter import space.kscience.dataforge.meta.get import space.kscience.dataforge.meta.int -import space.kscience.dataforge.meta.transformations.MetaConverter //TODO this device is not tested @@ -94,7 +94,7 @@ class MksPdr900Device(context: Context, meta: Meta) : DeviceBySpec