Implemented external configuration support through ExternalConfigurationProvider and ExternalConfigApplier, and expanded error handling in AbstractDeviceHubManager with CUSTOM strategy support. Improved DeviceLifecycleConfig, added HealthChecker support for device health checks. Implemented hot-swappable device functionality.
This commit is contained in:
parent
76fa751e25
commit
7e286ca111
@ -8,6 +8,11 @@ import kotlinx.serialization.Serializable
|
|||||||
@Serializable
|
@Serializable
|
||||||
public enum class LifecycleState {
|
public enum class LifecycleState {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The device is newly created and has not started yet.
|
||||||
|
*/
|
||||||
|
INITIAL,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Device is initializing
|
* Device is initializing
|
||||||
*/
|
*/
|
||||||
@ -18,6 +23,11 @@ public enum class LifecycleState {
|
|||||||
*/
|
*/
|
||||||
STARTED,
|
STARTED,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Device is stopping
|
||||||
|
*/
|
||||||
|
STOPPING,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Device is closed
|
* The Device is closed
|
||||||
*/
|
*/
|
||||||
@ -50,8 +60,10 @@ public interface WithLifeCycle {
|
|||||||
public fun WithLifeCycle.bindToDeviceLifecycle(device: Device){
|
public fun WithLifeCycle.bindToDeviceLifecycle(device: Device){
|
||||||
device.onLifecycleEvent {
|
device.onLifecycleEvent {
|
||||||
when(it){
|
when(it){
|
||||||
|
LifecycleState.INITIAL -> {/*ignore*/}
|
||||||
LifecycleState.STARTING -> start()
|
LifecycleState.STARTING -> start()
|
||||||
LifecycleState.STARTED -> {/*ignore*/}
|
LifecycleState.STARTED -> {/*ignore*/}
|
||||||
|
LifecycleState.STOPPING -> stop()
|
||||||
LifecycleState.STOPPED -> stop()
|
LifecycleState.STOPPED -> stop()
|
||||||
LifecycleState.ERROR -> stop()
|
LifecycleState.ERROR -> stop()
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,384 +1,248 @@
|
|||||||
package space.kscience.controls.spec
|
package space.kscience.controls.spec
|
||||||
|
|
||||||
import kotlinx.coroutines.Deferred
|
import kotlinx.coroutines.Deferred
|
||||||
import space.kscience.controls.api.ActionDescriptorBuilder
|
import space.kscience.controls.api.*
|
||||||
import space.kscience.controls.api.Device
|
import space.kscience.dataforge.meta.*
|
||||||
import space.kscience.controls.api.PropertyDescriptorBuilder
|
|
||||||
import space.kscience.controls.api.id
|
|
||||||
import space.kscience.dataforge.meta.Meta
|
|
||||||
import space.kscience.dataforge.meta.MetaConverter
|
|
||||||
import space.kscience.dataforge.meta.ValueType
|
|
||||||
import space.kscience.dataforge.meta.descriptors.MetaDescriptor
|
import space.kscience.dataforge.meta.descriptors.MetaDescriptor
|
||||||
import space.kscience.dataforge.meta.string
|
|
||||||
import kotlin.properties.PropertyDelegateProvider
|
import kotlin.properties.PropertyDelegateProvider
|
||||||
import kotlin.properties.ReadOnlyProperty
|
import kotlin.properties.ReadOnlyProperty
|
||||||
import kotlin.reflect.KMutableProperty1
|
|
||||||
import kotlin.reflect.KProperty1
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a [MetaConverter] for enum values
|
* Create a [MetaConverter] for enum values using [reified] type with an option to ignore case.
|
||||||
*/
|
*/
|
||||||
public fun <E : Enum<E>> createEnumConverter(enumValues: Array<E>): MetaConverter<E> = object : MetaConverter<E> {
|
public inline fun <reified E : Enum<E>> createEnumConverter(ignoreCase: Boolean = false): MetaConverter<E> {
|
||||||
|
val allValues = enumValues<E>()
|
||||||
|
return object : MetaConverter<E> {
|
||||||
override val descriptor: MetaDescriptor = MetaDescriptor {
|
override val descriptor: MetaDescriptor = MetaDescriptor {
|
||||||
valueType(ValueType.STRING)
|
valueType(ValueType.STRING)
|
||||||
allowedValues(enumValues.map { it.name })
|
allowedValues(allValues.map { it.name })
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun readOrNull(source: Meta): E? {
|
override fun readOrNull(source: Meta): E? {
|
||||||
val value = source.value ?: return null
|
val stringVal = source.value?.string ?: return null
|
||||||
return enumValues.firstOrNull { it.name == value.string }
|
return allValues.firstOrNull { it.name.equals(stringVal, ignoreCase) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun convert(obj: E): Meta = Meta(obj.name)
|
override fun convert(obj: E): Meta = Meta(obj.name)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A read-only device property that delegates reading to a device [KProperty1]
|
* Unified function: if [write] == null -> read-only property, else -> mutable property.
|
||||||
*/
|
*/
|
||||||
public fun <T, D : Device> CompositeControlComponentSpec<D>.property(
|
public fun <T, D : ConfigurableCompositeControlComponent<D>> CompositeControlComponentSpec<D>.typedProperty(
|
||||||
converter: MetaConverter<T>,
|
converter: MetaConverter<T>,
|
||||||
descriptorBuilder: PropertyDescriptorBuilder.() -> Unit = {},
|
|
||||||
name: String? = null,
|
name: String? = null,
|
||||||
read: suspend D.(propertyName: String) -> T?,
|
descriptorBuilder: PropertyDescriptorBuilder.() -> Unit = {},
|
||||||
|
read: suspend D.(String) -> T?,
|
||||||
|
write: (suspend D.(String, T) -> Unit)? = null,
|
||||||
): PropertyDelegateProvider<CompositeControlComponentSpec<D>, ReadOnlyProperty<CompositeControlComponentSpec<D>, DevicePropertySpec<D, T>>> {
|
): PropertyDelegateProvider<CompositeControlComponentSpec<D>, ReadOnlyProperty<CompositeControlComponentSpec<D>, DevicePropertySpec<D, T>>> {
|
||||||
return property(converter, descriptorBuilder, name, read)
|
return if (write == null) {
|
||||||
|
property(converter, descriptorBuilder, name, read)
|
||||||
|
} else {
|
||||||
|
mutableProperty(converter, descriptorBuilder, name, read, write)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mutable property that delegates reading and writing to a device [KMutableProperty1]
|
* Boolean property: read-only or mutable (if [write] is not null).
|
||||||
*/
|
*/
|
||||||
public fun <T, D : Device> CompositeControlComponentSpec<D>.mutableProperty(
|
public fun <D : ConfigurableCompositeControlComponent<D>> CompositeControlComponentSpec<D>.booleanProperty(
|
||||||
converter: MetaConverter<T>,
|
|
||||||
descriptorBuilder: PropertyDescriptorBuilder.() -> Unit = {},
|
|
||||||
name: String? = null,
|
name: String? = null,
|
||||||
read: suspend D.(propertyName: String) -> T?,
|
descriptorBuilder: PropertyDescriptorBuilder.() -> Unit = {},
|
||||||
write: suspend D.(propertyName: String, value: T) -> Unit,
|
read: suspend D.(String) -> Boolean?,
|
||||||
): PropertyDelegateProvider<CompositeControlComponentSpec<D>, ReadOnlyProperty<CompositeControlComponentSpec<D>, MutableDevicePropertySpec<D, T>>> {
|
write: (suspend D.(String, Boolean) -> Unit)? = null,
|
||||||
return mutableProperty(converter, descriptorBuilder, name, read, write)
|
) = typedProperty(MetaConverter.boolean, name, descriptorBuilder, read, write)
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register a mutable logical property (without a corresponding physical state) for a device
|
* Int property: read-only or mutable.
|
||||||
*/
|
*/
|
||||||
public fun <T, D : DeviceBase<D>> CompositeControlComponentSpec<D>.logical(
|
public fun <D : ConfigurableCompositeControlComponent<D>> CompositeControlComponentSpec<D>.intProperty(
|
||||||
converter: MetaConverter<T>,
|
|
||||||
descriptorBuilder: PropertyDescriptorBuilder.() -> Unit = {},
|
|
||||||
name: String? = null,
|
name: String? = null,
|
||||||
): PropertyDelegateProvider<CompositeControlComponentSpec<D>, ReadOnlyProperty<CompositeControlComponentSpec<D>, MutableDevicePropertySpec<D, T>>> =
|
descriptorBuilder: PropertyDescriptorBuilder.() -> Unit = {},
|
||||||
mutableProperty(
|
read: suspend D.(String) -> Int?,
|
||||||
converter,
|
write: (suspend D.(String, Int) -> Unit)? = null,
|
||||||
descriptorBuilder,
|
) = typedProperty(MetaConverter.int, name, descriptorBuilder, read, write)
|
||||||
name,
|
|
||||||
|
/**
|
||||||
|
* Double property: read-only or mutable.
|
||||||
|
*/
|
||||||
|
public fun <D : ConfigurableCompositeControlComponent<D>> CompositeControlComponentSpec<D>.doubleProperty(
|
||||||
|
name: String? = null,
|
||||||
|
descriptorBuilder: PropertyDescriptorBuilder.() -> Unit = {},
|
||||||
|
read: suspend D.(String) -> Double?,
|
||||||
|
write: (suspend D.(String, Double) -> Unit)? = null,
|
||||||
|
) = typedProperty(MetaConverter.double, name, descriptorBuilder, read, write)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Long property: read-only or mutable.
|
||||||
|
*/
|
||||||
|
public fun <D : ConfigurableCompositeControlComponent<D>> CompositeControlComponentSpec<D>.longProperty(
|
||||||
|
name: String? = null,
|
||||||
|
descriptorBuilder: PropertyDescriptorBuilder.() -> Unit = {},
|
||||||
|
read: suspend D.(String) -> Long?,
|
||||||
|
write: (suspend D.(String, Long) -> Unit)? = null,
|
||||||
|
) = typedProperty(MetaConverter.long, name, descriptorBuilder, read, write)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Float property: read-only or mutable.
|
||||||
|
*/
|
||||||
|
public fun <D : ConfigurableCompositeControlComponent<D>> CompositeControlComponentSpec<D>.floatProperty(
|
||||||
|
name: String? = null,
|
||||||
|
descriptorBuilder: PropertyDescriptorBuilder.() -> Unit = {},
|
||||||
|
read: suspend D.(String) -> Float?,
|
||||||
|
write: (suspend D.(String, Float) -> Unit)? = null,
|
||||||
|
) = typedProperty(MetaConverter.float, name, descriptorBuilder, read, write)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Number property: read-only or mutable.
|
||||||
|
*/
|
||||||
|
public fun <D : ConfigurableCompositeControlComponent<D>> CompositeControlComponentSpec<D>.numberProperty(
|
||||||
|
name: String? = null,
|
||||||
|
descriptorBuilder: PropertyDescriptorBuilder.() -> Unit = {},
|
||||||
|
read: suspend D.(String) -> Number?,
|
||||||
|
write: (suspend D.(String, Number) -> Unit)? = null,
|
||||||
|
) = typedProperty(MetaConverter.number, name, descriptorBuilder, read, write)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* String property: read-only or mutable.
|
||||||
|
*/
|
||||||
|
public fun <D : ConfigurableCompositeControlComponent<D>> CompositeControlComponentSpec<D>.stringProperty(
|
||||||
|
name: String? = null,
|
||||||
|
descriptorBuilder: PropertyDescriptorBuilder.() -> Unit = {},
|
||||||
|
read: suspend D.(String) -> String?,
|
||||||
|
write: (suspend D.(String, String) -> Unit)? = null,
|
||||||
|
) = typedProperty(MetaConverter.string, name, descriptorBuilder, read, write)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Meta property: read-only or mutable.
|
||||||
|
*/
|
||||||
|
public fun <D : ConfigurableCompositeControlComponent<D>> CompositeControlComponentSpec<D>.metaProperty(
|
||||||
|
name: String? = null,
|
||||||
|
descriptorBuilder: PropertyDescriptorBuilder.() -> Unit = {},
|
||||||
|
read: suspend D.(String) -> Meta?,
|
||||||
|
write: (suspend D.(String, Meta) -> Unit)? = null,
|
||||||
|
) = typedProperty(MetaConverter.meta, name, descriptorBuilder, read, write)
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enum property (read-only or mutable).
|
||||||
|
* [ignoreCase] controls case sensitivity when reading the enum value from Meta.
|
||||||
|
* If [write] is null, the property is read-only; otherwise it's read-write.
|
||||||
|
*/
|
||||||
|
public inline fun <reified E : Enum<E>, D : ConfigurableCompositeControlComponent<D>>
|
||||||
|
CompositeControlComponentSpec<D>.enumProperty(
|
||||||
|
name: String? = null,
|
||||||
|
ignoreCase: Boolean = false,
|
||||||
|
noinline descriptorBuilder: PropertyDescriptorBuilder.() -> Unit = {},
|
||||||
|
noinline read: suspend D.(String) -> E?,
|
||||||
|
noinline write: (suspend D.(String, E) -> Unit)? = null,
|
||||||
|
): PropertyDelegateProvider<CompositeControlComponentSpec<D>, ReadOnlyProperty<CompositeControlComponentSpec<D>, DevicePropertySpec<D, E>>> =
|
||||||
|
typedProperty(
|
||||||
|
converter = createEnumConverter<E>(ignoreCase),
|
||||||
|
name = name,
|
||||||
|
descriptorBuilder = descriptorBuilder,
|
||||||
|
read = read,
|
||||||
|
write = write
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List property: read-only or mutable.
|
||||||
|
*/
|
||||||
|
public fun <T, D : ConfigurableCompositeControlComponent<D>> CompositeControlComponentSpec<D>.listProperty(
|
||||||
|
listConverter: MetaConverter<List<T>>,
|
||||||
|
name: String? = null,
|
||||||
|
descriptorBuilder: PropertyDescriptorBuilder.() -> Unit = {},
|
||||||
|
read: suspend D.(String) -> List<T>?,
|
||||||
|
write: (suspend D.(String, List<T>) -> Unit)? = null,
|
||||||
|
) = typedProperty(listConverter, name, descriptorBuilder, read, write)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logical property (no real hardware I/O).
|
||||||
|
*/
|
||||||
|
public fun <T, D : ConfigurableCompositeControlComponent<D>> CompositeControlComponentSpec<D>.logicalProperty(
|
||||||
|
converter: MetaConverter<T>,
|
||||||
|
name: String? = null,
|
||||||
|
descriptorBuilder: PropertyDescriptorBuilder.() -> Unit = {},
|
||||||
|
) = typedProperty(
|
||||||
|
converter = converter,
|
||||||
|
name = name,
|
||||||
|
descriptorBuilder = descriptorBuilder,
|
||||||
read = { propertyName -> getProperty(propertyName)?.let(converter::readOrNull) },
|
read = { propertyName -> getProperty(propertyName)?.let(converter::readOrNull) },
|
||||||
write = { propertyName, value -> writeProperty(propertyName, converter.convert(value)) }
|
write = { propertyName, value -> writeProperty(propertyName, converter.convert(value)) }
|
||||||
)
|
)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a boolean property for a device.
|
* Creates an action with optional input/output converters.
|
||||||
*/
|
*/
|
||||||
public fun <D : Device> CompositeControlComponentSpec<D>.boolean(
|
public fun <I, O, D : ConfigurableCompositeControlComponent<D>> CompositeControlComponentSpec<D>.typedAction(
|
||||||
descriptorBuilder: PropertyDescriptorBuilder.() -> Unit = {},
|
|
||||||
name: String? = null,
|
|
||||||
read: suspend D.(propertyName: String) -> Boolean?,
|
|
||||||
): PropertyDelegateProvider<CompositeControlComponentSpec<D>, ReadOnlyProperty<CompositeControlComponentSpec<D>, DevicePropertySpec<D, Boolean>>> =
|
|
||||||
property(MetaConverter.boolean, descriptorBuilder, name, read)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a mutable boolean property for a device.
|
|
||||||
*/
|
|
||||||
public fun <D : Device> CompositeControlComponentSpec<D>.booleanMutable(
|
|
||||||
descriptorBuilder: PropertyDescriptorBuilder.() -> Unit = {},
|
|
||||||
name: String? = null,
|
|
||||||
read: suspend D.(propertyName: String) -> Boolean?,
|
|
||||||
write: suspend D.(propertyName: String, value: Boolean) -> Unit
|
|
||||||
): PropertyDelegateProvider<CompositeControlComponentSpec<D>, ReadOnlyProperty<CompositeControlComponentSpec<D>, MutableDevicePropertySpec<D, Boolean>>> =
|
|
||||||
mutableProperty(MetaConverter.boolean, descriptorBuilder, name, read, write)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a read-only number property for a device.
|
|
||||||
*/
|
|
||||||
public fun <D : Device> CompositeControlComponentSpec<D>.number(
|
|
||||||
descriptorBuilder: PropertyDescriptorBuilder.() -> Unit = {},
|
|
||||||
name: String? = null,
|
|
||||||
read: suspend D.(propertyName: String) -> Number?,
|
|
||||||
): PropertyDelegateProvider<CompositeControlComponentSpec<D>, ReadOnlyProperty<CompositeControlComponentSpec<D>, DevicePropertySpec<D, Number>>> =
|
|
||||||
property(MetaConverter.number, descriptorBuilder, name, read)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a mutable number property for a device.
|
|
||||||
*/
|
|
||||||
public fun <D : Device> CompositeControlComponentSpec<D>.numberMutable(
|
|
||||||
descriptorBuilder: PropertyDescriptorBuilder.() -> Unit = {},
|
|
||||||
name: String? = null,
|
|
||||||
read: suspend D.(propertyName: String) -> Number?,
|
|
||||||
write: suspend D.(propertyName: String, value: Number) -> Unit
|
|
||||||
): PropertyDelegateProvider<CompositeControlComponentSpec<D>, ReadOnlyProperty<CompositeControlComponentSpec<D>, MutableDevicePropertySpec<D, Number>>> =
|
|
||||||
mutableProperty(MetaConverter.number, descriptorBuilder, name, read, write)
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a read-only double property for a device.
|
|
||||||
*/
|
|
||||||
public fun <D : Device> CompositeControlComponentSpec<D>.double(
|
|
||||||
descriptorBuilder: PropertyDescriptorBuilder.() -> Unit = {},
|
|
||||||
name: String? = null,
|
|
||||||
read: suspend D.(propertyName: String) -> Double?,
|
|
||||||
): PropertyDelegateProvider<CompositeControlComponentSpec<D>, ReadOnlyProperty<CompositeControlComponentSpec<D>, DevicePropertySpec<D, Double>>> =
|
|
||||||
property(MetaConverter.double, descriptorBuilder, name, read)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a mutable double property for a device.
|
|
||||||
*/
|
|
||||||
public fun <D : Device> CompositeControlComponentSpec<D>.doubleMutable(
|
|
||||||
descriptorBuilder: PropertyDescriptorBuilder.() -> Unit = {},
|
|
||||||
name: String? = null,
|
|
||||||
read: suspend D.(propertyName: String) -> Double?,
|
|
||||||
write: suspend D.(propertyName: String, value: Double) -> Unit
|
|
||||||
): PropertyDelegateProvider<CompositeControlComponentSpec<D>, ReadOnlyProperty<CompositeControlComponentSpec<D>, MutableDevicePropertySpec<D, Double>>> =
|
|
||||||
mutableProperty(MetaConverter.double, descriptorBuilder, name, read, write)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a read-only string property for a device.
|
|
||||||
*/
|
|
||||||
public fun <D : Device> CompositeControlComponentSpec<D>.string(
|
|
||||||
descriptorBuilder: PropertyDescriptorBuilder.() -> Unit = {},
|
|
||||||
name: String? = null,
|
|
||||||
read: suspend D.(propertyName: String) -> String?
|
|
||||||
): PropertyDelegateProvider<CompositeControlComponentSpec<D>, ReadOnlyProperty<CompositeControlComponentSpec<D>, DevicePropertySpec<D, String>>> =
|
|
||||||
property(MetaConverter.string, descriptorBuilder, name, read)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a mutable string property for a device.
|
|
||||||
*/
|
|
||||||
public fun <D : Device> CompositeControlComponentSpec<D>.stringMutableProperty(
|
|
||||||
descriptorBuilder: PropertyDescriptorBuilder.() -> Unit = {},
|
|
||||||
name: String? = null,
|
|
||||||
read: suspend D.(propertyName: String) -> String?,
|
|
||||||
write: suspend D.(propertyName: String, value: String) -> Unit
|
|
||||||
): PropertyDelegateProvider<CompositeControlComponentSpec<D>, ReadOnlyProperty<CompositeControlComponentSpec<D>, MutableDevicePropertySpec<D, String>>> =
|
|
||||||
mutableProperty(MetaConverter.string, descriptorBuilder, name, read, write)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a read-only meta property for a device.
|
|
||||||
*/
|
|
||||||
public fun <D : Device> CompositeControlComponentSpec<D>.meta(
|
|
||||||
descriptorBuilder: PropertyDescriptorBuilder.() -> Unit = {},
|
|
||||||
name: String? = null,
|
|
||||||
read: suspend D.(propertyName: String) -> Meta?,
|
|
||||||
): PropertyDelegateProvider<CompositeControlComponentSpec<D>, ReadOnlyProperty<CompositeControlComponentSpec<D>, DevicePropertySpec<D, Meta>>> =
|
|
||||||
property(MetaConverter.meta, descriptorBuilder, name, read)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a mutable meta property for a device.
|
|
||||||
*/
|
|
||||||
public fun <D : Device> CompositeControlComponentSpec<D>.metaMutable(
|
|
||||||
descriptorBuilder: PropertyDescriptorBuilder.() -> Unit = {},
|
|
||||||
name: String? = null,
|
|
||||||
read: suspend D.(propertyName: String) -> Meta?,
|
|
||||||
write: suspend D.(propertyName: String, value: Meta) -> Unit
|
|
||||||
): PropertyDelegateProvider<CompositeControlComponentSpec<D>, ReadOnlyProperty<CompositeControlComponentSpec<D>, MutableDevicePropertySpec<D, Meta>>> =
|
|
||||||
mutableProperty(MetaConverter.meta, descriptorBuilder, name, read, write)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a read-only enum property for a device.
|
|
||||||
*/
|
|
||||||
public fun <E : Enum<E>, D : Device> CompositeControlComponentSpec<D>.enum(
|
|
||||||
enumValues: Array<E>,
|
|
||||||
descriptorBuilder: PropertyDescriptorBuilder.() -> Unit = {},
|
|
||||||
name: String? = null,
|
|
||||||
read: suspend D.(propertyName: String) -> E?,
|
|
||||||
): PropertyDelegateProvider<CompositeControlComponentSpec<D>, ReadOnlyProperty<CompositeControlComponentSpec<D>, DevicePropertySpec<D, E>>> {
|
|
||||||
val converter = createEnumConverter(enumValues)
|
|
||||||
return property(converter, descriptorBuilder, name, read)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a mutable enum property for a device.
|
|
||||||
*/
|
|
||||||
public fun <E : Enum<E>, D : Device> CompositeControlComponentSpec<D>.enumMutable(
|
|
||||||
enumValues: Array<E>,
|
|
||||||
descriptorBuilder: PropertyDescriptorBuilder.() -> Unit = {},
|
|
||||||
name: String? = null,
|
|
||||||
read: suspend D.(propertyName: String) -> E?,
|
|
||||||
write: suspend D.(propertyName: String, value: E) -> Unit
|
|
||||||
): PropertyDelegateProvider<CompositeControlComponentSpec<D>, ReadOnlyProperty<CompositeControlComponentSpec<D>, MutableDevicePropertySpec<D, E>>> {
|
|
||||||
val converter = createEnumConverter(enumValues)
|
|
||||||
return mutableProperty(converter, descriptorBuilder, name, read, write)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a read-only float property for a device.
|
|
||||||
*/
|
|
||||||
public fun <D : Device> CompositeControlComponentSpec<D>.float(
|
|
||||||
descriptorBuilder: PropertyDescriptorBuilder.() -> Unit = {},
|
|
||||||
name: String? = null,
|
|
||||||
read: suspend D.(propertyName: String) -> Float?,
|
|
||||||
): PropertyDelegateProvider<CompositeControlComponentSpec<D>, ReadOnlyProperty<CompositeControlComponentSpec<D>, DevicePropertySpec<D, Float>>> =
|
|
||||||
property(MetaConverter.float, descriptorBuilder, name, read)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a mutable float property for a device.
|
|
||||||
*/
|
|
||||||
public fun <D : Device> CompositeControlComponentSpec<D>.floatMutable(
|
|
||||||
descriptorBuilder: PropertyDescriptorBuilder.() -> Unit = {},
|
|
||||||
name: String? = null,
|
|
||||||
read: suspend D.(propertyName: String) -> Float?,
|
|
||||||
write: suspend D.(propertyName: String, value: Float) -> Unit
|
|
||||||
): PropertyDelegateProvider<CompositeControlComponentSpec<D>, ReadOnlyProperty<CompositeControlComponentSpec<D>, MutableDevicePropertySpec<D, Float>>> =
|
|
||||||
mutableProperty(MetaConverter.float, descriptorBuilder, name, read, write)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a read-only long property for a device.
|
|
||||||
*/
|
|
||||||
public fun <D : Device> CompositeControlComponentSpec<D>.long(
|
|
||||||
descriptorBuilder: PropertyDescriptorBuilder.() -> Unit = {},
|
|
||||||
name: String? = null,
|
|
||||||
read: suspend D.(propertyName: String) -> Long?,
|
|
||||||
): PropertyDelegateProvider<CompositeControlComponentSpec<D>, ReadOnlyProperty<CompositeControlComponentSpec<D>, DevicePropertySpec<D, Long>>> =
|
|
||||||
property(MetaConverter.long, descriptorBuilder, name, read)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a mutable long property for a device.
|
|
||||||
*/
|
|
||||||
public fun <D : Device> CompositeControlComponentSpec<D>.longMutable(
|
|
||||||
descriptorBuilder: PropertyDescriptorBuilder.() -> Unit = {},
|
|
||||||
name: String? = null,
|
|
||||||
read: suspend D.(propertyName: String) -> Long?,
|
|
||||||
write: suspend D.(propertyName: String, value: Long) -> Unit
|
|
||||||
): PropertyDelegateProvider<CompositeControlComponentSpec<D>, ReadOnlyProperty<CompositeControlComponentSpec<D>, MutableDevicePropertySpec<D, Long>>> =
|
|
||||||
mutableProperty(MetaConverter.long, descriptorBuilder, name, read, write)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a read-only int property for a device.
|
|
||||||
*/
|
|
||||||
public fun <D : Device> CompositeControlComponentSpec<D>.int(
|
|
||||||
descriptorBuilder: PropertyDescriptorBuilder.() -> Unit = {},
|
|
||||||
name: String? = null,
|
|
||||||
read: suspend D.(propertyName: String) -> Int?,
|
|
||||||
): PropertyDelegateProvider<CompositeControlComponentSpec<D>, ReadOnlyProperty<CompositeControlComponentSpec<D>, DevicePropertySpec<D, Int>>> =
|
|
||||||
property(MetaConverter.int, descriptorBuilder, name, read)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a mutable int property for a device.
|
|
||||||
*/
|
|
||||||
public fun <D : Device> CompositeControlComponentSpec<D>.intMutable(
|
|
||||||
descriptorBuilder: PropertyDescriptorBuilder.() -> Unit = {},
|
|
||||||
name: String? = null,
|
|
||||||
read: suspend D.(propertyName: String) -> Int?,
|
|
||||||
write: suspend D.(propertyName: String, value: Int) -> Unit
|
|
||||||
): PropertyDelegateProvider<CompositeControlComponentSpec<D>, ReadOnlyProperty<CompositeControlComponentSpec<D>, MutableDevicePropertySpec<D, Int>>> =
|
|
||||||
mutableProperty(MetaConverter.int, descriptorBuilder, name, read, write)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a read-only list property for a device.
|
|
||||||
*/
|
|
||||||
public fun <T, D : Device> CompositeControlComponentSpec<D>.list(
|
|
||||||
converter: MetaConverter<List<T>>,
|
|
||||||
descriptorBuilder: PropertyDescriptorBuilder.() -> Unit = {},
|
|
||||||
name: String? = null,
|
|
||||||
read: suspend D.(propertyName: String) -> List<T>?,
|
|
||||||
): PropertyDelegateProvider<CompositeControlComponentSpec<D>, ReadOnlyProperty<CompositeControlComponentSpec<D>, DevicePropertySpec<D, List<T>>>> =
|
|
||||||
property(converter, descriptorBuilder, name, read)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a mutable list property for a device.
|
|
||||||
*/
|
|
||||||
public fun <T, D : Device> CompositeControlComponentSpec<D>.listMutable(
|
|
||||||
converter: MetaConverter<List<T>>,
|
|
||||||
descriptorBuilder: PropertyDescriptorBuilder.() -> Unit = {},
|
|
||||||
name: String? = null,
|
|
||||||
read: suspend D.(propertyName: String) -> List<T>?,
|
|
||||||
write: suspend D.(propertyName: String, value: List<T>) -> Unit
|
|
||||||
): PropertyDelegateProvider<CompositeControlComponentSpec<D>, ReadOnlyProperty<CompositeControlComponentSpec<D>, MutableDevicePropertySpec<D, List<T>>>> =
|
|
||||||
mutableProperty(converter, descriptorBuilder, name, read, write)
|
|
||||||
|
|
||||||
|
|
||||||
public fun <I, O, D : Device> CompositeControlComponentSpec<D>.asyncActionProperty(
|
|
||||||
inputConverter: MetaConverter<I>,
|
inputConverter: MetaConverter<I>,
|
||||||
outputConverter: MetaConverter<O>,
|
outputConverter: MetaConverter<O>,
|
||||||
|
name: String? = null,
|
||||||
descriptorBuilder: ActionDescriptorBuilder.() -> Unit = {},
|
descriptorBuilder: ActionDescriptorBuilder.() -> Unit = {},
|
||||||
name: String? = null,
|
execute: suspend D.(I) -> O,
|
||||||
execute: suspend D.(I) -> Deferred<O>,
|
|
||||||
): PropertyDelegateProvider<CompositeControlComponentSpec<D>, ReadOnlyProperty<CompositeControlComponentSpec<D>, DeviceActionSpec<D, I, O>>> =
|
): PropertyDelegateProvider<CompositeControlComponentSpec<D>, ReadOnlyProperty<CompositeControlComponentSpec<D>, DeviceActionSpec<D, I, O>>> =
|
||||||
action(inputConverter, outputConverter, descriptorBuilder, name) { input ->
|
action(
|
||||||
execute(input).await()
|
inputConverter = inputConverter,
|
||||||
}
|
outputConverter = outputConverter,
|
||||||
|
descriptorBuilder = descriptorBuilder,
|
||||||
public fun <T, D : Device> CompositeControlComponentSpec<D>.metaProperty(
|
name = name,
|
||||||
descriptorBuilder: PropertyDescriptorBuilder.() -> Unit = {},
|
execute = execute
|
||||||
name: String? = null,
|
)
|
||||||
read: suspend D.(propertyName: String) -> Meta?,
|
|
||||||
): PropertyDelegateProvider<CompositeControlComponentSpec<D>, ReadOnlyProperty<CompositeControlComponentSpec<D>, DevicePropertySpec<D, Meta>>> =
|
|
||||||
property(MetaConverter.meta, descriptorBuilder, name, read)
|
|
||||||
|
|
||||||
|
|
||||||
public fun <T, D : Device> CompositeControlComponentSpec<D>.mutableMetaProperty(
|
|
||||||
descriptorBuilder: PropertyDescriptorBuilder.() -> Unit = {},
|
|
||||||
name: String? = null,
|
|
||||||
read: suspend D.(propertyName: String) -> Meta?,
|
|
||||||
write: suspend D.(propertyName: String, value: Meta) -> Unit
|
|
||||||
): PropertyDelegateProvider<CompositeControlComponentSpec<D>, ReadOnlyProperty<CompositeControlComponentSpec<D>, MutableDevicePropertySpec<D, Meta>>> =
|
|
||||||
mutableProperty(MetaConverter.meta, descriptorBuilder, name, read, write)
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An action that takes no parameters and returns no values
|
* Action with no parameters and no return values.
|
||||||
*/
|
*/
|
||||||
public fun <T, D : Device> CompositeControlComponentSpec<D>.unitAction(
|
public fun <D : ConfigurableCompositeControlComponent<D>> CompositeControlComponentSpec<D>.unitAction(
|
||||||
descriptorBuilder: ActionDescriptorBuilder.() -> Unit = {},
|
|
||||||
name: String? = null,
|
name: String? = null,
|
||||||
|
descriptorBuilder: ActionDescriptorBuilder.() -> Unit = {},
|
||||||
execute: suspend D.() -> Unit,
|
execute: suspend D.() -> Unit,
|
||||||
): PropertyDelegateProvider<CompositeControlComponentSpec<D>, ReadOnlyProperty<CompositeControlComponentSpec<D>, DeviceActionSpec<D, Unit, Unit>>> =
|
): PropertyDelegateProvider<CompositeControlComponentSpec<D>, ReadOnlyProperty<CompositeControlComponentSpec<D>, DeviceActionSpec<D, Unit, Unit>>> =
|
||||||
action(
|
typedAction(
|
||||||
MetaConverter.unit,
|
inputConverter = MetaConverter.unit,
|
||||||
MetaConverter.unit,
|
outputConverter = MetaConverter.unit,
|
||||||
descriptorBuilder,
|
name = name,
|
||||||
name
|
descriptorBuilder = descriptorBuilder,
|
||||||
) {
|
) {
|
||||||
execute()
|
execute()
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun <I, O, D : Device> CompositeControlComponentSpec<D>.asyncAction(
|
/**
|
||||||
|
* Action with async result. The result is awaited.
|
||||||
|
*/
|
||||||
|
public fun <I, O, D : ConfigurableCompositeControlComponent<D>> CompositeControlComponentSpec<D>.asyncAction(
|
||||||
inputConverter: MetaConverter<I>,
|
inputConverter: MetaConverter<I>,
|
||||||
outputConverter: MetaConverter<O>,
|
outputConverter: MetaConverter<O>,
|
||||||
descriptorBuilder: ActionDescriptorBuilder.() -> Unit = {},
|
|
||||||
name: String? = null,
|
name: String? = null,
|
||||||
|
descriptorBuilder: ActionDescriptorBuilder.() -> Unit = {},
|
||||||
execute: suspend D.(I) -> Deferred<O>,
|
execute: suspend D.(I) -> Deferred<O>,
|
||||||
): PropertyDelegateProvider<CompositeControlComponentSpec<D>, ReadOnlyProperty<CompositeControlComponentSpec<D>, DeviceActionSpec<D, I, O>>> =
|
): PropertyDelegateProvider<CompositeControlComponentSpec<D>, ReadOnlyProperty<CompositeControlComponentSpec<D>, DeviceActionSpec<D, I, O>>> =
|
||||||
action(
|
typedAction(inputConverter, outputConverter, name, descriptorBuilder) { input ->
|
||||||
inputConverter,
|
execute(input).await()
|
||||||
outputConverter,
|
|
||||||
descriptorBuilder,
|
|
||||||
name
|
|
||||||
) {
|
|
||||||
execute(it).await()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An action that takes [Meta] and returns [Meta]. No conversions are done
|
* Action that takes and returns [Meta].
|
||||||
*/
|
*/
|
||||||
public fun <T, D : Device> CompositeControlComponentSpec<D>.metaAction(
|
public fun <D : ConfigurableCompositeControlComponent<D>> CompositeControlComponentSpec<D>.metaAction(
|
||||||
descriptorBuilder: ActionDescriptorBuilder.() -> Unit = {},
|
|
||||||
name: String? = null,
|
name: String? = null,
|
||||||
|
descriptorBuilder: ActionDescriptorBuilder.() -> Unit = {},
|
||||||
execute: suspend D.(Meta) -> Meta,
|
execute: suspend D.(Meta) -> Meta,
|
||||||
): PropertyDelegateProvider<CompositeControlComponentSpec<D>, ReadOnlyProperty<CompositeControlComponentSpec<D>, DeviceActionSpec<D, Meta, Meta>>> =
|
): PropertyDelegateProvider<CompositeControlComponentSpec<D>, ReadOnlyProperty<CompositeControlComponentSpec<D>, DeviceActionSpec<D, Meta, Meta>>> =
|
||||||
action(
|
typedAction(MetaConverter.meta, MetaConverter.meta, name, descriptorBuilder, execute)
|
||||||
MetaConverter.meta,
|
|
||||||
MetaConverter.meta,
|
|
||||||
descriptorBuilder,
|
|
||||||
name
|
|
||||||
) {
|
|
||||||
execute(it)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Throw an exception if device does not have all properties and actions defined by this specification
|
* Validates that [device] has all properties and actions defined by this spec.
|
||||||
*/
|
*/
|
||||||
public fun CompositeControlComponentSpec<*>.validate(device: Device) {
|
public fun CompositeControlComponentSpec<*>.validateSpec(device: Device) {
|
||||||
properties.map { it.value.descriptor }.forEach { specProperty ->
|
properties.values.forEach { propSpec ->
|
||||||
check(specProperty in device.propertyDescriptors) { "Property ${specProperty.name} not registered in ${device.id}" }
|
check(propSpec.descriptor in device.propertyDescriptors) {
|
||||||
}
|
"Property ${propSpec.descriptor.name} not registered in ${device.id}"
|
||||||
|
}
|
||||||
actions.map { it.value.descriptor }.forEach { specAction ->
|
}
|
||||||
check(specAction in device.actionDescriptors) { "Action ${specAction.name} not registered in ${device.id}" }
|
actions.values.forEach { actSpec ->
|
||||||
|
check(actSpec.descriptor in device.actionDescriptors) {
|
||||||
|
"Action ${actSpec.descriptor.name} not registered in ${device.id}"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -18,98 +18,92 @@ class CompositeControlTest {
|
|||||||
// ---------------------- Device Specifications ----------------------------------
|
// ---------------------- Device Specifications ----------------------------------
|
||||||
|
|
||||||
public object StepperMotorSpec : CompositeControlComponentSpec<StepperMotorDevice>() {
|
public object StepperMotorSpec : CompositeControlComponentSpec<StepperMotorDevice>() {
|
||||||
public val position by intMutable(
|
public val position by intProperty(
|
||||||
name = "position",
|
name = "position",
|
||||||
read = { getPosition() },
|
read = { getPosition() },
|
||||||
write = { _, value -> setPosition(value) }
|
write = { _, value -> setPosition(value) }
|
||||||
)
|
)
|
||||||
|
|
||||||
public val maxPosition by int(
|
public val maxPosition by intProperty(
|
||||||
name = "maxPosition",
|
name = "maxPosition",
|
||||||
read = { maxPosition }
|
read = { maxPosition }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
public object ValveSpec : CompositeControlComponentSpec<ValveDevice>() {
|
public object ValveSpec : CompositeControlComponentSpec<ValveDevice>() {
|
||||||
public val state by booleanMutable(
|
public val state by booleanProperty(
|
||||||
read = { getState() },
|
read = { getState() },
|
||||||
write = { _, value -> setState(value) }
|
write = { _, value -> setState(value) }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
public object PressureChamberSpec : CompositeControlComponentSpec<PressureChamberDevice>() {
|
public object PressureChamberSpec : CompositeControlComponentSpec<PressureChamberDevice>() {
|
||||||
public val pressure by doubleMutable(
|
public val pressure by doubleProperty(
|
||||||
read = { getPressure() },
|
read = { getPressure() },
|
||||||
write = { _, value -> setPressure(value) }
|
write = { _, value -> setPressure(value) }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
public object SyringePumpSpec : CompositeControlComponentSpec<SyringePumpDevice>() {
|
public object SyringePumpSpec : CompositeControlComponentSpec<SyringePumpDevice>() {
|
||||||
public val volume by doubleMutable(
|
public val volume by doubleProperty(
|
||||||
read = { getVolume() },
|
read = { getVolume() },
|
||||||
write = { _, value -> setVolume(value) }
|
write = { _, value -> setVolume(value) }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
public object ReagentSensorSpec : CompositeControlComponentSpec<ReagentSensorDevice>() {
|
public object ReagentSensorSpec : CompositeControlComponentSpec<ReagentSensorDevice>() {
|
||||||
public val isPresent by boolean(
|
public val isPresent by booleanProperty(
|
||||||
read = { checkReagent() }
|
read = { checkReagent() }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
public object NeedleSpec : CompositeControlComponentSpec<NeedleDevice>() {
|
public object NeedleSpec : CompositeControlComponentSpec<NeedleDevice>() {
|
||||||
public val mode by enumMutable(
|
public val mode by enumProperty<NeedleDevice.Mode, NeedleDevice>(
|
||||||
enumValues = NeedleDevice.Mode.entries.toTypedArray(),
|
|
||||||
read = { getMode() },
|
read = { getMode() },
|
||||||
write = { _, value -> setMode(value) }
|
write = { _, value -> setMode(value) }
|
||||||
)
|
)
|
||||||
|
|
||||||
public val position by doubleMutable(
|
public val position by doubleProperty(
|
||||||
read = { getPosition() },
|
read = { getPosition() },
|
||||||
write = { _, value -> setPosition(value) }
|
write = { _, value -> setPosition(value) }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
public object ShakerSpec : CompositeControlComponentSpec<ShakerDevice>() {
|
public object ShakerSpec : CompositeControlComponentSpec<ShakerDevice>() {
|
||||||
public val verticalMotor by childSpec<StepperMotorSpec, StepperMotorDevice>()
|
public val verticalMotor by childSpec<StepperMotorSpec, StepperMotorDevice>(StepperMotorSpec)
|
||||||
public val horizontalMotor by childSpec<StepperMotorSpec, StepperMotorDevice>()
|
public val horizontalMotor by childSpec<StepperMotorSpec, StepperMotorDevice>(StepperMotorSpec)
|
||||||
}
|
}
|
||||||
|
|
||||||
public object TransportationSystemSpec : CompositeControlComponentSpec<TransportationSystem>() {
|
public object TransportationSystemSpec : CompositeControlComponentSpec<TransportationSystem>() {
|
||||||
public val slideMotor by childSpec<StepperMotorSpec, StepperMotorDevice>()
|
public val slideMotor by childSpec<StepperMotorSpec, StepperMotorDevice>(StepperMotorSpec)
|
||||||
|
public val pushMotor by childSpec<StepperMotorSpec, StepperMotorDevice>(StepperMotorSpec)
|
||||||
public val pushMotor by childSpec<StepperMotorSpec, StepperMotorDevice>()
|
public val receiveMotor by childSpec<StepperMotorSpec, StepperMotorDevice>(StepperMotorSpec)
|
||||||
|
|
||||||
public val receiveMotor by childSpec<StepperMotorSpec, StepperMotorDevice>()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public object AnalyzerSpec : CompositeControlComponentSpec<AnalyzerDevice>() {
|
public object AnalyzerSpec : CompositeControlComponentSpec<AnalyzerDevice>() {
|
||||||
public val transportationSystem by childSpec<TransportationSystemSpec, TransportationSystemSpec>()
|
public val transportationSystem by childSpec<TransportationSystemSpec, TransportationSystem>(TransportationSystemSpec)
|
||||||
public val shakerDevice by childSpec<ShakerSpec, ShakerDevice>()
|
public val shakerDevice by childSpec<ShakerSpec, ShakerDevice>(ShakerSpec)
|
||||||
public val needleDevice by childSpec<NeedleSpec, NeedleDevice>()
|
public val needleDevice by childSpec<NeedleSpec, NeedleDevice>(NeedleSpec)
|
||||||
|
|
||||||
|
public val valveV20 by childSpec<ValveSpec, ValveDevice>(ValveSpec)
|
||||||
|
public val valveV17 by childSpec<ValveSpec, ValveDevice>(ValveSpec)
|
||||||
|
public val valveV18 by childSpec<ValveSpec, ValveDevice>(ValveSpec)
|
||||||
|
public val valveV35 by childSpec<ValveSpec, ValveDevice>(ValveSpec)
|
||||||
|
|
||||||
public val valveV20 by childSpec<ValveSpec, ValveDevice>()
|
public val pressureChamberHigh by childSpec<PressureChamberSpec, PressureChamberDevice>(PressureChamberSpec)
|
||||||
public val valveV17 by childSpec<ValveSpec, ValveDevice>()
|
public val pressureChamberLow by childSpec<PressureChamberSpec, PressureChamberDevice>(PressureChamberSpec)
|
||||||
public val valveV18 by childSpec<ValveSpec, ValveDevice>()
|
|
||||||
public val valveV35 by childSpec<ValveSpec, ValveDevice>()
|
|
||||||
|
|
||||||
|
public val syringePumpMA100 by childSpec<SyringePumpSpec, SyringePumpDevice>(SyringePumpSpec)
|
||||||
|
public val syringePumpMA25 by childSpec<SyringePumpSpec, SyringePumpDevice>(SyringePumpSpec)
|
||||||
|
|
||||||
public val pressureChamberHigh by childSpec<PressureChamberSpec, PressureChamberDevice>()
|
public val reagentSensor1 by childSpec<ReagentSensorSpec, ReagentSensorDevice>(ReagentSensorSpec)
|
||||||
public val pressureChamberLow by childSpec<PressureChamberSpec, PressureChamberDevice>()
|
public val reagentSensor2 by childSpec<ReagentSensorSpec, ReagentSensorDevice>(ReagentSensorSpec)
|
||||||
|
public val reagentSensor3 by childSpec<ReagentSensorSpec, ReagentSensorDevice>(ReagentSensorSpec)
|
||||||
public val syringePumpMA100 by childSpec<SyringePumpSpec, SyringePumpDevice>()
|
|
||||||
public val syringePumpMA25 by childSpec<SyringePumpSpec, SyringePumpDevice>()
|
|
||||||
|
|
||||||
public val reagentSensor1 by childSpec<ReagentSensorSpec, ReagentSensorDevice>()
|
|
||||||
public val reagentSensor2 by childSpec<ReagentSensorSpec, ReagentSensorDevice>()
|
|
||||||
public val reagentSensor3 by childSpec<ReagentSensorSpec, ReagentSensorDevice>()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------- Device Implementations ----------------------------------
|
// ---------------------- Device Implementations ----------------------------------
|
||||||
|
|
||||||
// Implementation of Stepper Motor Device
|
|
||||||
public class StepperMotorDevice(
|
public class StepperMotorDevice(
|
||||||
context: Context,
|
context: Context,
|
||||||
meta: Meta = Meta.EMPTY
|
meta: Meta = Meta.EMPTY
|
||||||
@ -774,6 +768,9 @@ class CompositeControlTest {
|
|||||||
val context = createTestContext()
|
val context = createTestContext()
|
||||||
val shaker = ShakerDevice(context)
|
val shaker = ShakerDevice(context)
|
||||||
|
|
||||||
|
shaker.initChildren()
|
||||||
|
shaker.start()// Start the device
|
||||||
|
|
||||||
// Access properties to initialize motors and test shaking
|
// Access properties to initialize motors and test shaking
|
||||||
val verticalMotor = shaker.verticalMotor
|
val verticalMotor = shaker.verticalMotor
|
||||||
val horizontalMotor = shaker.horizontalMotor
|
val horizontalMotor = shaker.horizontalMotor
|
||||||
@ -791,19 +788,23 @@ class CompositeControlTest {
|
|||||||
val context = createTestContext()
|
val context = createTestContext()
|
||||||
val transportationSystem = TransportationSystem(context)
|
val transportationSystem = TransportationSystem(context)
|
||||||
|
|
||||||
|
transportationSystem.initChildren()
|
||||||
|
transportationSystem.start()// Start the device
|
||||||
|
|
||||||
// Access properties to initialize motors and test existence
|
// Access properties to initialize motors and test existence
|
||||||
assertNotNull(transportationSystem.slideMotor, "slideMotor should exist")
|
assertNotNull(transportationSystem.slideMotor, "slideMotor should exist")
|
||||||
assertNotNull(transportationSystem.pushMotor, "pushMotor should exist")
|
assertNotNull(transportationSystem.pushMotor, "pushMotor should exist")
|
||||||
assertNotNull(transportationSystem.receiveMotor, "receiveMotor should exist")
|
assertNotNull(transportationSystem.receiveMotor, "receiveMotor should exist")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `test AnalyzerDevice device access`() = runTest {
|
fun `test AnalyzerDevice device access`() = runTest {
|
||||||
val context = createTestContext()
|
val context = createTestContext()
|
||||||
val analyzer = AnalyzerDevice(context)
|
val analyzer = AnalyzerDevice(context)
|
||||||
|
analyzer.initChildren()
|
||||||
|
analyzer.start()// Start the device
|
||||||
|
|
||||||
// Access properties to initialize child devices and test existence
|
// Access properties to initialize child devices
|
||||||
assertNotNull(analyzer.transportationSystem, "Transportation system should exist")
|
assertNotNull(analyzer.transportationSystem, "Transportation system should exist")
|
||||||
assertNotNull(analyzer.shakerDevice, "Shaker device should exist")
|
assertNotNull(analyzer.shakerDevice, "Shaker device should exist")
|
||||||
assertNotNull(analyzer.needleDevice, "Needle device should exist")
|
assertNotNull(analyzer.needleDevice, "Needle device should exist")
|
||||||
|
Loading…
Reference in New Issue
Block a user