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
|
* Subscribe on property changes for the whole device
|
||||||
*/
|
*/
|
||||||
public fun Device.onPropertyChange(callback: suspend PropertyChangedMessage.() -> Unit): Job =
|
public fun Device.onPropertyChange(scope: CoroutineScope = this, callback: suspend PropertyChangedMessage.() -> Unit): Job =
|
||||||
messageFlow.filterIsInstance<PropertyChangedMessage>().onEach(callback).launchIn(this)
|
messageFlow.filterIsInstance<PropertyChangedMessage>().onEach(callback).launchIn(scope)
|
||||||
|
@ -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 -> {
|
||||||
|
@ -115,6 +115,7 @@ public fun <D : Device, T> D.propertyFlow(spec: DevicePropertySpec<D, T>): Flow<
|
|||||||
*/
|
*/
|
||||||
public fun <D : Device, T> D.onPropertyChange(
|
public fun <D : Device, T> D.onPropertyChange(
|
||||||
spec: DevicePropertySpec<D, T>,
|
spec: DevicePropertySpec<D, T>,
|
||||||
|
scope: CoroutineScope = this,
|
||||||
callback: suspend PropertyChangedMessage.(T) -> Unit,
|
callback: suspend PropertyChangedMessage.(T) -> Unit,
|
||||||
): Job = messageFlow
|
): Job = messageFlow
|
||||||
.filterIsInstance<PropertyChangedMessage>()
|
.filterIsInstance<PropertyChangedMessage>()
|
||||||
@ -124,15 +125,16 @@ public fun <D : Device, T> D.onPropertyChange(
|
|||||||
if (newValue != null) {
|
if (newValue != null) {
|
||||||
change.callback(newValue)
|
change.callback(newValue)
|
||||||
}
|
}
|
||||||
}.launchIn(this)
|
}.launchIn(scope)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Call [callback] on initial property value and each value change
|
* Call [callback] on initial property value and each value change
|
||||||
*/
|
*/
|
||||||
public fun <D : Device, T> D.useProperty(
|
public fun <D : Device, T> D.useProperty(
|
||||||
spec: DevicePropertySpec<D, T>,
|
spec: DevicePropertySpec<D, T>,
|
||||||
|
scope: CoroutineScope = this,
|
||||||
callback: suspend (T) -> Unit,
|
callback: suspend (T) -> Unit,
|
||||||
): Job = launch {
|
): Job = scope.launch {
|
||||||
callback(read(spec))
|
callback(read(spec))
|
||||||
messageFlow
|
messageFlow
|
||||||
.filterIsInstance<PropertyChangedMessage>()
|
.filterIsInstance<PropertyChangedMessage>()
|
||||||
|
@ -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
|
||||||
)
|
)
|
||||||
|
@ -183,10 +183,6 @@ public fun ModbusDevice.writeHoldingRegisters(address: Int, buffer: ByteBuffer):
|
|||||||
return writeHoldingRegisters(address, array)
|
return writeHoldingRegisters(address, array)
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun ModbusDevice.writeShortRegister(address: Int, value: Short) {
|
|
||||||
master.writeSingleRegister(address, SimpleInputRegister(value.toInt()))
|
|
||||||
}
|
|
||||||
|
|
||||||
public fun ModbusDevice.modbusRegister(
|
public fun ModbusDevice.modbusRegister(
|
||||||
address: Int,
|
address: Int,
|
||||||
): ReadWriteProperty<ModbusDevice, Short> = object : ReadWriteProperty<ModbusDevice, Short> {
|
): ReadWriteProperty<ModbusDevice, Short> = object : ReadWriteProperty<ModbusDevice, Short> {
|
||||||
|
@ -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
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user