Java rsocket bindings
This commit is contained in:
parent
b883bece48
commit
cb22374da5
@ -31,7 +31,7 @@ Among other things, you can:
|
||||
### `dataforge-control-core` module packages
|
||||
|
||||
- `api` - defines API for device management. The main class here is
|
||||
[`Device`](dataforge-device-core/src/commonMain/kotlin/hep/dataforge/control/api/Device.kt).
|
||||
[`Device`](controls-core/src/commonMain/kotlin/hep/dataforge/control/api/Device.kt).
|
||||
Generally, a Device has Properties that can be read and written. Also, some Actions
|
||||
can optionally be applied on a device (may or may not affect properties).
|
||||
|
||||
|
@ -4,28 +4,26 @@ plugins {
|
||||
kotlin("js") apply false
|
||||
}
|
||||
|
||||
val dataforgeVersion: String by extra("0.2.1-dev-2")
|
||||
val ktorVersion: String by extra("1.5.0")
|
||||
val dataforgeVersion: String by extra("0.3.0")
|
||||
val ktorVersion: String by extra(ru.mipt.npm.gradle.KScienceVersions.ktorVersion)
|
||||
val rsocketVersion by extra("0.12.0")
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
mavenLocal()
|
||||
//maven("https://dl.bintray.com/pdvrieze/maven")
|
||||
//maven("http://maven.jzy3d.org/releases")
|
||||
maven("https://kotlin.bintray.com/js-externals")
|
||||
maven("https://maven.pkg.github.com/altavir/kotlin-logging/")
|
||||
//maven("https://dl.bintray.com/rsocket-admin/RSocket")
|
||||
maven("https://dl.bintray.com/rsocket-admin/RSocket")
|
||||
//maven("https://maven.pkg.github.com/altavir/ktor-client-sse")
|
||||
}
|
||||
|
||||
group = "hep.dataforge"
|
||||
group = "ru.mipt.npm"
|
||||
version = "0.1.0"
|
||||
}
|
||||
|
||||
ksciencePublish {
|
||||
githubProject = "controls.kt"
|
||||
bintrayRepo = "dataforge"
|
||||
bintrayRepo = "kscience"
|
||||
}
|
||||
|
||||
apiValidation {
|
||||
|
@ -4,7 +4,6 @@ plugins {
|
||||
}
|
||||
|
||||
val dataforgeVersion: String by rootProject.extra
|
||||
val ktorVersion: String by rootProject.extra
|
||||
|
||||
kscience {
|
||||
useCoroutines("1.4.1")
|
@ -4,7 +4,7 @@ import hep.dataforge.context.ContextAware
|
||||
import hep.dataforge.control.api.Device.Companion.DEVICE_TARGET
|
||||
import hep.dataforge.meta.Meta
|
||||
import hep.dataforge.meta.MetaItem
|
||||
import hep.dataforge.provider.Type
|
||||
import hep.dataforge.misc.Type
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.cancel
|
||||
import kotlinx.coroutines.flow.SharedFlow
|
||||
@ -35,7 +35,7 @@ public interface Device : Closeable, ContextAware {
|
||||
* Get the value of the property or throw error if property in not defined.
|
||||
* Suspend if property value is not available
|
||||
*/
|
||||
public suspend fun getProperty(propertyName: String): MetaItem<*>?
|
||||
public suspend fun getProperty(propertyName: String): MetaItem?
|
||||
|
||||
/**
|
||||
* Invalidate property and force recalculate
|
||||
@ -46,18 +46,18 @@ public interface Device : Closeable, ContextAware {
|
||||
* Set property [value] for a property with name [propertyName].
|
||||
* In rare cases could suspend if the [Device] supports command queue and it is full at the moment.
|
||||
*/
|
||||
public suspend fun setProperty(propertyName: String, value: MetaItem<*>)
|
||||
public suspend fun setProperty(propertyName: String, value: MetaItem)
|
||||
|
||||
/**
|
||||
* The [SharedFlow] of property changes
|
||||
*/
|
||||
public val propertyFlow: SharedFlow<Pair<String, MetaItem<*>>>
|
||||
public val propertyFlow: SharedFlow<Pair<String, MetaItem>>
|
||||
|
||||
/**
|
||||
* Send an action request and suspend caller while request is being processed.
|
||||
* Could return null if request does not return a meaningful answer.
|
||||
*/
|
||||
public suspend fun execute(action: String, argument: MetaItem<*>? = null): MetaItem<*>?
|
||||
public suspend fun execute(action: String, argument: MetaItem? = null): MetaItem?
|
||||
|
||||
override fun close() {
|
||||
scope.cancel("The device is closed")
|
||||
@ -74,4 +74,4 @@ public suspend fun Device.getState(): Meta = Meta{
|
||||
}
|
||||
}
|
||||
|
||||
//public suspend fun Device.execute(name: String, meta: Meta?): MetaItem<*>? = execute(name, meta?.let { MetaItem.NodeItem(it) })
|
||||
//public suspend fun Device.execute(name: String, meta: Meta?): MetaItem? = execute(name, meta?.let { MetaItemNode(it) })
|
@ -54,14 +54,14 @@ public operator fun DeviceHub.get(name: Name): Device? = when {
|
||||
|
||||
public operator fun DeviceHub.get(deviceName: String): Device? = get(deviceName.toName())
|
||||
|
||||
public suspend fun DeviceHub.getProperty(deviceName: Name, propertyName: String): MetaItem<*>? =
|
||||
public suspend fun DeviceHub.getProperty(deviceName: Name, propertyName: String): MetaItem? =
|
||||
this[deviceName]?.getProperty(propertyName)
|
||||
|
||||
public suspend fun DeviceHub.setProperty(deviceName: Name, propertyName: String, value: MetaItem<*>) {
|
||||
public suspend fun DeviceHub.setProperty(deviceName: Name, propertyName: String, value: MetaItem) {
|
||||
this[deviceName]?.setProperty(propertyName, value)
|
||||
}
|
||||
|
||||
public suspend fun DeviceHub.execute(deviceName: Name, command: String, argument: MetaItem<*>?): MetaItem<*>? =
|
||||
public suspend fun DeviceHub.execute(deviceName: Name, command: String, argument: MetaItem?): MetaItem? =
|
||||
this[deviceName]?.execute(command, argument)
|
||||
|
||||
|
@ -8,7 +8,7 @@ import hep.dataforge.meta.asMetaItem
|
||||
public interface DeviceAction {
|
||||
public val name: String
|
||||
public val descriptor: ActionDescriptor
|
||||
public suspend operator fun invoke(arg: MetaItem<*>? = null): MetaItem<*>?
|
||||
public suspend operator fun invoke(arg: MetaItem? = null): MetaItem?
|
||||
}
|
||||
|
||||
public suspend operator fun DeviceAction.invoke(meta: Meta): MetaItem<*>? = invoke(meta.asMetaItem())
|
||||
public suspend operator fun DeviceAction.invoke(meta: Meta): MetaItem? = invoke(meta.asMetaItem())
|
@ -4,8 +4,8 @@ import hep.dataforge.context.Context
|
||||
import hep.dataforge.control.api.ActionDescriptor
|
||||
import hep.dataforge.control.api.Device
|
||||
import hep.dataforge.control.api.PropertyDescriptor
|
||||
import hep.dataforge.meta.DFExperimental
|
||||
import hep.dataforge.meta.MetaItem
|
||||
import hep.dataforge.misc.DFExperimental
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
@ -29,9 +29,9 @@ public abstract class DeviceBase(override val context: Context) : Device {
|
||||
private val _actions = HashMap<String, DeviceAction>()
|
||||
public val actions: Map<String, DeviceAction> get() = _actions
|
||||
|
||||
private val sharedPropertyFlow = MutableSharedFlow<Pair<String, MetaItem<*>>>()
|
||||
private val sharedPropertyFlow = MutableSharedFlow<Pair<String, MetaItem>>()
|
||||
|
||||
override val propertyFlow: SharedFlow<Pair<String, MetaItem<*>>> get() = sharedPropertyFlow
|
||||
override val propertyFlow: SharedFlow<Pair<String, MetaItem>> get() = sharedPropertyFlow
|
||||
|
||||
private val sharedLogFlow = MutableSharedFlow<LogEntry>()
|
||||
|
||||
@ -62,47 +62,47 @@ public abstract class DeviceBase(override val context: Context) : Device {
|
||||
_actions[name] = action
|
||||
}
|
||||
|
||||
override suspend fun getProperty(propertyName: String): MetaItem<*> =
|
||||
override suspend fun getProperty(propertyName: String): MetaItem =
|
||||
(_properties[propertyName] ?: error("Property with name $propertyName not defined")).read()
|
||||
|
||||
override suspend fun invalidateProperty(propertyName: String) {
|
||||
(_properties[propertyName] ?: error("Property with name $propertyName not defined")).invalidate()
|
||||
}
|
||||
|
||||
override suspend fun setProperty(propertyName: String, value: MetaItem<*>) {
|
||||
override suspend fun setProperty(propertyName: String, value: MetaItem) {
|
||||
(_properties[propertyName] as? DeviceProperty ?: error("Property with name $propertyName not defined")).write(
|
||||
value
|
||||
)
|
||||
}
|
||||
|
||||
override suspend fun execute(action: String, argument: MetaItem<*>?): MetaItem<*>? =
|
||||
override suspend fun execute(action: String, argument: MetaItem?): MetaItem? =
|
||||
(_actions[action] ?: error("Request with name $action not defined")).invoke(argument)
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
private open inner class BasicReadOnlyDeviceProperty(
|
||||
override val name: String,
|
||||
default: MetaItem<*>?,
|
||||
default: MetaItem?,
|
||||
override val descriptor: PropertyDescriptor,
|
||||
private val getter: suspend (before: MetaItem<*>?) -> MetaItem<*>,
|
||||
private val getter: suspend (before: MetaItem?) -> MetaItem,
|
||||
) : ReadOnlyDeviceProperty {
|
||||
|
||||
override val scope: CoroutineScope get() = this@DeviceBase.scope
|
||||
|
||||
private val state: MutableStateFlow<MetaItem<*>?> = MutableStateFlow(default)
|
||||
override val value: MetaItem<*>? get() = state.value
|
||||
private val state: MutableStateFlow<MetaItem?> = MutableStateFlow(default)
|
||||
override val value: MetaItem? get() = state.value
|
||||
|
||||
override suspend fun invalidate() {
|
||||
state.value = null
|
||||
}
|
||||
|
||||
override fun updateLogical(item: MetaItem<*>) {
|
||||
override fun updateLogical(item: MetaItem) {
|
||||
state.value = item
|
||||
scope.launch {
|
||||
sharedPropertyFlow.emit(Pair(name, item))
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun read(force: Boolean): MetaItem<*> {
|
||||
override suspend fun read(force: Boolean): MetaItem {
|
||||
//backup current value
|
||||
val currentValue = value
|
||||
return if (force || currentValue == null) {
|
||||
@ -118,7 +118,7 @@ public abstract class DeviceBase(override val context: Context) : Device {
|
||||
}
|
||||
}
|
||||
|
||||
override fun flow(): StateFlow<MetaItem<*>?> = state
|
||||
override fun flow(): StateFlow<MetaItem?> = state
|
||||
}
|
||||
|
||||
/**
|
||||
@ -126,9 +126,9 @@ public abstract class DeviceBase(override val context: Context) : Device {
|
||||
*/
|
||||
public fun createReadOnlyProperty(
|
||||
name: String,
|
||||
default: MetaItem<*>?,
|
||||
default: MetaItem?,
|
||||
descriptorBuilder: PropertyDescriptor.() -> Unit = {},
|
||||
getter: suspend (MetaItem<*>?) -> MetaItem<*>,
|
||||
getter: suspend (MetaItem?) -> MetaItem,
|
||||
): ReadOnlyDeviceProperty {
|
||||
val property = BasicReadOnlyDeviceProperty(
|
||||
name,
|
||||
@ -143,13 +143,13 @@ public abstract class DeviceBase(override val context: Context) : Device {
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
private inner class BasicDeviceProperty(
|
||||
name: String,
|
||||
default: MetaItem<*>?,
|
||||
default: MetaItem?,
|
||||
descriptor: PropertyDescriptor,
|
||||
getter: suspend (MetaItem<*>?) -> MetaItem<*>,
|
||||
private val setter: suspend (oldValue: MetaItem<*>?, newValue: MetaItem<*>) -> MetaItem<*>?,
|
||||
getter: suspend (MetaItem?) -> MetaItem,
|
||||
private val setter: suspend (oldValue: MetaItem?, newValue: MetaItem) -> MetaItem?,
|
||||
) : BasicReadOnlyDeviceProperty(name, default, descriptor, getter), DeviceProperty {
|
||||
|
||||
override var value: MetaItem<*>?
|
||||
override var value: MetaItem?
|
||||
get() = super.value
|
||||
set(value) {
|
||||
scope.launch {
|
||||
@ -163,7 +163,7 @@ public abstract class DeviceBase(override val context: Context) : Device {
|
||||
|
||||
private val writeLock = Mutex()
|
||||
|
||||
override suspend fun write(item: MetaItem<*>) {
|
||||
override suspend fun write(item: MetaItem) {
|
||||
writeLock.withLock {
|
||||
//fast return if value is not changed
|
||||
if (item == value) return@withLock
|
||||
@ -183,10 +183,10 @@ public abstract class DeviceBase(override val context: Context) : Device {
|
||||
*/
|
||||
internal fun createMutableProperty(
|
||||
name: String,
|
||||
default: MetaItem<*>?,
|
||||
default: MetaItem?,
|
||||
descriptorBuilder: PropertyDescriptor.() -> Unit = {},
|
||||
getter: suspend (MetaItem<*>?) -> MetaItem<*>,
|
||||
setter: suspend (oldValue: MetaItem<*>?, newValue: MetaItem<*>) -> MetaItem<*>?,
|
||||
getter: suspend (MetaItem?) -> MetaItem,
|
||||
setter: suspend (oldValue: MetaItem?, newValue: MetaItem) -> MetaItem?,
|
||||
): DeviceProperty {
|
||||
val property = BasicDeviceProperty(
|
||||
name,
|
||||
@ -205,9 +205,9 @@ public abstract class DeviceBase(override val context: Context) : Device {
|
||||
private inner class BasicDeviceAction(
|
||||
override val name: String,
|
||||
override val descriptor: ActionDescriptor,
|
||||
private val block: suspend (MetaItem<*>?) -> MetaItem<*>?,
|
||||
private val block: suspend (MetaItem?) -> MetaItem?,
|
||||
) : DeviceAction {
|
||||
override suspend fun invoke(arg: MetaItem<*>?): MetaItem<*>? =
|
||||
override suspend fun invoke(arg: MetaItem?): MetaItem? =
|
||||
withContext(scope.coroutineContext + SupervisorJob(scope.coroutineContext[Job])) {
|
||||
block(arg)
|
||||
}
|
||||
@ -219,7 +219,7 @@ public abstract class DeviceBase(override val context: Context) : Device {
|
||||
internal fun createAction(
|
||||
name: String,
|
||||
descriptorBuilder: ActionDescriptor.() -> Unit = {},
|
||||
block: suspend (MetaItem<*>?) -> MetaItem<*>?,
|
||||
block: suspend (MetaItem?) -> MetaItem?,
|
||||
): DeviceAction {
|
||||
val action = BasicDeviceAction(name, ActionDescriptor(name).apply(descriptorBuilder), block)
|
||||
registerAction(name, action)
|
@ -30,24 +30,24 @@ public interface ReadOnlyDeviceProperty {
|
||||
/**
|
||||
* Directly update property logical value and notify listener without writing it to device
|
||||
*/
|
||||
public fun updateLogical(item: MetaItem<*>)
|
||||
public fun updateLogical(item: MetaItem)
|
||||
|
||||
/**
|
||||
* Get cached value and return null if value is invalid or not initialized
|
||||
*/
|
||||
public val value: MetaItem<*>?
|
||||
public val value: MetaItem?
|
||||
|
||||
/**
|
||||
* Read value either from cache if cache is valid or directly from physical device.
|
||||
* If [force], reread from physical state even if the logical state is set.
|
||||
*/
|
||||
public suspend fun read(force: Boolean = false): MetaItem<*>
|
||||
public suspend fun read(force: Boolean = false): MetaItem
|
||||
|
||||
/**
|
||||
* The [Flow] representing future logical states of the property.
|
||||
* Produces null when the state is invalidated
|
||||
*/
|
||||
public fun flow(): Flow<MetaItem<*>?>
|
||||
public fun flow(): Flow<MetaItem?>
|
||||
}
|
||||
|
||||
|
||||
@ -65,10 +65,10 @@ public fun ReadOnlyDeviceProperty.readEvery(duration: Duration): Job = scope.lau
|
||||
* A writeable device property with non-suspended write
|
||||
*/
|
||||
public interface DeviceProperty : ReadOnlyDeviceProperty {
|
||||
override var value: MetaItem<*>?
|
||||
override var value: MetaItem?
|
||||
|
||||
/**
|
||||
* Write value to physical device. Invalidates logical value, but does not update it automatically
|
||||
*/
|
||||
public suspend fun write(item: MetaItem<*>)
|
||||
public suspend fun write(item: MetaItem)
|
||||
}
|
@ -32,7 +32,7 @@ public class TypedDeviceProperty<T : Any>(
|
||||
converter: MetaConverter<T>,
|
||||
) : TypedReadOnlyDeviceProperty<T>(property, converter), DeviceProperty {
|
||||
|
||||
override var value: MetaItem<*>?
|
||||
override var value: MetaItem?
|
||||
get() = property.value
|
||||
set(arg) {
|
||||
property.value = arg
|
||||
@ -44,7 +44,7 @@ public class TypedDeviceProperty<T : Any>(
|
||||
property.value = arg?.let { converter.objectToMetaItem(arg) }
|
||||
}
|
||||
|
||||
override suspend fun write(item: MetaItem<*>) {
|
||||
override suspend fun write(item: MetaItem) {
|
||||
property.write(item)
|
||||
}
|
||||
|
@ -3,6 +3,8 @@ package hep.dataforge.control.base
|
||||
import hep.dataforge.control.api.ActionDescriptor
|
||||
import hep.dataforge.meta.MetaBuilder
|
||||
import hep.dataforge.meta.MetaItem
|
||||
import hep.dataforge.meta.MetaItemNode
|
||||
import hep.dataforge.meta.MetaItemValue
|
||||
import hep.dataforge.values.Value
|
||||
import kotlin.properties.PropertyDelegateProvider
|
||||
import kotlin.properties.ReadOnlyProperty
|
||||
@ -20,7 +22,7 @@ public typealias ActionDelegate = ReadOnlyProperty<DeviceBase, DeviceAction>
|
||||
private class ActionProvider<D : DeviceBase>(
|
||||
val owner: D,
|
||||
val descriptorBuilder: ActionDescriptor.() -> Unit = {},
|
||||
val block: suspend (MetaItem<*>?) -> MetaItem<*>?,
|
||||
val block: suspend (MetaItem?) -> MetaItem?,
|
||||
) : PropertyDelegateProvider<D, ActionDelegate> {
|
||||
override operator fun provideDelegate(thisRef: D, property: KProperty<*>): ActionDelegate {
|
||||
val name = property.name
|
||||
@ -31,28 +33,28 @@ private class ActionProvider<D : DeviceBase>(
|
||||
|
||||
public fun DeviceBase.requesting(
|
||||
descriptorBuilder: ActionDescriptor.() -> Unit = {},
|
||||
action: suspend (MetaItem<*>?) -> MetaItem<*>?,
|
||||
action: suspend (MetaItem?) -> MetaItem?,
|
||||
): PropertyDelegateProvider<DeviceBase, ActionDelegate> = ActionProvider(this, descriptorBuilder, action)
|
||||
|
||||
public fun <D : DeviceBase> D.requestingValue(
|
||||
descriptorBuilder: ActionDescriptor.() -> Unit = {},
|
||||
action: suspend (MetaItem<*>?) -> Any?,
|
||||
action: suspend (MetaItem?) -> Any?,
|
||||
): PropertyDelegateProvider<D, ActionDelegate> = ActionProvider(this, descriptorBuilder) {
|
||||
val res = action(it)
|
||||
MetaItem.ValueItem(Value.of(res))
|
||||
MetaItemValue(Value.of(res))
|
||||
}
|
||||
|
||||
public fun <D : DeviceBase> D.requestingMeta(
|
||||
descriptorBuilder: ActionDescriptor.() -> Unit = {},
|
||||
action: suspend MetaBuilder.(MetaItem<*>?) -> Unit,
|
||||
action: suspend MetaBuilder.(MetaItem?) -> Unit,
|
||||
): PropertyDelegateProvider<D, ActionDelegate> = ActionProvider(this, descriptorBuilder) {
|
||||
val res = MetaBuilder().apply { action(it) }
|
||||
MetaItem.NodeItem(res)
|
||||
MetaItemNode(res)
|
||||
}
|
||||
|
||||
public fun DeviceBase.acting(
|
||||
descriptorBuilder: ActionDescriptor.() -> Unit = {},
|
||||
action: suspend (MetaItem<*>?) -> Unit,
|
||||
action: suspend (MetaItem?) -> Unit,
|
||||
): PropertyDelegateProvider<DeviceBase, ActionDelegate> = ActionProvider(this, descriptorBuilder) {
|
||||
action(it)
|
||||
null
|
@ -29,9 +29,9 @@ public typealias TypedReadOnlyPropertyDelegate<T> = ReadOnlyProperty<DeviceBase,
|
||||
|
||||
private class ReadOnlyDevicePropertyProvider<D : DeviceBase>(
|
||||
val owner: D,
|
||||
val default: MetaItem<*>?,
|
||||
val default: MetaItem?,
|
||||
val descriptorBuilder: PropertyDescriptor.() -> Unit = {},
|
||||
private val getter: suspend (MetaItem<*>?) -> MetaItem<*>,
|
||||
private val getter: suspend (MetaItem?) -> MetaItem,
|
||||
) : PropertyDelegateProvider<D, ReadOnlyPropertyDelegate> {
|
||||
|
||||
override operator fun provideDelegate(thisRef: D, property: KProperty<*>): ReadOnlyPropertyDelegate {
|
||||
@ -43,10 +43,10 @@ private class ReadOnlyDevicePropertyProvider<D : DeviceBase>(
|
||||
|
||||
private class TypedReadOnlyDevicePropertyProvider<D : DeviceBase, T : Any>(
|
||||
val owner: D,
|
||||
val default: MetaItem<*>?,
|
||||
val default: MetaItem?,
|
||||
val converter: MetaConverter<T>,
|
||||
val descriptorBuilder: PropertyDescriptor.() -> Unit = {},
|
||||
private val getter: suspend (MetaItem<*>?) -> MetaItem<*>,
|
||||
private val getter: suspend (MetaItem?) -> MetaItem,
|
||||
) : PropertyDelegateProvider<D, TypedReadOnlyPropertyDelegate<T>> {
|
||||
|
||||
override operator fun provideDelegate(thisRef: D, property: KProperty<*>): TypedReadOnlyPropertyDelegate<T> {
|
||||
@ -57,9 +57,9 @@ private class TypedReadOnlyDevicePropertyProvider<D : DeviceBase, T : Any>(
|
||||
}
|
||||
|
||||
public fun DeviceBase.reading(
|
||||
default: MetaItem<*>? = null,
|
||||
default: MetaItem? = null,
|
||||
descriptorBuilder: PropertyDescriptor.() -> Unit = {},
|
||||
getter: suspend (MetaItem<*>?) -> MetaItem<*>,
|
||||
getter: suspend (MetaItem?) -> MetaItem,
|
||||
): PropertyDelegateProvider<DeviceBase, ReadOnlyPropertyDelegate> = ReadOnlyDevicePropertyProvider(
|
||||
this,
|
||||
default,
|
||||
@ -73,9 +73,9 @@ public fun DeviceBase.readingValue(
|
||||
getter: suspend () -> Any?,
|
||||
): PropertyDelegateProvider<DeviceBase, ReadOnlyPropertyDelegate> = ReadOnlyDevicePropertyProvider(
|
||||
this,
|
||||
default?.let { MetaItem.ValueItem(it) },
|
||||
default?.let { MetaItemValue(it) },
|
||||
descriptorBuilder,
|
||||
getter = { MetaItem.ValueItem(Value.of(getter())) }
|
||||
getter = { MetaItemValue(Value.of(getter())) }
|
||||
)
|
||||
|
||||
public fun DeviceBase.readingNumber(
|
||||
@ -84,12 +84,12 @@ public fun DeviceBase.readingNumber(
|
||||
getter: suspend () -> Number,
|
||||
): PropertyDelegateProvider<DeviceBase, TypedReadOnlyPropertyDelegate<Number>> = TypedReadOnlyDevicePropertyProvider(
|
||||
this,
|
||||
default?.let { MetaItem.ValueItem(it.asValue()) },
|
||||
default?.let { MetaItemValue(it.asValue()) },
|
||||
MetaConverter.number,
|
||||
descriptorBuilder,
|
||||
getter = {
|
||||
val number = getter()
|
||||
MetaItem.ValueItem(number.asValue())
|
||||
MetaItemValue(number.asValue())
|
||||
}
|
||||
)
|
||||
|
||||
@ -99,12 +99,12 @@ public fun DeviceBase.readingDouble(
|
||||
getter: suspend () -> Double,
|
||||
): PropertyDelegateProvider<DeviceBase, TypedReadOnlyPropertyDelegate<Double>> = TypedReadOnlyDevicePropertyProvider(
|
||||
this,
|
||||
default?.let { MetaItem.ValueItem(it.asValue()) },
|
||||
default?.let { MetaItemValue(it.asValue()) },
|
||||
MetaConverter.double,
|
||||
descriptorBuilder,
|
||||
getter = {
|
||||
val number = getter()
|
||||
MetaItem.ValueItem(number.asValue())
|
||||
MetaItemValue(number.asValue())
|
||||
}
|
||||
)
|
||||
|
||||
@ -114,12 +114,12 @@ public fun DeviceBase.readingString(
|
||||
getter: suspend () -> String,
|
||||
): PropertyDelegateProvider<DeviceBase, TypedReadOnlyPropertyDelegate<String>> = TypedReadOnlyDevicePropertyProvider(
|
||||
this,
|
||||
default?.let { MetaItem.ValueItem(it.asValue()) },
|
||||
default?.let { MetaItemValue(it.asValue()) },
|
||||
MetaConverter.string,
|
||||
descriptorBuilder,
|
||||
getter = {
|
||||
val number = getter()
|
||||
MetaItem.ValueItem(number.asValue())
|
||||
MetaItemValue(number.asValue())
|
||||
}
|
||||
)
|
||||
|
||||
@ -129,12 +129,12 @@ public fun DeviceBase.readingBoolean(
|
||||
getter: suspend () -> Boolean,
|
||||
): PropertyDelegateProvider<DeviceBase, TypedReadOnlyPropertyDelegate<Boolean>> = TypedReadOnlyDevicePropertyProvider(
|
||||
this,
|
||||
default?.let { MetaItem.ValueItem(it.asValue()) },
|
||||
default?.let { MetaItemValue(it.asValue()) },
|
||||
MetaConverter.boolean,
|
||||
descriptorBuilder,
|
||||
getter = {
|
||||
val boolean = getter()
|
||||
MetaItem.ValueItem(boolean.asValue())
|
||||
MetaItemValue(boolean.asValue())
|
||||
}
|
||||
)
|
||||
|
||||
@ -144,11 +144,11 @@ public fun DeviceBase.readingMeta(
|
||||
getter: suspend MetaBuilder.() -> Unit,
|
||||
): PropertyDelegateProvider<DeviceBase, TypedReadOnlyPropertyDelegate<Meta>> = TypedReadOnlyDevicePropertyProvider(
|
||||
this,
|
||||
default?.let { MetaItem.NodeItem(it) },
|
||||
default?.let { MetaItemNode(it) },
|
||||
MetaConverter.meta,
|
||||
descriptorBuilder,
|
||||
getter = {
|
||||
MetaItem.NodeItem(MetaBuilder().apply { getter() })
|
||||
MetaItemNode(MetaBuilder().apply { getter() })
|
||||
}
|
||||
)
|
||||
|
||||
@ -170,10 +170,10 @@ public typealias TypedPropertyDelegate<T> = ReadOnlyProperty<DeviceBase, TypedDe
|
||||
|
||||
private class DevicePropertyProvider<D : DeviceBase>(
|
||||
val owner: D,
|
||||
val default: MetaItem<*>?,
|
||||
val default: MetaItem?,
|
||||
val descriptorBuilder: PropertyDescriptor.() -> Unit = {},
|
||||
private val getter: suspend (MetaItem<*>?) -> MetaItem<*>,
|
||||
private val setter: suspend (oldValue: MetaItem<*>?, newValue: MetaItem<*>) -> MetaItem<*>?,
|
||||
private val getter: suspend (MetaItem?) -> MetaItem,
|
||||
private val setter: suspend (oldValue: MetaItem?, newValue: MetaItem) -> MetaItem?,
|
||||
) : PropertyDelegateProvider<D, PropertyDelegate> {
|
||||
|
||||
override operator fun provideDelegate(thisRef: D, property: KProperty<*>): PropertyDelegate {
|
||||
@ -185,11 +185,11 @@ private class DevicePropertyProvider<D : DeviceBase>(
|
||||
|
||||
private class TypedDevicePropertyProvider<D : DeviceBase, T : Any>(
|
||||
val owner: D,
|
||||
val default: MetaItem<*>?,
|
||||
val default: MetaItem?,
|
||||
val converter: MetaConverter<T>,
|
||||
val descriptorBuilder: PropertyDescriptor.() -> Unit = {},
|
||||
private val getter: suspend (MetaItem<*>?) -> MetaItem<*>,
|
||||
private val setter: suspend (oldValue: MetaItem<*>?, newValue: MetaItem<*>) -> MetaItem<*>?,
|
||||
private val getter: suspend (MetaItem?) -> MetaItem,
|
||||
private val setter: suspend (oldValue: MetaItem?, newValue: MetaItem) -> MetaItem?,
|
||||
) : PropertyDelegateProvider<D, TypedPropertyDelegate<T>> {
|
||||
|
||||
override operator fun provideDelegate(thisRef: D, property: KProperty<*>): TypedPropertyDelegate<T> {
|
||||
@ -200,10 +200,10 @@ private class TypedDevicePropertyProvider<D : DeviceBase, T : Any>(
|
||||
}
|
||||
|
||||
public fun DeviceBase.writing(
|
||||
default: MetaItem<*>? = null,
|
||||
default: MetaItem? = null,
|
||||
descriptorBuilder: PropertyDescriptor.() -> Unit = {},
|
||||
getter: suspend (MetaItem<*>?) -> MetaItem<*>,
|
||||
setter: suspend (oldValue: MetaItem<*>?, newValue: MetaItem<*>) -> MetaItem<*>?,
|
||||
getter: suspend (MetaItem?) -> MetaItem,
|
||||
setter: suspend (oldValue: MetaItem?, newValue: MetaItem) -> MetaItem?,
|
||||
): PropertyDelegateProvider<DeviceBase, PropertyDelegate> = DevicePropertyProvider(
|
||||
this,
|
||||
default,
|
||||
@ -213,7 +213,7 @@ public fun DeviceBase.writing(
|
||||
)
|
||||
|
||||
public fun DeviceBase.writingVirtual(
|
||||
default: MetaItem<*>,
|
||||
default: MetaItem,
|
||||
descriptorBuilder: PropertyDescriptor.() -> Unit = {},
|
||||
): PropertyDelegateProvider<DeviceBase, PropertyDelegate> = writing(
|
||||
default,
|
||||
@ -226,9 +226,9 @@ public fun DeviceBase.writingVirtual(
|
||||
default: Value,
|
||||
descriptorBuilder: PropertyDescriptor.() -> Unit = {},
|
||||
): PropertyDelegateProvider<DeviceBase, PropertyDelegate> = writing(
|
||||
MetaItem.ValueItem(default),
|
||||
MetaItemValue(default),
|
||||
descriptorBuilder,
|
||||
getter = { it ?: MetaItem.ValueItem(default) },
|
||||
getter = { it ?: MetaItemValue(default) },
|
||||
setter = { _, newItem -> newItem }
|
||||
)
|
||||
|
||||
@ -236,9 +236,9 @@ public fun DeviceBase.writingVirtual(
|
||||
default: Meta,
|
||||
descriptorBuilder: PropertyDescriptor.() -> Unit = {},
|
||||
): PropertyDelegateProvider<DeviceBase, PropertyDelegate> = writing(
|
||||
MetaItem.NodeItem(default),
|
||||
MetaItemNode(default),
|
||||
descriptorBuilder,
|
||||
getter = { it ?: MetaItem.NodeItem(default) },
|
||||
getter = { it ?: MetaItemNode(default) },
|
||||
setter = { _, newItem -> newItem }
|
||||
)
|
||||
|
||||
@ -247,17 +247,17 @@ public fun <D : DeviceBase> D.writingDouble(
|
||||
getter: suspend (Double) -> Double,
|
||||
setter: suspend (oldValue: Double?, newValue: Double) -> Double?,
|
||||
): PropertyDelegateProvider<D, TypedPropertyDelegate<Double>> {
|
||||
val innerGetter: suspend (MetaItem<*>?) -> MetaItem<*> = {
|
||||
MetaItem.ValueItem(getter(it.double ?: Double.NaN).asValue())
|
||||
val innerGetter: suspend (MetaItem?) -> MetaItem = {
|
||||
MetaItemValue(getter(it.double ?: Double.NaN).asValue())
|
||||
}
|
||||
|
||||
val innerSetter: suspend (oldValue: MetaItem<*>?, newValue: MetaItem<*>) -> MetaItem<*>? = { oldValue, newValue ->
|
||||
val innerSetter: suspend (oldValue: MetaItem?, newValue: MetaItem) -> MetaItem? = { oldValue, newValue ->
|
||||
setter(oldValue.double, newValue.double ?: Double.NaN)?.asMetaItem()
|
||||
}
|
||||
|
||||
return TypedDevicePropertyProvider(
|
||||
this,
|
||||
MetaItem.ValueItem(Double.NaN.asValue()),
|
||||
MetaItemValue(Double.NaN.asValue()),
|
||||
MetaConverter.double,
|
||||
descriptorBuilder,
|
||||
innerGetter,
|
||||
@ -270,18 +270,18 @@ public fun <D : DeviceBase> D.writingBoolean(
|
||||
getter: suspend (Boolean?) -> Boolean,
|
||||
setter: suspend (oldValue: Boolean?, newValue: Boolean) -> Boolean?,
|
||||
): PropertyDelegateProvider<D, TypedPropertyDelegate<Boolean>> {
|
||||
val innerGetter: suspend (MetaItem<*>?) -> MetaItem<*> = {
|
||||
MetaItem.ValueItem(getter(it.boolean).asValue())
|
||||
val innerGetter: suspend (MetaItem?) -> MetaItem = {
|
||||
MetaItemValue(getter(it.boolean).asValue())
|
||||
}
|
||||
|
||||
val innerSetter: suspend (oldValue: MetaItem<*>?, newValue: MetaItem<*>) -> MetaItem<*>? = { oldValue, newValue ->
|
||||
val innerSetter: suspend (oldValue: MetaItem?, newValue: MetaItem) -> MetaItem? = { oldValue, newValue ->
|
||||
setter(oldValue.boolean, newValue.boolean ?: error("Can't convert $newValue to boolean"))?.asValue()
|
||||
?.asMetaItem()
|
||||
}
|
||||
|
||||
return TypedDevicePropertyProvider(
|
||||
this,
|
||||
MetaItem.ValueItem(Null),
|
||||
MetaItemValue(Null),
|
||||
MetaConverter.boolean,
|
||||
descriptorBuilder,
|
||||
innerGetter,
|
@ -8,20 +8,20 @@ import kotlin.time.Duration
|
||||
import kotlin.time.DurationUnit
|
||||
import kotlin.time.toDuration
|
||||
|
||||
public fun Double.asMetaItem(): MetaItem.ValueItem = MetaItem.ValueItem(asValue())
|
||||
public fun Double.asMetaItem(): MetaItemValue = MetaItemValue(asValue())
|
||||
|
||||
//TODO to be moved to DF
|
||||
public object DurationConverter : MetaConverter<Duration> {
|
||||
override fun itemToObject(item: MetaItem<*>): Duration = when (item) {
|
||||
is MetaItem.NodeItem -> {
|
||||
override fun itemToObject(item: MetaItem): Duration = when (item) {
|
||||
is MetaItemNode -> {
|
||||
val unit: DurationUnit = item.node["unit"].enum<DurationUnit>() ?: DurationUnit.SECONDS
|
||||
val value = item.node[Meta.VALUE_KEY].double ?: error("No value present for Duration")
|
||||
value.toDuration(unit)
|
||||
}
|
||||
is MetaItem.ValueItem -> item.value.double.toDuration(DurationUnit.SECONDS)
|
||||
is MetaItemValue -> item.value.double.toDuration(DurationUnit.SECONDS)
|
||||
}
|
||||
|
||||
override fun objectToMetaItem(obj: Duration): MetaItem<*> = obj.toDouble(DurationUnit.SECONDS).asMetaItem()
|
||||
override fun objectToMetaItem(obj: Duration): MetaItem = obj.toDouble(DurationUnit.SECONDS).asMetaItem()
|
||||
}
|
||||
|
||||
public val MetaConverter.Companion.duration: MetaConverter<Duration> get() = DurationConverter
|
@ -4,9 +4,9 @@ import hep.dataforge.control.api.Device
|
||||
import hep.dataforge.control.api.DeviceHub
|
||||
import hep.dataforge.control.api.get
|
||||
import hep.dataforge.control.messages.*
|
||||
import hep.dataforge.meta.DFExperimental
|
||||
import hep.dataforge.meta.Meta
|
||||
import hep.dataforge.meta.MetaItem
|
||||
import hep.dataforge.misc.DFExperimental
|
||||
import hep.dataforge.names.Name
|
||||
import hep.dataforge.names.toName
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
@ -21,7 +21,7 @@ public class DeviceController(
|
||||
public val deviceName: String,
|
||||
) {
|
||||
|
||||
private val propertyChanges = device.propertyFlow.map { (propertyName: String, value: MetaItem<*>) ->
|
||||
private val propertyChanges = device.propertyFlow.map { (propertyName: String, value: MetaItem) ->
|
||||
PropertyChangedMessage(
|
||||
sourceDevice = deviceName,
|
||||
property = propertyName,
|
||||
@ -103,12 +103,12 @@ public class DeviceController(
|
||||
val descriptionMeta = Meta {
|
||||
"properties" put {
|
||||
device.propertyDescriptors.map { descriptor ->
|
||||
descriptor.name put descriptor.config
|
||||
descriptor.name put descriptor.toMeta()
|
||||
}
|
||||
}
|
||||
"actions" put {
|
||||
device.actionDescriptors.map { descriptor ->
|
||||
descriptor.name put descriptor.config
|
||||
descriptor.name put descriptor.toMeta()
|
||||
}
|
||||
}
|
||||
}
|
@ -3,7 +3,7 @@ package hep.dataforge.control.controllers
|
||||
import hep.dataforge.control.api.DeviceHub
|
||||
import hep.dataforge.control.api.get
|
||||
import hep.dataforge.control.messages.DeviceMessage
|
||||
import hep.dataforge.meta.DFExperimental
|
||||
import hep.dataforge.misc.DFExperimental
|
||||
import hep.dataforge.names.Name
|
||||
import hep.dataforge.names.toName
|
||||
import kotlinx.coroutines.channels.Channel
|
||||
@ -33,7 +33,7 @@ public class HubController(
|
||||
|
||||
// private val listeners: Map<NameToken, DeviceListener> = hub.devices.mapValues { (deviceNameToken, device) ->
|
||||
// object : DeviceListener {
|
||||
// override fun propertyChanged(propertyName: String, value: MetaItem<*>?) {
|
||||
// override fun propertyChanged(propertyName: String, value: MetaItem?) {
|
||||
// if (value == null) return
|
||||
// scope.launch {
|
||||
// val change = PropertyChangedMessage(
|
@ -42,7 +42,7 @@ public sealed class DeviceMessage {
|
||||
@SerialName("property.changed")
|
||||
public data class PropertyChangedMessage(
|
||||
public val property: String,
|
||||
public val value: MetaItem<*>?,
|
||||
public val value: MetaItem?,
|
||||
override val sourceDevice: String,
|
||||
override val targetDevice: String? = null,
|
||||
override val comment: String? = null,
|
||||
@ -55,7 +55,7 @@ public data class PropertyChangedMessage(
|
||||
@SerialName("property.set")
|
||||
public data class PropertySetMessage(
|
||||
public val property: String,
|
||||
public val value: MetaItem<*>?,
|
||||
public val value: MetaItem?,
|
||||
override val sourceDevice: String? = null,
|
||||
override val targetDevice: String,
|
||||
override val comment: String? = null,
|
||||
@ -104,7 +104,7 @@ public data class DescriptionMessage(
|
||||
@SerialName("action.execute")
|
||||
public data class ActionExecuteMessage(
|
||||
public val action: String,
|
||||
public val argument: MetaItem<*>?,
|
||||
public val argument: MetaItem?,
|
||||
override val sourceDevice: String? = null,
|
||||
override val targetDevice: String,
|
||||
override val comment: String? = null,
|
||||
@ -117,7 +117,7 @@ public data class ActionExecuteMessage(
|
||||
@SerialName("action.result")
|
||||
public data class ActionResultMessage(
|
||||
public val action: String,
|
||||
public val result: MetaItem<*>?,
|
||||
public val result: MetaItem?,
|
||||
override val sourceDevice: String,
|
||||
override val targetDevice: String? = null,
|
||||
override val comment: String? = null,
|
||||
@ -154,7 +154,7 @@ public data class EmptyDeviceMessage(
|
||||
@SerialName("log")
|
||||
public data class DeviceLogMessage(
|
||||
val message: String,
|
||||
val data: MetaItem<*>? = null,
|
||||
val data: MetaItem? = null,
|
||||
override val sourceDevice: String? = null,
|
||||
override val targetDevice: String? = null,
|
||||
override val comment: String? = null,
|
@ -3,6 +3,7 @@ package hep.dataforge.control.ports
|
||||
import hep.dataforge.context.Context
|
||||
import hep.dataforge.context.ContextAware
|
||||
import hep.dataforge.context.Factory
|
||||
import hep.dataforge.context.logger
|
||||
import hep.dataforge.control.api.Socket
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.channels.Channel
|
@ -3,6 +3,7 @@ package hep.dataforge.control.ports
|
||||
import hep.dataforge.context.Context
|
||||
import hep.dataforge.context.ContextAware
|
||||
import hep.dataforge.context.Global
|
||||
import hep.dataforge.context.logger
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.collect
|
@ -1,7 +1,7 @@
|
||||
package hep.dataforge.control.controllers
|
||||
|
||||
import hep.dataforge.control.base.*
|
||||
import hep.dataforge.meta.*
|
||||
import hep.dataforge.meta.MetaItem
|
||||
import hep.dataforge.meta.transformations.MetaConverter
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import kotlin.properties.ReadOnlyProperty
|
||||
@ -12,7 +12,7 @@ import kotlin.time.Duration
|
||||
/**
|
||||
* Blocking read of the value
|
||||
*/
|
||||
public operator fun ReadOnlyDeviceProperty.getValue(thisRef: Any?, property: KProperty<*>): MetaItem<*> =
|
||||
public operator fun ReadOnlyDeviceProperty.getValue(thisRef: Any?, property: KProperty<*>): MetaItem =
|
||||
runBlocking(scope.coroutineContext) {
|
||||
read()
|
||||
}
|
||||
@ -22,7 +22,7 @@ public operator fun <T: Any> TypedReadOnlyDeviceProperty<T>.getValue(thisRef: An
|
||||
readTyped()
|
||||
}
|
||||
|
||||
public operator fun DeviceProperty.setValue(thisRef: Any?, property: KProperty<*>, value: MetaItem<*>) {
|
||||
public operator fun DeviceProperty.setValue(thisRef: Any?, property: KProperty<*>, value: MetaItem) {
|
||||
this.value = value
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package hep.dataforge.control.ports
|
||||
|
||||
import hep.dataforge.context.Context
|
||||
import hep.dataforge.context.logger
|
||||
import hep.dataforge.meta.Meta
|
||||
import hep.dataforge.meta.get
|
||||
import hep.dataforge.meta.int
|
@ -3,8 +3,6 @@ plugins {
|
||||
id("ru.mipt.npm.publish")
|
||||
}
|
||||
|
||||
val ktorVersion: String by rootProject.extra
|
||||
|
||||
kscience{
|
||||
useSerialization {
|
||||
json()
|
||||
@ -16,7 +14,7 @@ kotlin {
|
||||
commonMain {
|
||||
dependencies {
|
||||
implementation(project(":magix:magix-service"))
|
||||
implementation(project(":dataforge-device-core"))
|
||||
implementation(project(":controls-core"))
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
package hep.dataforge.control.client
|
||||
|
||||
import hep.dataforge.context.logger
|
||||
import hep.dataforge.control.controllers.DeviceManager
|
||||
import hep.dataforge.control.controllers.respondMessage
|
||||
import hep.dataforge.control.messages.DeviceMessage
|
@ -4,6 +4,6 @@ plugins {
|
||||
}
|
||||
|
||||
dependencies{
|
||||
api(project(":dataforge-device-core"))
|
||||
api(project(":controls-core"))
|
||||
implementation("org.scream3r:jssc:2.8.0")
|
||||
}
|
@ -7,8 +7,8 @@ val dataforgeVersion: String by rootProject.extra
|
||||
val ktorVersion: String by rootProject.extra
|
||||
|
||||
dependencies{
|
||||
implementation(project(":dataforge-device-core"))
|
||||
implementation(project(":dataforge-device-tcp"))
|
||||
implementation(project(":controls-core"))
|
||||
implementation(project(":controls-tcp"))
|
||||
implementation("io.ktor:ktor-server-cio:$ktorVersion")
|
||||
implementation("io.ktor:ktor-websockets:$ktorVersion")
|
||||
implementation("io.ktor:ktor-serialization:$ktorVersion")
|
@ -20,18 +20,19 @@ import io.ktor.http.HttpStatusCode
|
||||
import io.ktor.request.receiveText
|
||||
import io.ktor.response.respond
|
||||
import io.ktor.response.respondRedirect
|
||||
import io.ktor.routing.*
|
||||
import io.ktor.routing.get
|
||||
import io.ktor.routing.post
|
||||
import io.ktor.routing.route
|
||||
import io.ktor.routing.routing
|
||||
import io.ktor.server.cio.CIO
|
||||
import io.ktor.server.engine.ApplicationEngine
|
||||
import io.ktor.server.engine.embeddedServer
|
||||
import io.ktor.util.KtorExperimentalAPI
|
||||
import io.ktor.util.getValue
|
||||
import io.ktor.websocket.WebSockets
|
||||
import io.ktor.websocket.webSocket
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.FlowPreview
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import kotlinx.html.*
|
||||
import kotlinx.serialization.json.Json
|
||||
import kotlinx.serialization.json.JsonObject
|
||||
@ -124,7 +125,7 @@ public fun Application.deviceModule(
|
||||
li {
|
||||
a(href = "../$deviceName/${property.name}/get") { +"${property.name}: " }
|
||||
code {
|
||||
+property.config.toJson().toString()
|
||||
+property.toMeta().toJson().toString()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -135,7 +136,7 @@ public fun Application.deviceModule(
|
||||
li {
|
||||
+("${action.name}: ")
|
||||
code {
|
||||
+action.config.toJson().toString()
|
||||
+action.toMeta().toJson().toString()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -152,12 +153,12 @@ public fun Application.deviceModule(
|
||||
put("target", name.toString())
|
||||
put("properties", buildJsonArray {
|
||||
device.propertyDescriptors.forEach { descriptor ->
|
||||
add(descriptor.config.toJson())
|
||||
add(descriptor.toMeta().toJson())
|
||||
}
|
||||
})
|
||||
put("actions", buildJsonArray {
|
||||
device.actionDescriptors.forEach { actionDescriptor ->
|
||||
add(actionDescriptor.config.toJson())
|
||||
add(actionDescriptor.toMeta().toJson())
|
||||
}
|
||||
})
|
||||
}
|
@ -8,7 +8,7 @@ kotlin {
|
||||
sourceSets {
|
||||
commonMain {
|
||||
dependencies {
|
||||
api(project(":dataforge-device-core"))
|
||||
api(project(":controls-core"))
|
||||
api("io.ktor:ktor-network:$ktorVersion")
|
||||
}
|
||||
}
|
@ -17,9 +17,9 @@ repositories{
|
||||
}
|
||||
|
||||
dependencies{
|
||||
implementation(project(":dataforge-device-core"))
|
||||
implementation(project(":dataforge-device-server"))
|
||||
implementation(project(":dataforge-magix-client"))
|
||||
implementation(project(":controls-core"))
|
||||
implementation(project(":controls-server"))
|
||||
implementation(project(":controls-magix-client"))
|
||||
implementation("no.tornado:tornadofx:1.7.20")
|
||||
implementation(kotlin("stdlib-jdk8"))
|
||||
implementation("kscience.plotlykt:plotlykt-server:0.3.0")
|
||||
|
@ -2,6 +2,7 @@ package hep.dataforge.control.demo
|
||||
|
||||
import hep.dataforge.context.ContextAware
|
||||
import hep.dataforge.context.Global
|
||||
import hep.dataforge.context.logger
|
||||
import io.ktor.server.engine.ApplicationEngine
|
||||
import javafx.scene.Parent
|
||||
import javafx.scene.control.Slider
|
||||
|
10
magix/magix-java-client/build.gradle.kts
Normal file
10
magix/magix-java-client/build.gradle.kts
Normal file
@ -0,0 +1,10 @@
|
||||
plugins {
|
||||
java
|
||||
id("ru.mipt.npm.jvm")
|
||||
id("ru.mipt.npm.publish")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(project(":magix:magix-service"))
|
||||
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-jdk9:${ru.mipt.npm.gradle.KScienceVersions.coroutinesVersion}")
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
package ru.mipt.npm.magix.client;
|
||||
|
||||
import hep.dataforge.magix.api.MagixMessage;
|
||||
import kotlinx.serialization.json.JsonElement;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.Flow;
|
||||
|
||||
/**
|
||||
* See https://github.com/waltz-controls/rfc/tree/master/2
|
||||
*
|
||||
* @param <T>
|
||||
*/
|
||||
public interface MagixClient<T> {
|
||||
void broadcast(MagixMessage<T> msg) throws IOException;
|
||||
|
||||
Flow.Publisher<MagixMessage<T>> subscribe();
|
||||
|
||||
static MagixClient<JsonElement> rSocketTcp(String host, int port) {
|
||||
return ControlsMagixClient.Companion.rSocketTcp(host, port);
|
||||
}
|
||||
|
||||
static MagixClient<JsonElement> rSocketWs(String host, int port, String path) {
|
||||
return ControlsMagixClient.Companion.rSocketWs(host, port, path);
|
||||
}
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
package ru.mipt.npm.magix.client
|
||||
|
||||
import hep.dataforge.magix.api.MagixEndpoint
|
||||
import hep.dataforge.magix.api.MagixMessage
|
||||
import hep.dataforge.magix.api.MagixMessageFilter
|
||||
import hep.dataforge.magix.service.RSocketMagixEndpoint
|
||||
import hep.dataforge.magix.service.withTcp
|
||||
import kotlinx.coroutines.jdk9.asPublisher
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import kotlinx.serialization.KSerializer
|
||||
import kotlinx.serialization.json.JsonElement
|
||||
import java.util.concurrent.Flow
|
||||
|
||||
public class ControlsMagixClient<T>(
|
||||
private val endpoint: MagixEndpoint,
|
||||
private val filter: MagixMessageFilter,
|
||||
private val serializer: KSerializer<T>,
|
||||
) : MagixClient<T> {
|
||||
|
||||
override fun broadcast(msg: MagixMessage<T>): Unit = runBlocking {
|
||||
endpoint.broadcast(serializer, msg)
|
||||
}
|
||||
|
||||
override fun subscribe(): Flow.Publisher<MagixMessage<T>> = endpoint.subscribe(serializer, filter).asPublisher()
|
||||
|
||||
public companion object {
|
||||
|
||||
public fun rSocketTcp(host: String, port: Int): ControlsMagixClient<JsonElement> {
|
||||
val endpoint = runBlocking {
|
||||
RSocketMagixEndpoint.withTcp(host, port)
|
||||
}
|
||||
return ControlsMagixClient(endpoint, MagixMessageFilter(), JsonElement.serializer())
|
||||
}
|
||||
|
||||
public fun rSocketWs(host: String, port: Int, path: String = "/rsocket"): ControlsMagixClient<JsonElement> {
|
||||
val endpoint = runBlocking {
|
||||
RSocketMagixEndpoint.withWebSockets(host, port, path)
|
||||
}
|
||||
return ControlsMagixClient(endpoint, MagixMessageFilter(), JsonElement.serializer())
|
||||
}
|
||||
}
|
||||
}
|
@ -11,8 +11,8 @@ kscience {
|
||||
}
|
||||
|
||||
val dataforgeVersion: String by rootProject.extra
|
||||
val ktorVersion: String by rootProject.extra
|
||||
val rsocketVersion: String by rootProject.extra
|
||||
val ktorVersion: String = ru.mipt.npm.gradle.KScienceVersions.ktorVersion
|
||||
|
||||
dependencies{
|
||||
api(project(":magix:magix-api"))
|
||||
|
@ -25,6 +25,7 @@ public fun CoroutineScope.startMagixServer(
|
||||
buffer,
|
||||
extraBufferCapacity = buffer
|
||||
)
|
||||
|
||||
val tcpTransport = aSocket(ActorSelectorManager(Dispatchers.IO)).tcp().serverTransport(port = rawSocketPort)
|
||||
RSocketServer().bind(tcpTransport, magixAcceptor(magixFlow))
|
||||
|
||||
|
@ -52,12 +52,14 @@ internal fun CoroutineScope.magixAcceptor(magixFlow: MutableSharedFlow<GenericMa
|
||||
magixFlow.emit(message)
|
||||
}
|
||||
// bi-directional connection
|
||||
requestChannel { _: Payload, input: Flow<Payload> ->
|
||||
requestChannel { request: Payload, input: Flow<Payload> ->
|
||||
input.onEach {
|
||||
magixFlow.emit(magixJson.decodeFromString(genericMessageSerializer, it.data.readText()))
|
||||
}.launchIn(this@magixAcceptor)
|
||||
|
||||
magixFlow.map { message ->
|
||||
val filter = magixJson.decodeFromString(MagixMessageFilter.serializer(), request.data.readText())
|
||||
|
||||
magixFlow.filter(filter).map { message ->
|
||||
val string = magixJson.encodeToString(genericMessageSerializer, message)
|
||||
buildPayload { data(string) }
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ kscience{
|
||||
val ktorVersion: String by rootProject.extra
|
||||
|
||||
dependencies {
|
||||
implementation(project(":dataforge-device-tcp"))
|
||||
implementation(project(":dataforge-magix-client"))
|
||||
implementation(project(":controls-tcp"))
|
||||
implementation(project(":controls-magix-client"))
|
||||
implementation("no.tornado:tornadofx:1.7.20")
|
||||
}
|
||||
|
@ -3,6 +3,7 @@
|
||||
package ru.mipt.npm.devices.pimotionmaster
|
||||
|
||||
import hep.dataforge.context.Context
|
||||
import hep.dataforge.context.logger
|
||||
import hep.dataforge.control.api.DeviceHub
|
||||
import hep.dataforge.control.api.PropertyDescriptor
|
||||
import hep.dataforge.control.base.*
|
||||
|
@ -2,6 +2,7 @@ package ru.mipt.npm.devices.pimotionmaster
|
||||
|
||||
import hep.dataforge.context.Context
|
||||
import hep.dataforge.context.ContextAware
|
||||
import hep.dataforge.context.logger
|
||||
import hep.dataforge.control.api.Socket
|
||||
import hep.dataforge.control.ports.AbstractPort
|
||||
import hep.dataforge.control.ports.withDelimiter
|
||||
|
@ -1,9 +1,12 @@
|
||||
package ru.mipt.npm.devices.pimotionmaster
|
||||
|
||||
import hep.dataforge.context.logger
|
||||
import hep.dataforge.control.api.Device
|
||||
import hep.dataforge.control.base.TypedDeviceProperty
|
||||
import hep.dataforge.control.base.TypedReadOnlyDeviceProperty
|
||||
import javafx.beans.property.*
|
||||
import javafx.beans.property.ObjectPropertyBase
|
||||
import javafx.beans.property.Property
|
||||
import javafx.beans.property.ReadOnlyProperty
|
||||
import kotlinx.coroutines.flow.catch
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
|
@ -1,6 +1,6 @@
|
||||
pluginManagement {
|
||||
val kotlinVersion = "1.4.21"
|
||||
val toolsVersion = "0.7.1"
|
||||
val kotlinVersion = "1.4.30"
|
||||
val toolsVersion = "0.7.6"
|
||||
|
||||
repositories {
|
||||
mavenLocal()
|
||||
@ -27,18 +27,20 @@ pluginManagement {
|
||||
rootProject.name = "controls.kt"
|
||||
|
||||
include(
|
||||
":dataforge-device-core",
|
||||
":dataforge-device-tcp",
|
||||
":dataforge-device-serial",
|
||||
":dataforge-device-server",
|
||||
":controls-core",
|
||||
":controls-tcp",
|
||||
":controls-serial",
|
||||
":controls-server",
|
||||
":demo",
|
||||
":magix",
|
||||
":magix:magix-api",
|
||||
":magix:magix-server",
|
||||
":magix:magix-service",
|
||||
":dataforge-magix-client",
|
||||
":magix:magix-java-client",
|
||||
":controls-magix-client",
|
||||
":motors"
|
||||
)
|
||||
|
||||
//includeBuild("../dataforge-core")
|
||||
//includeBuild("../plotly.kt")
|
||||
//includeBuild("../plotly.kt")
|
||||
include("magix-java-client")
|
||||
|
Loading…
Reference in New Issue
Block a user