Compare commits
2 Commits
8b6a6abd92
...
a337daee93
Author | SHA1 | Date | |
---|---|---|---|
a337daee93 | |||
a51510606f |
@ -124,5 +124,5 @@ public fun Device.getAllProperties(): Meta = Meta {
|
||||
/**
|
||||
* Subscribe on property changes for the whole device
|
||||
*/
|
||||
public fun Device.onPropertyChange(callback: suspend PropertyChangedMessage.() -> Unit): Job =
|
||||
messageFlow.filterIsInstance<PropertyChangedMessage>().onEach(callback).launchIn(this)
|
||||
public fun Device.onPropertyChange(scope: CoroutineScope = this, callback: suspend PropertyChangedMessage.() -> Unit): Job =
|
||||
messageFlow.filterIsInstance<PropertyChangedMessage>().onEach(callback).launchIn(scope)
|
||||
|
@ -87,7 +87,7 @@ public abstract class DeviceBase<D : Device>(
|
||||
/**
|
||||
* 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]) {
|
||||
stateLock.withLock {
|
||||
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) {
|
||||
updateLogical(spec.name, spec.converter.objectToMeta(value))
|
||||
protected suspend fun <T> propertyChanged(spec: DevicePropertySpec<D, T>, value: T) {
|
||||
propertyChanged(spec.name, spec.converter.objectToMeta(value))
|
||||
}
|
||||
|
||||
/**
|
||||
@ -112,7 +112,7 @@ public abstract class DeviceBase<D : Device>(
|
||||
override suspend fun readProperty(propertyName: String): Meta {
|
||||
val spec = properties[propertyName] ?: error("Property with name $propertyName not found")
|
||||
val meta = spec.readMeta(self) ?: error("Failed to read property $propertyName")
|
||||
updateLogical(propertyName, meta)
|
||||
propertyChanged(propertyName, meta)
|
||||
return meta
|
||||
}
|
||||
|
||||
@ -122,7 +122,7 @@ public abstract class DeviceBase<D : Device>(
|
||||
public suspend fun readPropertyOrNull(propertyName: String): Meta? {
|
||||
val spec = properties[propertyName] ?: return null
|
||||
val meta = spec.readMeta(self) ?: return null
|
||||
updateLogical(propertyName, meta)
|
||||
propertyChanged(propertyName, meta)
|
||||
return meta
|
||||
}
|
||||
|
||||
@ -137,13 +137,18 @@ public abstract class DeviceBase<D : Device>(
|
||||
override suspend fun writeProperty(propertyName: String, value: Meta): Unit {
|
||||
when (val property = properties[propertyName]) {
|
||||
null -> {
|
||||
//If there is a physical property with a given name, invalidate logical property and write physical one
|
||||
updateLogical(propertyName, value)
|
||||
//If there are no physical properties with given name, write a logical one.
|
||||
propertyChanged(propertyName, value)
|
||||
}
|
||||
|
||||
is WritableDevicePropertySpec -> {
|
||||
//if there is a writeable property with a given name, invalidate logical and write physical
|
||||
invalidate(propertyName)
|
||||
property.writeMeta(self, value)
|
||||
// perform read after writing if the writer did not set the value
|
||||
if (logicalState[propertyName] == null) {
|
||||
readPropertyOrNull(propertyName)
|
||||
}
|
||||
}
|
||||
|
||||
else -> {
|
||||
|
@ -115,6 +115,7 @@ public fun <D : Device, T> D.propertyFlow(spec: DevicePropertySpec<D, T>): Flow<
|
||||
*/
|
||||
public fun <D : Device, T> D.onPropertyChange(
|
||||
spec: DevicePropertySpec<D, T>,
|
||||
scope: CoroutineScope = this,
|
||||
callback: suspend PropertyChangedMessage.(T) -> Unit,
|
||||
): Job = messageFlow
|
||||
.filterIsInstance<PropertyChangedMessage>()
|
||||
@ -124,15 +125,16 @@ public fun <D : Device, T> D.onPropertyChange(
|
||||
if (newValue != null) {
|
||||
change.callback(newValue)
|
||||
}
|
||||
}.launchIn(this)
|
||||
}.launchIn(scope)
|
||||
|
||||
/**
|
||||
* Call [callback] on initial property value and each value change
|
||||
*/
|
||||
public fun <D : Device, T> D.useProperty(
|
||||
spec: DevicePropertySpec<D, T>,
|
||||
scope: CoroutineScope = this,
|
||||
callback: suspend (T) -> Unit,
|
||||
): Job = launch {
|
||||
): Job = scope.launch {
|
||||
callback(read(spec))
|
||||
messageFlow
|
||||
.filterIsInstance<PropertyChangedMessage>()
|
||||
|
@ -22,7 +22,7 @@ public val MetaConverter.Companion.unit: MetaConverter<Unit> get() = UnitMetaCon
|
||||
|
||||
@OptIn(InternalDeviceAPI::class)
|
||||
public abstract class DeviceSpec<D : Device> {
|
||||
//initializing meta property for everyone
|
||||
//initializing the metadata property for everyone
|
||||
private val _properties = hashMapOf<String, DevicePropertySpec<D, *>>(
|
||||
DeviceMetaPropertySpec.name to DeviceMetaPropertySpec
|
||||
)
|
||||
|
@ -183,10 +183,6 @@ public fun ModbusDevice.writeHoldingRegisters(address: Int, buffer: ByteBuffer):
|
||||
return writeHoldingRegisters(address, array)
|
||||
}
|
||||
|
||||
public fun ModbusDevice.writeShortRegister(address: Int, value: Short) {
|
||||
master.writeSingleRegister(address, SimpleInputRegister(value.toInt()))
|
||||
}
|
||||
|
||||
public fun ModbusDevice.modbusRegister(
|
||||
address: Int,
|
||||
): ReadWriteProperty<ModbusDevice, Short> = object : ReadWriteProperty<ModbusDevice, Short> {
|
||||
|
@ -49,16 +49,16 @@ class MksPdr900Device(context: Context, meta: Meta) : DeviceBySpec<MksPdr900Devi
|
||||
if (powerOnValue) {
|
||||
val ans = talk("FP!ON")
|
||||
if (ans == "ON") {
|
||||
updateLogical(powerOn, true)
|
||||
propertyChanged(powerOn, true)
|
||||
} else {
|
||||
updateLogical(error, "Failed to set power state")
|
||||
propertyChanged(error, "Failed to set power state")
|
||||
}
|
||||
} else {
|
||||
val ans = talk("FP!OFF")
|
||||
if (ans == "OFF") {
|
||||
updateLogical(powerOn, false)
|
||||
propertyChanged(powerOn, false)
|
||||
} 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)
|
||||
return if (answer.isNullOrEmpty()) {
|
||||
// updateState(PortSensor.CONNECTED_STATE, false)
|
||||
updateLogical(error, "No connection")
|
||||
propertyChanged(error, "No connection")
|
||||
null
|
||||
} else {
|
||||
val res = answer.toDouble()
|
||||
if (res <= 0) {
|
||||
updateLogical(powerOn, false)
|
||||
updateLogical(error, "No power")
|
||||
propertyChanged(powerOn, false)
|
||||
propertyChanged(error, "No power")
|
||||
null
|
||||
} else {
|
||||
res
|
||||
|
@ -172,7 +172,7 @@ class PiMotionMasterDevice(
|
||||
//Update port
|
||||
//address = portSpec.node
|
||||
port = portFactory(portSpec, context)
|
||||
updateLogical(connected, true)
|
||||
propertyChanged(connected, true)
|
||||
// connector.open()
|
||||
//Initialize axes
|
||||
val idn = read(identity)
|
||||
@ -196,7 +196,7 @@ class PiMotionMasterDevice(
|
||||
it.close()
|
||||
}
|
||||
port = null
|
||||
updateLogical(connected, false)
|
||||
propertyChanged(connected, false)
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user