Compare commits
No commits in common. "07cc41c645692f1004ba293498f9768482150cd4" and "afee2f0a02bdd97bf82c8e48d2050825c6608f1a" have entirely different histories.
07cc41c645
...
afee2f0a02
@ -5,11 +5,9 @@
|
|||||||
### Added
|
### Added
|
||||||
- Device lifecycle message
|
- Device lifecycle message
|
||||||
- Low-code constructor
|
- Low-code constructor
|
||||||
- Automatic description generation for spec properties (JVM only)
|
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
- Property caching moved from core `Device` to the `CachingDevice`
|
- Property caching moved from core `Device` to the `CachingDevice`
|
||||||
- `DeviceSpec` properties no explicitly pass property name to getters and setters.
|
|
||||||
|
|
||||||
### Deprecated
|
### Deprecated
|
||||||
|
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
package space.kscience.controls.constructor
|
package space.kscience.controls.constructor
|
||||||
|
|
||||||
import space.kscience.controls.api.Device
|
import space.kscience.controls.api.Device
|
||||||
import space.kscience.controls.spec.*
|
import space.kscience.controls.spec.DevicePropertySpec
|
||||||
|
import space.kscience.controls.spec.DeviceSpec
|
||||||
|
import space.kscience.controls.spec.MutableDevicePropertySpec
|
||||||
|
import space.kscience.controls.spec.doubleProperty
|
||||||
import space.kscience.dataforge.meta.transformations.MetaConverter
|
import space.kscience.dataforge.meta.transformations.MetaConverter
|
||||||
|
|
||||||
|
|
||||||
|
@ -27,6 +27,6 @@ public fun PropertyDescriptor.metaDescriptor(block: MetaDescriptorBuilder.()->Un
|
|||||||
*/
|
*/
|
||||||
@Serializable
|
@Serializable
|
||||||
public class ActionDescriptor(public val name: String) {
|
public class ActionDescriptor(public val name: String) {
|
||||||
public var description: String? = null
|
public var info: String? = null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,7 +8,9 @@ import space.kscience.dataforge.meta.Meta
|
|||||||
import space.kscience.dataforge.meta.transformations.MetaConverter
|
import space.kscience.dataforge.meta.transformations.MetaConverter
|
||||||
import kotlin.properties.PropertyDelegateProvider
|
import kotlin.properties.PropertyDelegateProvider
|
||||||
import kotlin.properties.ReadOnlyProperty
|
import kotlin.properties.ReadOnlyProperty
|
||||||
|
import kotlin.reflect.KMutableProperty1
|
||||||
import kotlin.reflect.KProperty
|
import kotlin.reflect.KProperty
|
||||||
|
import kotlin.reflect.KProperty1
|
||||||
|
|
||||||
public object UnitMetaConverter : MetaConverter<Unit> {
|
public object UnitMetaConverter : MetaConverter<Unit> {
|
||||||
override fun metaToObject(meta: Meta): Unit = Unit
|
override fun metaToObject(meta: Meta): Unit = Unit
|
||||||
@ -42,25 +44,72 @@ public abstract class DeviceSpec<D : Device> {
|
|||||||
return deviceProperty
|
return deviceProperty
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public fun <T> property(
|
||||||
|
converter: MetaConverter<T>,
|
||||||
|
readOnlyProperty: KProperty1<D, T>,
|
||||||
|
descriptorBuilder: PropertyDescriptor.() -> Unit = {},
|
||||||
|
): PropertyDelegateProvider<DeviceSpec<D>, ReadOnlyProperty<Any?, DevicePropertySpec<D, T>>> =
|
||||||
|
PropertyDelegateProvider { _, property ->
|
||||||
|
val deviceProperty = object : DevicePropertySpec<D, T> {
|
||||||
|
override val descriptor: PropertyDescriptor = PropertyDescriptor(property.name).apply {
|
||||||
|
//TODO add type from converter
|
||||||
|
mutable = true
|
||||||
|
}.apply(descriptorBuilder)
|
||||||
|
|
||||||
|
override val converter: MetaConverter<T> = converter
|
||||||
|
|
||||||
|
override suspend fun read(device: D): T = withContext(device.coroutineContext) {
|
||||||
|
readOnlyProperty.get(device)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
registerProperty(deviceProperty)
|
||||||
|
ReadOnlyProperty { _, _ ->
|
||||||
|
deviceProperty
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public fun <T> mutableProperty(
|
||||||
|
converter: MetaConverter<T>,
|
||||||
|
readWriteProperty: KMutableProperty1<D, T>,
|
||||||
|
descriptorBuilder: PropertyDescriptor.() -> Unit = {},
|
||||||
|
): PropertyDelegateProvider<DeviceSpec<D>, ReadOnlyProperty<Any?, MutableDevicePropertySpec<D, T>>> =
|
||||||
|
PropertyDelegateProvider { _, property ->
|
||||||
|
val deviceProperty = object : MutableDevicePropertySpec<D, T> {
|
||||||
|
|
||||||
|
override val descriptor: PropertyDescriptor = PropertyDescriptor(property.name).apply {
|
||||||
|
//TODO add the type from converter
|
||||||
|
mutable = true
|
||||||
|
}.apply(descriptorBuilder)
|
||||||
|
|
||||||
|
override val converter: MetaConverter<T> = converter
|
||||||
|
|
||||||
|
override suspend fun read(device: D): T = withContext(device.coroutineContext) {
|
||||||
|
readWriteProperty.get(device)
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun write(device: D, value: T): Unit = withContext(device.coroutineContext) {
|
||||||
|
readWriteProperty.set(device, value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
registerProperty(deviceProperty)
|
||||||
|
ReadOnlyProperty { _, _ ->
|
||||||
|
deviceProperty
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public fun <T> property(
|
public fun <T> property(
|
||||||
converter: MetaConverter<T>,
|
converter: MetaConverter<T>,
|
||||||
descriptorBuilder: PropertyDescriptor.() -> Unit = {},
|
descriptorBuilder: PropertyDescriptor.() -> Unit = {},
|
||||||
name: String? = null,
|
name: String? = null,
|
||||||
read: suspend D.(propertyName: String) -> T?,
|
read: suspend D.() -> T?,
|
||||||
): PropertyDelegateProvider<DeviceSpec<D>, ReadOnlyProperty<DeviceSpec<D>, DevicePropertySpec<D, T>>> =
|
): PropertyDelegateProvider<DeviceSpec<D>, ReadOnlyProperty<DeviceSpec<D>, DevicePropertySpec<D, T>>> =
|
||||||
PropertyDelegateProvider { _: DeviceSpec<D>, property ->
|
PropertyDelegateProvider { _: DeviceSpec<D>, property ->
|
||||||
val propertyName = name ?: property.name
|
val propertyName = name ?: property.name
|
||||||
val deviceProperty = object : DevicePropertySpec<D, T> {
|
val deviceProperty = object : DevicePropertySpec<D, T> {
|
||||||
|
override val descriptor: PropertyDescriptor = PropertyDescriptor(propertyName).apply(descriptorBuilder)
|
||||||
override val descriptor: PropertyDescriptor = PropertyDescriptor(propertyName).apply {
|
|
||||||
fromSpec(property)
|
|
||||||
descriptorBuilder()
|
|
||||||
}
|
|
||||||
|
|
||||||
override val converter: MetaConverter<T> = converter
|
override val converter: MetaConverter<T> = converter
|
||||||
|
|
||||||
override suspend fun read(device: D): T? =
|
override suspend fun read(device: D): T? = withContext(device.coroutineContext) { device.read() }
|
||||||
withContext(device.coroutineContext) { device.read(propertyName) }
|
|
||||||
}
|
}
|
||||||
registerProperty(deviceProperty)
|
registerProperty(deviceProperty)
|
||||||
ReadOnlyProperty<DeviceSpec<D>, DevicePropertySpec<D, T>> { _, _ ->
|
ReadOnlyProperty<DeviceSpec<D>, DevicePropertySpec<D, T>> { _, _ ->
|
||||||
@ -72,29 +121,23 @@ public abstract class DeviceSpec<D : Device> {
|
|||||||
converter: MetaConverter<T>,
|
converter: MetaConverter<T>,
|
||||||
descriptorBuilder: PropertyDescriptor.() -> Unit = {},
|
descriptorBuilder: PropertyDescriptor.() -> Unit = {},
|
||||||
name: String? = null,
|
name: String? = null,
|
||||||
read: suspend D.(propertyName: String) -> T?,
|
read: suspend D.() -> T?,
|
||||||
write: suspend D.(propertyName: String, value: T) -> Unit,
|
write: suspend D.(T) -> Unit,
|
||||||
): PropertyDelegateProvider<DeviceSpec<D>, ReadOnlyProperty<DeviceSpec<D>, MutableDevicePropertySpec<D, T>>> =
|
): PropertyDelegateProvider<DeviceSpec<D>, ReadOnlyProperty<DeviceSpec<D>, MutableDevicePropertySpec<D, T>>> =
|
||||||
PropertyDelegateProvider { _: DeviceSpec<D>, property: KProperty<*> ->
|
PropertyDelegateProvider { _: DeviceSpec<D>, property: KProperty<*> ->
|
||||||
val propertyName = name ?: property.name
|
val propertyName = name ?: property.name
|
||||||
val deviceProperty = object : MutableDevicePropertySpec<D, T> {
|
val deviceProperty = object : MutableDevicePropertySpec<D, T> {
|
||||||
override val descriptor: PropertyDescriptor = PropertyDescriptor(
|
override val descriptor: PropertyDescriptor = PropertyDescriptor(propertyName, mutable = true)
|
||||||
propertyName,
|
.apply(descriptorBuilder)
|
||||||
mutable = true
|
|
||||||
).apply {
|
|
||||||
fromSpec(property)
|
|
||||||
descriptorBuilder()
|
|
||||||
}
|
|
||||||
override val converter: MetaConverter<T> = converter
|
override val converter: MetaConverter<T> = converter
|
||||||
|
|
||||||
override suspend fun read(device: D): T? =
|
override suspend fun read(device: D): T? = withContext(device.coroutineContext) { device.read() }
|
||||||
withContext(device.coroutineContext) { device.read(propertyName) }
|
|
||||||
|
|
||||||
override suspend fun write(device: D, value: T): Unit = withContext(device.coroutineContext) {
|
override suspend fun write(device: D, value: T): Unit = withContext(device.coroutineContext) {
|
||||||
device.write(propertyName, value)
|
device.write(value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
registerProperty(deviceProperty)
|
_properties[propertyName] = deviceProperty
|
||||||
ReadOnlyProperty<DeviceSpec<D>, MutableDevicePropertySpec<D, T>> { _, _ ->
|
ReadOnlyProperty<DeviceSpec<D>, MutableDevicePropertySpec<D, T>> { _, _ ->
|
||||||
deviceProperty
|
deviceProperty
|
||||||
}
|
}
|
||||||
@ -113,13 +156,10 @@ public abstract class DeviceSpec<D : Device> {
|
|||||||
name: String? = null,
|
name: String? = null,
|
||||||
execute: suspend D.(I) -> O,
|
execute: suspend D.(I) -> O,
|
||||||
): PropertyDelegateProvider<DeviceSpec<D>, ReadOnlyProperty<DeviceSpec<D>, DeviceActionSpec<D, I, O>>> =
|
): PropertyDelegateProvider<DeviceSpec<D>, ReadOnlyProperty<DeviceSpec<D>, DeviceActionSpec<D, I, O>>> =
|
||||||
PropertyDelegateProvider { _: DeviceSpec<D>, property: KProperty<*> ->
|
PropertyDelegateProvider { _: DeviceSpec<D>, property ->
|
||||||
val actionName = name ?: property.name
|
val actionName = name ?: property.name
|
||||||
val deviceAction = object : DeviceActionSpec<D, I, O> {
|
val deviceAction = object : DeviceActionSpec<D, I, O> {
|
||||||
override val descriptor: ActionDescriptor = ActionDescriptor(actionName).apply {
|
override val descriptor: ActionDescriptor = ActionDescriptor(actionName).apply(descriptorBuilder)
|
||||||
fromSpec(property)
|
|
||||||
descriptorBuilder()
|
|
||||||
}
|
|
||||||
|
|
||||||
override val inputConverter: MetaConverter<I> = inputConverter
|
override val inputConverter: MetaConverter<I> = inputConverter
|
||||||
override val outputConverter: MetaConverter<O> = outputConverter
|
override val outputConverter: MetaConverter<O> = outputConverter
|
||||||
@ -134,39 +174,68 @@ public abstract class DeviceSpec<D : Device> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An action that takes [Meta] and returns [Meta]. No conversions are done
|
||||||
|
*/
|
||||||
|
public fun metaAction(
|
||||||
|
descriptorBuilder: ActionDescriptor.() -> Unit = {},
|
||||||
|
name: String? = null,
|
||||||
|
execute: suspend D.(Meta) -> Meta,
|
||||||
|
): PropertyDelegateProvider<DeviceSpec<D>, ReadOnlyProperty<DeviceSpec<D>, DeviceActionSpec<D, Meta, Meta>>> =
|
||||||
|
action(
|
||||||
|
MetaConverter.Companion.meta,
|
||||||
|
MetaConverter.Companion.meta,
|
||||||
|
descriptorBuilder,
|
||||||
|
name
|
||||||
|
) {
|
||||||
|
execute(it)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An action that takes no parameters and returns no values
|
||||||
|
*/
|
||||||
|
public fun unitAction(
|
||||||
|
descriptorBuilder: ActionDescriptor.() -> Unit = {},
|
||||||
|
name: String? = null,
|
||||||
|
execute: suspend D.() -> Unit,
|
||||||
|
): PropertyDelegateProvider<DeviceSpec<D>, ReadOnlyProperty<DeviceSpec<D>, DeviceActionSpec<D, Unit, Unit>>> =
|
||||||
|
action(
|
||||||
|
MetaConverter.Companion.unit,
|
||||||
|
MetaConverter.Companion.unit,
|
||||||
|
descriptorBuilder,
|
||||||
|
name
|
||||||
|
) {
|
||||||
|
execute()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* An action that takes no parameters and returns no values
|
|
||||||
*/
|
|
||||||
public fun <D : Device> DeviceSpec<D>.unitAction(
|
|
||||||
descriptorBuilder: ActionDescriptor.() -> Unit = {},
|
|
||||||
name: String? = null,
|
|
||||||
execute: suspend D.() -> Unit,
|
|
||||||
): PropertyDelegateProvider<DeviceSpec<D>, ReadOnlyProperty<DeviceSpec<D>, DeviceActionSpec<D, Unit, Unit>>> =
|
|
||||||
action(
|
|
||||||
MetaConverter.Companion.unit,
|
|
||||||
MetaConverter.Companion.unit,
|
|
||||||
descriptorBuilder,
|
|
||||||
name
|
|
||||||
) {
|
|
||||||
execute()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An action that takes [Meta] and returns [Meta]. No conversions are done
|
* Register a mutable logical property for a device
|
||||||
*/
|
*/
|
||||||
public fun <D : Device> DeviceSpec<D>.metaAction(
|
@OptIn(InternalDeviceAPI::class)
|
||||||
descriptorBuilder: ActionDescriptor.() -> Unit = {},
|
public fun <T, D : DeviceBase<D>> DeviceSpec<D>.logicalProperty(
|
||||||
|
converter: MetaConverter<T>,
|
||||||
|
descriptorBuilder: PropertyDescriptor.() -> Unit = {},
|
||||||
name: String? = null,
|
name: String? = null,
|
||||||
execute: suspend D.(Meta) -> Meta,
|
): PropertyDelegateProvider<DeviceSpec<D>, ReadOnlyProperty<Any?, MutableDevicePropertySpec<D, T>>> =
|
||||||
): PropertyDelegateProvider<DeviceSpec<D>, ReadOnlyProperty<DeviceSpec<D>, DeviceActionSpec<D, Meta, Meta>>> =
|
PropertyDelegateProvider { _, property ->
|
||||||
action(
|
val deviceProperty = object : MutableDevicePropertySpec<D, T> {
|
||||||
MetaConverter.Companion.meta,
|
val propertyName = name ?: property.name
|
||||||
MetaConverter.Companion.meta,
|
override val descriptor: PropertyDescriptor = PropertyDescriptor(propertyName).apply {
|
||||||
descriptorBuilder,
|
//TODO add type from converter
|
||||||
name
|
mutable = true
|
||||||
) {
|
}.apply(descriptorBuilder)
|
||||||
execute(it)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
override val converter: MetaConverter<T> = converter
|
||||||
|
|
||||||
|
override suspend fun read(device: D): T? = device.getProperty(propertyName)?.let(converter::metaToObject)
|
||||||
|
|
||||||
|
override suspend fun write(device: D, value: T): Unit =
|
||||||
|
device.writeProperty(propertyName, converter.objectToMeta(value))
|
||||||
|
}
|
||||||
|
registerProperty(deviceProperty)
|
||||||
|
ReadOnlyProperty { _, _ ->
|
||||||
|
deviceProperty
|
||||||
|
}
|
||||||
|
}
|
@ -12,7 +12,7 @@ import kotlin.time.Duration
|
|||||||
/**
|
/**
|
||||||
* Perform a recurring asynchronous read action and return a flow of results.
|
* Perform a recurring asynchronous read action and return a flow of results.
|
||||||
* The flow is lazy, so action is not performed unless flow is consumed.
|
* The flow is lazy, so action is not performed unless flow is consumed.
|
||||||
* The flow uses caller context. To call it on device context, use `flowOn(coroutineContext)`.
|
* The flow uses called context. In order to call it on device context, use `flowOn(coroutineContext)`.
|
||||||
*
|
*
|
||||||
* The flow is canceled when the device scope is canceled
|
* The flow is canceled when the device scope is canceled
|
||||||
*/
|
*/
|
||||||
|
@ -1,12 +0,0 @@
|
|||||||
package space.kscience.controls.spec
|
|
||||||
|
|
||||||
import space.kscience.controls.api.ActionDescriptor
|
|
||||||
import space.kscience.controls.api.PropertyDescriptor
|
|
||||||
import kotlin.reflect.KProperty
|
|
||||||
|
|
||||||
@Target(AnnotationTarget.CLASS, AnnotationTarget.PROPERTY, AnnotationTarget.FIELD)
|
|
||||||
public annotation class Description(val content: String)
|
|
||||||
|
|
||||||
internal expect fun PropertyDescriptor.fromSpec(property: KProperty<*>)
|
|
||||||
|
|
||||||
internal expect fun ActionDescriptor.fromSpec(property: KProperty<*>)
|
|
@ -8,62 +8,13 @@ import space.kscience.dataforge.meta.ValueType
|
|||||||
import space.kscience.dataforge.meta.transformations.MetaConverter
|
import space.kscience.dataforge.meta.transformations.MetaConverter
|
||||||
import kotlin.properties.PropertyDelegateProvider
|
import kotlin.properties.PropertyDelegateProvider
|
||||||
import kotlin.properties.ReadOnlyProperty
|
import kotlin.properties.ReadOnlyProperty
|
||||||
import kotlin.reflect.KMutableProperty1
|
|
||||||
import kotlin.reflect.KProperty1
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A read-only device property that delegates reading to a device [KProperty1]
|
|
||||||
*/
|
|
||||||
public fun <T, D : Device> DeviceSpec<D>.property(
|
|
||||||
converter: MetaConverter<T>,
|
|
||||||
readOnlyProperty: KProperty1<D, T>,
|
|
||||||
descriptorBuilder: PropertyDescriptor.() -> Unit = {},
|
|
||||||
): PropertyDelegateProvider<DeviceSpec<D>, ReadOnlyProperty<DeviceSpec<D>, DevicePropertySpec<D, T>>> = property(
|
|
||||||
converter,
|
|
||||||
descriptorBuilder,
|
|
||||||
name = readOnlyProperty.name,
|
|
||||||
read = { readOnlyProperty.get(this) }
|
|
||||||
)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Mutable property that delegates reading and writing to a device [KMutableProperty1]
|
|
||||||
*/
|
|
||||||
public fun <T, D : Device> DeviceSpec<D>.mutableProperty(
|
|
||||||
converter: MetaConverter<T>,
|
|
||||||
readWriteProperty: KMutableProperty1<D, T>,
|
|
||||||
descriptorBuilder: PropertyDescriptor.() -> Unit = {},
|
|
||||||
): PropertyDelegateProvider<DeviceSpec<D>, ReadOnlyProperty<DeviceSpec<D>, MutableDevicePropertySpec<D, T>>> =
|
|
||||||
mutableProperty(
|
|
||||||
converter,
|
|
||||||
descriptorBuilder,
|
|
||||||
readWriteProperty.name,
|
|
||||||
read = { _ -> readWriteProperty.get(this) },
|
|
||||||
write = { _, value: T -> readWriteProperty.set(this, value) }
|
|
||||||
)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Register a mutable logical property (without a corresponding physical state) for a device
|
|
||||||
*/
|
|
||||||
public fun <T, D : DeviceBase<D>> DeviceSpec<D>.logicalProperty(
|
|
||||||
converter: MetaConverter<T>,
|
|
||||||
descriptorBuilder: PropertyDescriptor.() -> Unit = {},
|
|
||||||
name: String? = null,
|
|
||||||
): PropertyDelegateProvider<DeviceSpec<D>, ReadOnlyProperty<DeviceSpec<D>, MutableDevicePropertySpec<D, T>>> =
|
|
||||||
mutableProperty(
|
|
||||||
converter,
|
|
||||||
descriptorBuilder,
|
|
||||||
name,
|
|
||||||
read = { propertyName -> getProperty(propertyName)?.let(converter::metaToObject) },
|
|
||||||
write = { propertyName, value -> writeProperty(propertyName, converter.objectToMeta(value)) }
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
//read only delegates
|
//read only delegates
|
||||||
|
|
||||||
public fun <D : Device> DeviceSpec<D>.booleanProperty(
|
public fun <D : Device> DeviceSpec<D>.booleanProperty(
|
||||||
descriptorBuilder: PropertyDescriptor.() -> Unit = {},
|
descriptorBuilder: PropertyDescriptor.() -> Unit = {},
|
||||||
name: String? = null,
|
name: String? = null,
|
||||||
read: suspend D.(propertyName: String) -> Boolean?
|
read: suspend D.() -> Boolean?
|
||||||
): PropertyDelegateProvider<DeviceSpec<D>, ReadOnlyProperty<DeviceSpec<D>, DevicePropertySpec<D, Boolean>>> = property(
|
): PropertyDelegateProvider<DeviceSpec<D>, ReadOnlyProperty<DeviceSpec<D>, DevicePropertySpec<D, Boolean>>> = property(
|
||||||
MetaConverter.boolean,
|
MetaConverter.boolean,
|
||||||
{
|
{
|
||||||
@ -86,9 +37,9 @@ private inline fun numberDescriptor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
public fun <D : Device> DeviceSpec<D>.numberProperty(
|
public fun <D : Device> DeviceSpec<D>.numberProperty(
|
||||||
descriptorBuilder: PropertyDescriptor.() -> Unit = {},
|
|
||||||
name: String? = null,
|
name: String? = null,
|
||||||
read: suspend D.(propertyName: String) -> Number?
|
descriptorBuilder: PropertyDescriptor.() -> Unit = {},
|
||||||
|
read: suspend D.() -> Number?
|
||||||
): PropertyDelegateProvider<DeviceSpec<D>, ReadOnlyProperty<DeviceSpec<D>, DevicePropertySpec<D, Number>>> = property(
|
): PropertyDelegateProvider<DeviceSpec<D>, ReadOnlyProperty<DeviceSpec<D>, DevicePropertySpec<D, Number>>> = property(
|
||||||
MetaConverter.number,
|
MetaConverter.number,
|
||||||
numberDescriptor(descriptorBuilder),
|
numberDescriptor(descriptorBuilder),
|
||||||
@ -99,7 +50,7 @@ public fun <D : Device> DeviceSpec<D>.numberProperty(
|
|||||||
public fun <D : Device> DeviceSpec<D>.doubleProperty(
|
public fun <D : Device> DeviceSpec<D>.doubleProperty(
|
||||||
descriptorBuilder: PropertyDescriptor.() -> Unit = {},
|
descriptorBuilder: PropertyDescriptor.() -> Unit = {},
|
||||||
name: String? = null,
|
name: String? = null,
|
||||||
read: suspend D.(propertyName: String) -> Double?
|
read: suspend D.() -> Double?
|
||||||
): PropertyDelegateProvider<DeviceSpec<D>, ReadOnlyProperty<DeviceSpec<D>, DevicePropertySpec<D, Double>>> = property(
|
): PropertyDelegateProvider<DeviceSpec<D>, ReadOnlyProperty<DeviceSpec<D>, DevicePropertySpec<D, Double>>> = property(
|
||||||
MetaConverter.double,
|
MetaConverter.double,
|
||||||
numberDescriptor(descriptorBuilder),
|
numberDescriptor(descriptorBuilder),
|
||||||
@ -110,7 +61,7 @@ public fun <D : Device> DeviceSpec<D>.doubleProperty(
|
|||||||
public fun <D : Device> DeviceSpec<D>.stringProperty(
|
public fun <D : Device> DeviceSpec<D>.stringProperty(
|
||||||
descriptorBuilder: PropertyDescriptor.() -> Unit = {},
|
descriptorBuilder: PropertyDescriptor.() -> Unit = {},
|
||||||
name: String? = null,
|
name: String? = null,
|
||||||
read: suspend D.(propertyName: String) -> String?
|
read: suspend D.() -> String?
|
||||||
): PropertyDelegateProvider<DeviceSpec<D>, ReadOnlyProperty<DeviceSpec<D>, DevicePropertySpec<D, String>>> = property(
|
): PropertyDelegateProvider<DeviceSpec<D>, ReadOnlyProperty<DeviceSpec<D>, DevicePropertySpec<D, String>>> = property(
|
||||||
MetaConverter.string,
|
MetaConverter.string,
|
||||||
{
|
{
|
||||||
@ -126,7 +77,7 @@ public fun <D : Device> DeviceSpec<D>.stringProperty(
|
|||||||
public fun <D : Device> DeviceSpec<D>.metaProperty(
|
public fun <D : Device> DeviceSpec<D>.metaProperty(
|
||||||
descriptorBuilder: PropertyDescriptor.() -> Unit = {},
|
descriptorBuilder: PropertyDescriptor.() -> Unit = {},
|
||||||
name: String? = null,
|
name: String? = null,
|
||||||
read: suspend D.(propertyName: String) -> Meta?
|
read: suspend D.() -> Meta?
|
||||||
): PropertyDelegateProvider<DeviceSpec<D>, ReadOnlyProperty<DeviceSpec<D>, DevicePropertySpec<D, Meta>>> = property(
|
): PropertyDelegateProvider<DeviceSpec<D>, ReadOnlyProperty<DeviceSpec<D>, DevicePropertySpec<D, Meta>>> = property(
|
||||||
MetaConverter.meta,
|
MetaConverter.meta,
|
||||||
{
|
{
|
||||||
@ -144,8 +95,8 @@ public fun <D : Device> DeviceSpec<D>.metaProperty(
|
|||||||
public fun <D : Device> DeviceSpec<D>.booleanProperty(
|
public fun <D : Device> DeviceSpec<D>.booleanProperty(
|
||||||
descriptorBuilder: PropertyDescriptor.() -> Unit = {},
|
descriptorBuilder: PropertyDescriptor.() -> Unit = {},
|
||||||
name: String? = null,
|
name: String? = null,
|
||||||
read: suspend D.(propertyName: String) -> Boolean?,
|
read: suspend D.() -> Boolean?,
|
||||||
write: suspend D.(propertyName: String, value: Boolean) -> Unit
|
write: suspend D.(Boolean) -> Unit
|
||||||
): PropertyDelegateProvider<DeviceSpec<D>, ReadOnlyProperty<DeviceSpec<D>, MutableDevicePropertySpec<D, Boolean>>> =
|
): PropertyDelegateProvider<DeviceSpec<D>, ReadOnlyProperty<DeviceSpec<D>, MutableDevicePropertySpec<D, Boolean>>> =
|
||||||
mutableProperty(
|
mutableProperty(
|
||||||
MetaConverter.boolean,
|
MetaConverter.boolean,
|
||||||
@ -164,31 +115,31 @@ public fun <D : Device> DeviceSpec<D>.booleanProperty(
|
|||||||
public fun <D : Device> DeviceSpec<D>.numberProperty(
|
public fun <D : Device> DeviceSpec<D>.numberProperty(
|
||||||
descriptorBuilder: PropertyDescriptor.() -> Unit = {},
|
descriptorBuilder: PropertyDescriptor.() -> Unit = {},
|
||||||
name: String? = null,
|
name: String? = null,
|
||||||
read: suspend D.(propertyName: String) -> Number,
|
read: suspend D.() -> Number,
|
||||||
write: suspend D.(propertyName: String, value: Number) -> Unit
|
write: suspend D.(Number) -> Unit
|
||||||
): PropertyDelegateProvider<DeviceSpec<D>, ReadOnlyProperty<DeviceSpec<D>, MutableDevicePropertySpec<D, Number>>> =
|
): PropertyDelegateProvider<DeviceSpec<D>, ReadOnlyProperty<DeviceSpec<D>, MutableDevicePropertySpec<D, Number>>> =
|
||||||
mutableProperty(MetaConverter.number, numberDescriptor(descriptorBuilder), name, read, write)
|
mutableProperty(MetaConverter.number, numberDescriptor(descriptorBuilder), name, read, write)
|
||||||
|
|
||||||
public fun <D : Device> DeviceSpec<D>.doubleProperty(
|
public fun <D : Device> DeviceSpec<D>.doubleProperty(
|
||||||
descriptorBuilder: PropertyDescriptor.() -> Unit = {},
|
descriptorBuilder: PropertyDescriptor.() -> Unit = {},
|
||||||
name: String? = null,
|
name: String? = null,
|
||||||
read: suspend D.(propertyName: String) -> Double,
|
read: suspend D.() -> Double,
|
||||||
write: suspend D.(propertyName: String, value: Double) -> Unit
|
write: suspend D.(Double) -> Unit
|
||||||
): PropertyDelegateProvider<DeviceSpec<D>, ReadOnlyProperty<DeviceSpec<D>, MutableDevicePropertySpec<D, Double>>> =
|
): PropertyDelegateProvider<DeviceSpec<D>, ReadOnlyProperty<DeviceSpec<D>, MutableDevicePropertySpec<D, Double>>> =
|
||||||
mutableProperty(MetaConverter.double, numberDescriptor(descriptorBuilder), name, read, write)
|
mutableProperty(MetaConverter.double, numberDescriptor(descriptorBuilder), name, read, write)
|
||||||
|
|
||||||
public fun <D : Device> DeviceSpec<D>.stringProperty(
|
public fun <D : Device> DeviceSpec<D>.stringProperty(
|
||||||
descriptorBuilder: PropertyDescriptor.() -> Unit = {},
|
descriptorBuilder: PropertyDescriptor.() -> Unit = {},
|
||||||
name: String? = null,
|
name: String? = null,
|
||||||
read: suspend D.(propertyName: String) -> String,
|
read: suspend D.() -> String,
|
||||||
write: suspend D.(propertyName: String, value: String) -> Unit
|
write: suspend D.(String) -> Unit
|
||||||
): PropertyDelegateProvider<DeviceSpec<D>, ReadOnlyProperty<DeviceSpec<D>, MutableDevicePropertySpec<D, String>>> =
|
): PropertyDelegateProvider<DeviceSpec<D>, ReadOnlyProperty<DeviceSpec<D>, MutableDevicePropertySpec<D, String>>> =
|
||||||
mutableProperty(MetaConverter.string, descriptorBuilder, name, read, write)
|
mutableProperty(MetaConverter.string, descriptorBuilder, name, read, write)
|
||||||
|
|
||||||
public fun <D : Device> DeviceSpec<D>.metaProperty(
|
public fun <D : Device> DeviceSpec<D>.metaProperty(
|
||||||
descriptorBuilder: PropertyDescriptor.() -> Unit = {},
|
descriptorBuilder: PropertyDescriptor.() -> Unit = {},
|
||||||
name: String? = null,
|
name: String? = null,
|
||||||
read: suspend D.(propertyName: String) -> Meta,
|
read: suspend D.() -> Meta,
|
||||||
write: suspend D.(propertyName: String, value: Meta) -> Unit
|
write: suspend D.(Meta) -> Unit
|
||||||
): PropertyDelegateProvider<DeviceSpec<D>, ReadOnlyProperty<DeviceSpec<D>, MutableDevicePropertySpec<D, Meta>>> =
|
): PropertyDelegateProvider<DeviceSpec<D>, ReadOnlyProperty<DeviceSpec<D>, MutableDevicePropertySpec<D, Meta>>> =
|
||||||
mutableProperty(MetaConverter.meta, descriptorBuilder, name, read, write)
|
mutableProperty(MetaConverter.meta, descriptorBuilder, name, read, write)
|
@ -1,9 +0,0 @@
|
|||||||
package space.kscience.controls.spec
|
|
||||||
|
|
||||||
import space.kscience.controls.api.ActionDescriptor
|
|
||||||
import space.kscience.controls.api.PropertyDescriptor
|
|
||||||
import kotlin.reflect.KProperty
|
|
||||||
|
|
||||||
internal actual fun PropertyDescriptor.fromSpec(property: KProperty<*>){}
|
|
||||||
|
|
||||||
internal actual fun ActionDescriptor.fromSpec(property: KProperty<*>){}
|
|
@ -1,18 +0,0 @@
|
|||||||
package space.kscience.controls.spec
|
|
||||||
|
|
||||||
import space.kscience.controls.api.ActionDescriptor
|
|
||||||
import space.kscience.controls.api.PropertyDescriptor
|
|
||||||
import kotlin.reflect.KProperty
|
|
||||||
import kotlin.reflect.full.findAnnotation
|
|
||||||
|
|
||||||
internal actual fun PropertyDescriptor.fromSpec(property: KProperty<*>) {
|
|
||||||
property.findAnnotation<Description>()?.let {
|
|
||||||
description = it.content
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal actual fun ActionDescriptor.fromSpec(property: KProperty<*>){
|
|
||||||
property.findAnnotation<Description>()?.let {
|
|
||||||
description = it.content
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,9 +0,0 @@
|
|||||||
package space.kscience.controls.spec
|
|
||||||
|
|
||||||
import space.kscience.controls.api.ActionDescriptor
|
|
||||||
import space.kscience.controls.api.PropertyDescriptor
|
|
||||||
import kotlin.reflect.KProperty
|
|
||||||
|
|
||||||
internal actual fun PropertyDescriptor.fromSpec(property: KProperty<*>) {}
|
|
||||||
|
|
||||||
internal actual fun ActionDescriptor.fromSpec(property: KProperty<*>){}
|
|
@ -29,7 +29,7 @@ class OpcUaClientTest {
|
|||||||
return DemoOpcUaDevice(config)
|
return DemoOpcUaDevice(config)
|
||||||
}
|
}
|
||||||
|
|
||||||
val randomDouble by doubleProperty { readRandomDouble() }
|
val randomDouble by doubleProperty(read = DemoOpcUaDevice::readRandomDouble)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -42,7 +42,7 @@ class OpcUaClientTest {
|
|||||||
fun testReadDouble() = runTest {
|
fun testReadDouble() = runTest {
|
||||||
val device = DemoOpcUaDevice.build()
|
val device = DemoOpcUaDevice.build()
|
||||||
device.start()
|
device.start()
|
||||||
println(device.read(DemoOpcUaDevice.randomDouble))
|
println(device.read(DemoOpcUaDevice.randomDouble))
|
||||||
device.stop()
|
device.stop()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,19 +0,0 @@
|
|||||||
package space.kscience.controls.vision
|
|
||||||
|
|
||||||
import kotlinx.serialization.modules.SerializersModule
|
|
||||||
import kotlinx.serialization.modules.polymorphic
|
|
||||||
import kotlinx.serialization.modules.subclass
|
|
||||||
import space.kscience.dataforge.context.PluginFactory
|
|
||||||
import space.kscience.visionforge.Vision
|
|
||||||
import space.kscience.visionforge.VisionPlugin
|
|
||||||
import space.kscience.visionforge.plotly.VisionOfPlotly
|
|
||||||
|
|
||||||
public expect class ControlVisionPlugin: VisionPlugin{
|
|
||||||
public companion object: PluginFactory<ControlVisionPlugin>
|
|
||||||
}
|
|
||||||
|
|
||||||
internal val controlsVisionSerializersModule = SerializersModule {
|
|
||||||
polymorphic(Vision::class) {
|
|
||||||
subclass(VisionOfPlotly.serializer())
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,20 +0,0 @@
|
|||||||
package space.kscience.controls.vision
|
|
||||||
|
|
||||||
import space.kscience.dataforge.meta.Meta
|
|
||||||
import space.kscience.dataforge.meta.node
|
|
||||||
import space.kscience.visionforge.AbstractVision
|
|
||||||
import space.kscience.visionforge.Vision
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A [Vision] that shows an indicator
|
|
||||||
*/
|
|
||||||
public class IndicatorVision: AbstractVision() {
|
|
||||||
public val value: Meta? by properties.node()
|
|
||||||
}
|
|
||||||
|
|
||||||
///**
|
|
||||||
// * A [Vision] that allows both showing the value and changing it
|
|
||||||
// */
|
|
||||||
//public interface RegulatorVision: IndicatorVision{
|
|
||||||
//
|
|
||||||
//}
|
|
@ -1,33 +0,0 @@
|
|||||||
package space.kscience.controls.vision
|
|
||||||
|
|
||||||
import kotlinx.serialization.modules.SerializersModule
|
|
||||||
import org.w3c.dom.Element
|
|
||||||
import space.kscience.dataforge.context.Context
|
|
||||||
import space.kscience.dataforge.context.PluginFactory
|
|
||||||
import space.kscience.dataforge.context.PluginTag
|
|
||||||
import space.kscience.dataforge.meta.Meta
|
|
||||||
import space.kscience.dataforge.names.Name
|
|
||||||
import space.kscience.visionforge.ElementVisionRenderer
|
|
||||||
import space.kscience.visionforge.Vision
|
|
||||||
import space.kscience.visionforge.VisionPlugin
|
|
||||||
|
|
||||||
public actual class ControlVisionPlugin : VisionPlugin(), ElementVisionRenderer {
|
|
||||||
override val tag: PluginTag get() = Companion.tag
|
|
||||||
|
|
||||||
override val visionSerializersModule: SerializersModule get() = controlsVisionSerializersModule
|
|
||||||
|
|
||||||
override fun rateVision(vision: Vision): Int {
|
|
||||||
TODO("Not yet implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun render(element: Element, name: Name, vision: Vision, meta: Meta) {
|
|
||||||
TODO("Not yet implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
public actual companion object : PluginFactory<ControlVisionPlugin> {
|
|
||||||
override val tag: PluginTag = PluginTag("controls.vision")
|
|
||||||
|
|
||||||
override fun build(context: Context, meta: Meta): ControlVisionPlugin = ControlVisionPlugin()
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,21 +0,0 @@
|
|||||||
package space.kscience.controls.vision
|
|
||||||
|
|
||||||
import kotlinx.serialization.modules.SerializersModule
|
|
||||||
import space.kscience.dataforge.context.Context
|
|
||||||
import space.kscience.dataforge.context.PluginFactory
|
|
||||||
import space.kscience.dataforge.context.PluginTag
|
|
||||||
import space.kscience.dataforge.meta.Meta
|
|
||||||
import space.kscience.visionforge.VisionPlugin
|
|
||||||
|
|
||||||
public actual class ControlVisionPlugin : VisionPlugin() {
|
|
||||||
override val tag: PluginTag get() = Companion.tag
|
|
||||||
|
|
||||||
override val visionSerializersModule: SerializersModule get() = controlsVisionSerializersModule
|
|
||||||
|
|
||||||
public actual companion object : PluginFactory<ControlVisionPlugin> {
|
|
||||||
override val tag: PluginTag = PluginTag("controls.vision")
|
|
||||||
|
|
||||||
override fun build(context: Context, meta: Meta): ControlVisionPlugin = ControlVisionPlugin()
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
@ -16,7 +16,7 @@ import kotlin.math.sin
|
|||||||
import kotlin.time.Duration.Companion.milliseconds
|
import kotlin.time.Duration.Companion.milliseconds
|
||||||
|
|
||||||
|
|
||||||
interface IDemoDevice : Device {
|
interface IDemoDevice: Device {
|
||||||
var timeScaleState: Double
|
var timeScaleState: Double
|
||||||
var sinScaleState: Double
|
var sinScaleState: Double
|
||||||
var cosScaleState: Double
|
var cosScaleState: Double
|
||||||
@ -50,8 +50,8 @@ class DemoDevice(context: Context, meta: Meta) : DeviceBySpec<IDemoDevice>(Compa
|
|||||||
val sinScale by mutableProperty(MetaConverter.double, IDemoDevice::sinScaleState)
|
val sinScale by mutableProperty(MetaConverter.double, IDemoDevice::sinScaleState)
|
||||||
val cosScale by mutableProperty(MetaConverter.double, IDemoDevice::cosScaleState)
|
val cosScale by mutableProperty(MetaConverter.double, IDemoDevice::cosScaleState)
|
||||||
|
|
||||||
val sin by doubleProperty { sinValue() }
|
val sin by doubleProperty(read = IDemoDevice::sinValue)
|
||||||
val cos by doubleProperty { cosValue() }
|
val cos by doubleProperty(read = IDemoDevice::cosValue)
|
||||||
|
|
||||||
val coordinates by metaProperty(
|
val coordinates by metaProperty(
|
||||||
descriptorBuilder = {
|
descriptorBuilder = {
|
||||||
|
@ -2,8 +2,6 @@ package space.kscience.controls.demo.car
|
|||||||
|
|
||||||
import space.kscience.controls.api.Device
|
import space.kscience.controls.api.Device
|
||||||
import space.kscience.controls.spec.DeviceSpec
|
import space.kscience.controls.spec.DeviceSpec
|
||||||
import space.kscience.controls.spec.mutableProperty
|
|
||||||
import space.kscience.controls.spec.property
|
|
||||||
|
|
||||||
interface IVirtualCar : Device {
|
interface IVirtualCar : Device {
|
||||||
var speedState: Vector2D
|
var speedState: Vector2D
|
||||||
|
@ -89,7 +89,7 @@ class MksPdr900Device(context: Context, meta: Meta) : DeviceBySpec<MksPdr900Devi
|
|||||||
|
|
||||||
override fun build(context: Context, meta: Meta): MksPdr900Device = MksPdr900Device(context, meta)
|
override fun build(context: Context, meta: Meta): MksPdr900Device = MksPdr900Device(context, meta)
|
||||||
|
|
||||||
val powerOn by booleanProperty(read = { readPowerOn() }, write = { _, value -> writePowerOn(value) })
|
val powerOn by booleanProperty(read = MksPdr900Device::readPowerOn, write = MksPdr900Device::writePowerOn)
|
||||||
|
|
||||||
val channel by logicalProperty(MetaConverter.int)
|
val channel by logicalProperty(MetaConverter.int)
|
||||||
|
|
||||||
|
@ -157,13 +157,13 @@ class PiMotionMasterDevice(
|
|||||||
}
|
}
|
||||||
|
|
||||||
val stop by unitAction({
|
val stop by unitAction({
|
||||||
description = "Stop all axis"
|
info = "Stop all axis"
|
||||||
}) {
|
}) {
|
||||||
send("STP")
|
send("STP")
|
||||||
}
|
}
|
||||||
|
|
||||||
val connect by action(MetaConverter.meta, MetaConverter.unit, descriptorBuilder = {
|
val connect by action(MetaConverter.meta, MetaConverter.unit, descriptorBuilder = {
|
||||||
description = "Connect to specific port and initialize axis"
|
info = "Connect to specific port and initialize axis"
|
||||||
}) { portSpec ->
|
}) { portSpec ->
|
||||||
//Clear current actions if present
|
//Clear current actions if present
|
||||||
if (port != null) {
|
if (port != null) {
|
||||||
@ -189,7 +189,7 @@ class PiMotionMasterDevice(
|
|||||||
}
|
}
|
||||||
|
|
||||||
val disconnect by unitAction({
|
val disconnect by unitAction({
|
||||||
description = "Disconnect the program from the device if it is connected"
|
info = "Disconnect the program from the device if it is connected"
|
||||||
}) {
|
}) {
|
||||||
port?.let {
|
port?.let {
|
||||||
execute(stop)
|
execute(stop)
|
||||||
@ -245,8 +245,8 @@ class PiMotionMasterDevice(
|
|||||||
read = {
|
read = {
|
||||||
readAxisBoolean("$command?")
|
readAxisBoolean("$command?")
|
||||||
},
|
},
|
||||||
write = { _, value ->
|
write = {
|
||||||
writeAxisBoolean(command, value)
|
writeAxisBoolean(command, it)
|
||||||
},
|
},
|
||||||
descriptorBuilder = descriptorBuilder
|
descriptorBuilder = descriptorBuilder
|
||||||
)
|
)
|
||||||
@ -259,7 +259,7 @@ class PiMotionMasterDevice(
|
|||||||
mm.requestAndParse("$command?", axisId)[axisId]?.toDoubleOrNull()
|
mm.requestAndParse("$command?", axisId)[axisId]?.toDoubleOrNull()
|
||||||
?: error("Malformed $command response. Should include float value for $axisId")
|
?: error("Malformed $command response. Should include float value for $axisId")
|
||||||
},
|
},
|
||||||
write = { _, newValue ->
|
write = { newValue ->
|
||||||
mm.send(command, axisId, newValue.toString())
|
mm.send(command, axisId, newValue.toString())
|
||||||
mm.failIfError()
|
mm.failIfError()
|
||||||
},
|
},
|
||||||
|
Loading…
Reference in New Issue
Block a user