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