Add read-after-write for DeviceBase property writers

This commit is contained in:
Alexander Nozik 2023-09-24 13:21:01 +03:00
parent a51510606f
commit a337daee93
4 changed files with 23 additions and 18 deletions

View File

@ -87,7 +87,7 @@ public abstract class DeviceBase<D : Device>(
/** /**
* Update logical property state and notify listeners * Update logical property state and notify listeners
*/ */
protected suspend fun updateLogical(propertyName: String, value: Meta?) { protected suspend fun propertyChanged(propertyName: String, value: Meta?) {
if (value != logicalState[propertyName]) { if (value != logicalState[propertyName]) {
stateLock.withLock { stateLock.withLock {
logicalState[propertyName] = value logicalState[propertyName] = value
@ -99,10 +99,10 @@ public abstract class DeviceBase<D : Device>(
} }
/** /**
* Update logical state using given [spec] and its convertor * Notify the device that a property with [spec] value is changed
*/ */
public suspend fun <T> updateLogical(spec: DevicePropertySpec<D, T>, value: T) { protected suspend fun <T> propertyChanged(spec: DevicePropertySpec<D, T>, value: T) {
updateLogical(spec.name, spec.converter.objectToMeta(value)) propertyChanged(spec.name, spec.converter.objectToMeta(value))
} }
/** /**
@ -112,7 +112,7 @@ public abstract class DeviceBase<D : Device>(
override suspend fun readProperty(propertyName: String): Meta { override suspend fun readProperty(propertyName: String): Meta {
val spec = properties[propertyName] ?: error("Property with name $propertyName not found") val spec = properties[propertyName] ?: error("Property with name $propertyName not found")
val meta = spec.readMeta(self) ?: error("Failed to read property $propertyName") val meta = spec.readMeta(self) ?: error("Failed to read property $propertyName")
updateLogical(propertyName, meta) propertyChanged(propertyName, meta)
return meta return meta
} }
@ -122,7 +122,7 @@ public abstract class DeviceBase<D : Device>(
public suspend fun readPropertyOrNull(propertyName: String): Meta? { public suspend fun readPropertyOrNull(propertyName: String): Meta? {
val spec = properties[propertyName] ?: return null val spec = properties[propertyName] ?: return null
val meta = spec.readMeta(self) ?: return null val meta = spec.readMeta(self) ?: return null
updateLogical(propertyName, meta) propertyChanged(propertyName, meta)
return meta return meta
} }
@ -137,13 +137,18 @@ public abstract class DeviceBase<D : Device>(
override suspend fun writeProperty(propertyName: String, value: Meta): Unit { override suspend fun writeProperty(propertyName: String, value: Meta): Unit {
when (val property = properties[propertyName]) { when (val property = properties[propertyName]) {
null -> { null -> {
//If there is a physical property with a given name, invalidate logical property and write physical one //If there are no physical properties with given name, write a logical one.
updateLogical(propertyName, value) propertyChanged(propertyName, value)
} }
is WritableDevicePropertySpec -> { is WritableDevicePropertySpec -> {
//if there is a writeable property with a given name, invalidate logical and write physical
invalidate(propertyName) invalidate(propertyName)
property.writeMeta(self, value) property.writeMeta(self, value)
// perform read after writing if the writer did not set the value
if (logicalState[propertyName] == null) {
readPropertyOrNull(propertyName)
}
} }
else -> { else -> {

View File

@ -22,7 +22,7 @@ public val MetaConverter.Companion.unit: MetaConverter<Unit> get() = UnitMetaCon
@OptIn(InternalDeviceAPI::class) @OptIn(InternalDeviceAPI::class)
public abstract class DeviceSpec<D : Device> { public abstract class DeviceSpec<D : Device> {
//initializing meta property for everyone //initializing the metadata property for everyone
private val _properties = hashMapOf<String, DevicePropertySpec<D, *>>( private val _properties = hashMapOf<String, DevicePropertySpec<D, *>>(
DeviceMetaPropertySpec.name to DeviceMetaPropertySpec DeviceMetaPropertySpec.name to DeviceMetaPropertySpec
) )

View File

@ -49,16 +49,16 @@ class MksPdr900Device(context: Context, meta: Meta) : DeviceBySpec<MksPdr900Devi
if (powerOnValue) { if (powerOnValue) {
val ans = talk("FP!ON") val ans = talk("FP!ON")
if (ans == "ON") { if (ans == "ON") {
updateLogical(powerOn, true) propertyChanged(powerOn, true)
} else { } else {
updateLogical(error, "Failed to set power state") propertyChanged(error, "Failed to set power state")
} }
} else { } else {
val ans = talk("FP!OFF") val ans = talk("FP!OFF")
if (ans == "OFF") { if (ans == "OFF") {
updateLogical(powerOn, false) propertyChanged(powerOn, false)
} else { } else {
updateLogical(error, "Failed to set power state") propertyChanged(error, "Failed to set power state")
} }
} }
} }
@ -68,13 +68,13 @@ class MksPdr900Device(context: Context, meta: Meta) : DeviceBySpec<MksPdr900Devi
invalidate(error) invalidate(error)
return if (answer.isNullOrEmpty()) { return if (answer.isNullOrEmpty()) {
// updateState(PortSensor.CONNECTED_STATE, false) // updateState(PortSensor.CONNECTED_STATE, false)
updateLogical(error, "No connection") propertyChanged(error, "No connection")
null null
} else { } else {
val res = answer.toDouble() val res = answer.toDouble()
if (res <= 0) { if (res <= 0) {
updateLogical(powerOn, false) propertyChanged(powerOn, false)
updateLogical(error, "No power") propertyChanged(error, "No power")
null null
} else { } else {
res res

View File

@ -172,7 +172,7 @@ class PiMotionMasterDevice(
//Update port //Update port
//address = portSpec.node //address = portSpec.node
port = portFactory(portSpec, context) port = portFactory(portSpec, context)
updateLogical(connected, true) propertyChanged(connected, true)
// connector.open() // connector.open()
//Initialize axes //Initialize axes
val idn = read(identity) val idn = read(identity)
@ -196,7 +196,7 @@ class PiMotionMasterDevice(
it.close() it.close()
} }
port = null port = null
updateLogical(connected, false) propertyChanged(connected, false)
} }