New builders for devices
This commit is contained in:
parent
bec075328b
commit
34f9108ef7
@ -6,14 +6,14 @@ plugins {
|
||||
}
|
||||
|
||||
val dataforgeVersion: String by extra("0.7.1")
|
||||
val visionforgeVersion by extra("0.3.0-RC")
|
||||
val visionforgeVersion by extra("0.3.1")
|
||||
val ktorVersion: String by extra(space.kscience.gradle.KScienceVersions.ktorVersion)
|
||||
val rsocketVersion by extra("0.15.4")
|
||||
val xodusVersion by extra("2.0.1")
|
||||
|
||||
allprojects {
|
||||
group = "space.kscience"
|
||||
version = "0.3.0-dev-5"
|
||||
version = "0.3.0-dev-6"
|
||||
repositories{
|
||||
maven("https://maven.pkg.jetbrains.space/spc/p/sci/dev")
|
||||
}
|
||||
|
@ -57,8 +57,8 @@ public abstract class DeviceConstructor(
|
||||
*/
|
||||
public fun <T : Any> property(
|
||||
state: DeviceState<T>,
|
||||
nameOverride: String? = null,
|
||||
descriptorBuilder: PropertyDescriptor.() -> Unit = {},
|
||||
nameOverride: String? = null,
|
||||
): PropertyDelegateProvider<DeviceConstructor, ReadOnlyProperty<DeviceConstructor, T>> =
|
||||
PropertyDelegateProvider { _: DeviceConstructor, property ->
|
||||
val name = nameOverride ?: property.name
|
||||
@ -77,11 +77,12 @@ public abstract class DeviceConstructor(
|
||||
reader: suspend () -> T,
|
||||
readInterval: Duration,
|
||||
initialState: T,
|
||||
nameOverride: String? = null,
|
||||
descriptorBuilder: PropertyDescriptor.() -> Unit = {},
|
||||
nameOverride: String? = null,
|
||||
): PropertyDelegateProvider<DeviceConstructor, ReadOnlyProperty<DeviceConstructor, T>> = property(
|
||||
DeviceState.external(this, metaConverter, readInterval, initialState, reader),
|
||||
nameOverride, descriptorBuilder
|
||||
descriptorBuilder,
|
||||
nameOverride,
|
||||
)
|
||||
|
||||
|
||||
@ -90,8 +91,8 @@ public abstract class DeviceConstructor(
|
||||
*/
|
||||
public fun <T : Any> mutableProperty(
|
||||
state: MutableDeviceState<T>,
|
||||
nameOverride: String? = null,
|
||||
descriptorBuilder: PropertyDescriptor.() -> Unit = {},
|
||||
nameOverride: String? = null,
|
||||
): PropertyDelegateProvider<DeviceConstructor, ReadWriteProperty<DeviceConstructor, T>> =
|
||||
PropertyDelegateProvider { _: DeviceConstructor, property ->
|
||||
val name = nameOverride ?: property.name
|
||||
@ -116,11 +117,26 @@ public abstract class DeviceConstructor(
|
||||
writer: suspend (T) -> Unit,
|
||||
readInterval: Duration,
|
||||
initialState: T,
|
||||
nameOverride: String? = null,
|
||||
descriptorBuilder: PropertyDescriptor.() -> Unit = {},
|
||||
nameOverride: String? = null,
|
||||
): PropertyDelegateProvider<DeviceConstructor, ReadWriteProperty<DeviceConstructor, T>> = mutableProperty(
|
||||
DeviceState.external(this, metaConverter, readInterval, initialState, reader, writer),
|
||||
descriptorBuilder,
|
||||
nameOverride,
|
||||
)
|
||||
|
||||
/**
|
||||
* Create and register a virtual property with optional [callback]
|
||||
*/
|
||||
public fun <T : Any> state(
|
||||
metaConverter: MetaConverter<T>,
|
||||
initialState: T,
|
||||
descriptorBuilder: PropertyDescriptor.() -> Unit = {},
|
||||
nameOverride: String? = null,
|
||||
callback: (T) -> Unit = {},
|
||||
): PropertyDelegateProvider<DeviceConstructor, ReadWriteProperty<DeviceConstructor, T>> = mutableProperty(
|
||||
DeviceState.virtual(metaConverter, initialState, callback),
|
||||
descriptorBuilder,
|
||||
nameOverride,
|
||||
descriptorBuilder
|
||||
)
|
||||
}
|
@ -47,9 +47,10 @@ public open class DeviceGroup(
|
||||
override val messageFlow: Flow<DeviceMessage>
|
||||
get() = sharedMessageFlow
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
override val coroutineContext: CoroutineContext = context.newCoroutineContext(
|
||||
SupervisorJob(context.coroutineContext[Job]) +
|
||||
CoroutineName("Device $this") +
|
||||
CoroutineName("Device $id") +
|
||||
CoroutineExceptionHandler { _, throwable ->
|
||||
context.launch {
|
||||
sharedMessageFlow.emit(
|
||||
@ -75,7 +76,7 @@ public open class DeviceGroup(
|
||||
public fun <D : Device> install(token: NameToken, device: D): D {
|
||||
require(_devices[token] == null) { "A child device with name $token already exists" }
|
||||
//start the child device if needed
|
||||
if(lifecycleState == STARTED || lifecycleState == STARTING) launch { device.start() }
|
||||
if (lifecycleState == STARTED || lifecycleState == STARTING) launch { device.start() }
|
||||
_devices[token] = device
|
||||
return device
|
||||
}
|
||||
@ -216,6 +217,9 @@ public fun <D : Device> DeviceGroup.install(name: Name, device: D): D {
|
||||
public fun <D : Device> DeviceGroup.install(name: String, device: D): D =
|
||||
install(name.parseAsName(), device)
|
||||
|
||||
public fun <D : Device> DeviceGroup.install(device: D): D =
|
||||
install(device.id, device)
|
||||
|
||||
public fun <D : Device> Context.install(name: String, device: D): D = request(DeviceManager).install(name, device)
|
||||
|
||||
/**
|
||||
@ -281,15 +285,6 @@ public fun <T : Any> DeviceGroup.registerMutableProperty(
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a virtual [MutableDeviceState], but do not register it to a device
|
||||
*/
|
||||
@Suppress("UnusedReceiverParameter")
|
||||
public fun <T : Any> DeviceGroup.state(
|
||||
converter: MetaConverter<T>,
|
||||
initialValue: T,
|
||||
): MutableDeviceState<T> = VirtualDeviceState<T>(converter, initialValue)
|
||||
|
||||
/**
|
||||
* Create a new virtual mutable state and a property based on it.
|
||||
* @return the mutable state used in property
|
||||
@ -299,8 +294,9 @@ public fun <T : Any> DeviceGroup.registerVirtualProperty(
|
||||
initialValue: T,
|
||||
converter: MetaConverter<T>,
|
||||
descriptorBuilder: PropertyDescriptor.() -> Unit = {},
|
||||
callback: (T) -> Unit = {},
|
||||
): MutableDeviceState<T> {
|
||||
val state = state(converter, initialValue)
|
||||
val state = DeviceState.virtual<T>(converter, initialValue, callback)
|
||||
registerMutableProperty(name, state, descriptorBuilder)
|
||||
return state
|
||||
}
|
||||
|
@ -45,17 +45,49 @@ public var <T : Any> MutableDeviceState<T>.valueAsMeta: Meta
|
||||
|
||||
/**
|
||||
* A [MutableDeviceState] that does not correspond to a physical state
|
||||
*
|
||||
* @param callback a synchronous callback that could be used without a scope
|
||||
*/
|
||||
public class VirtualDeviceState<T>(
|
||||
private class VirtualDeviceState<T>(
|
||||
override val converter: MetaConverter<T>,
|
||||
initialValue: T,
|
||||
private val callback: (T) -> Unit = {},
|
||||
) : MutableDeviceState<T> {
|
||||
private val flow = MutableStateFlow(initialValue)
|
||||
override val valueFlow: Flow<T> get() = flow
|
||||
|
||||
override var value: T by flow::value
|
||||
override var value: T
|
||||
get() = flow.value
|
||||
set(value) {
|
||||
flow.value = value
|
||||
callback(value)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A [MutableDeviceState] that does not correspond to a physical state
|
||||
*
|
||||
* @param callback a synchronous callback that could be used without a scope
|
||||
*/
|
||||
public fun <T> DeviceState.Companion.virtual(
|
||||
converter: MetaConverter<T>,
|
||||
initialValue: T,
|
||||
callback: (T) -> Unit = {},
|
||||
): MutableDeviceState<T> = VirtualDeviceState(converter, initialValue, callback)
|
||||
|
||||
private class StateFlowAsState<T>(
|
||||
override val converter: MetaConverter<T>,
|
||||
val flow: MutableStateFlow<T>,
|
||||
) : MutableDeviceState<T> {
|
||||
override var value: T by flow::value
|
||||
override val valueFlow: Flow<T> get() = flow
|
||||
}
|
||||
|
||||
public fun <T> MutableStateFlow<T>.asDeviceState(converter: MetaConverter<T>): DeviceState<T> =
|
||||
StateFlowAsState(converter, this)
|
||||
|
||||
|
||||
private open class BoundDeviceState<T>(
|
||||
override val converter: MetaConverter<T>,
|
||||
val device: Device,
|
||||
|
@ -10,6 +10,8 @@ import space.kscience.dataforge.context.ContextAware
|
||||
import space.kscience.dataforge.context.info
|
||||
import space.kscience.dataforge.context.logger
|
||||
import space.kscience.dataforge.meta.Meta
|
||||
import space.kscience.dataforge.meta.get
|
||||
import space.kscience.dataforge.meta.string
|
||||
import space.kscience.dataforge.misc.DFExperimental
|
||||
import space.kscience.dataforge.misc.DfType
|
||||
import space.kscience.dataforge.names.parseAsName
|
||||
@ -111,6 +113,11 @@ public interface Device : ContextAware, CoroutineScope {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Inner id of a device. Not necessary corresponds to the name in the parent container
|
||||
*/
|
||||
public val Device.id: String get() = meta["id"].string?: "device[${hashCode().toString(16)}]"
|
||||
|
||||
/**
|
||||
* Device that caches properties values
|
||||
*/
|
||||
|
@ -4,6 +4,7 @@ import kotlinx.coroutines.launch
|
||||
import space.kscience.controls.api.Device
|
||||
import space.kscience.controls.api.DeviceHub
|
||||
import space.kscience.controls.api.getOrNull
|
||||
import space.kscience.controls.api.id
|
||||
import space.kscience.dataforge.context.*
|
||||
import space.kscience.dataforge.meta.Meta
|
||||
import space.kscience.dataforge.meta.MutableMeta
|
||||
@ -45,6 +46,8 @@ public fun <D : Device> DeviceManager.install(name: String, device: D): D {
|
||||
return device
|
||||
}
|
||||
|
||||
public fun <D : Device> DeviceManager.install(device: D): D = install(device.id, device)
|
||||
|
||||
|
||||
/**
|
||||
* Register and start a device built by [factory] with current [Context] and [meta].
|
||||
|
Loading…
Reference in New Issue
Block a user