hub returns list of messages.
This commit is contained in:
parent
34f9108ef7
commit
aa52b4b927
@ -10,6 +10,7 @@
|
||||
### Changed
|
||||
- Property caching moved from core `Device` to the `CachingDevice`
|
||||
- `DeviceSpec` properties no explicitly pass property name to getters and setters.
|
||||
- `DeviceHub.respondHubMessage` now returns a list of messages to allow querying multiple devices. Device server also returns an array.
|
||||
|
||||
### Deprecated
|
||||
|
||||
|
@ -14,8 +14,10 @@ public interface DeviceHub : Provider {
|
||||
|
||||
override val defaultChainTarget: String get() = Device.DEVICE_TARGET
|
||||
|
||||
override fun content(target: String): Map<Name, Any> = if (target == Device.DEVICE_TARGET) {
|
||||
buildMap {
|
||||
/**
|
||||
* List all devices, including sub-devices
|
||||
*/
|
||||
public fun buildDeviceTree(): Map<Name, Device> = buildMap {
|
||||
fun putAll(prefix: Name, hub: DeviceHub) {
|
||||
hub.devices.forEach {
|
||||
put(prefix + it.key, it.value)
|
||||
@ -30,6 +32,9 @@ public interface DeviceHub : Provider {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun content(target: String): Map<Name, Any> = if (target == Device.DEVICE_TARGET) {
|
||||
buildDeviceTree()
|
||||
} else {
|
||||
emptyMap()
|
||||
}
|
||||
@ -37,6 +42,7 @@ public interface DeviceHub : Provider {
|
||||
public companion object
|
||||
}
|
||||
|
||||
|
||||
public operator fun DeviceHub.get(nameToken: NameToken): Device =
|
||||
devices[nameToken] ?: error("Device with name $nameToken not found in $this")
|
||||
|
||||
|
@ -103,7 +103,7 @@ public data class PropertyGetMessage(
|
||||
@SerialName("description.get")
|
||||
public data class GetDescriptionMessage(
|
||||
override val sourceDevice: Name? = null,
|
||||
override val targetDevice: Name,
|
||||
override val targetDevice: Name? = null,
|
||||
override val comment: String? = null,
|
||||
@EncodeDefault override val time: Instant? = Clock.System.now(),
|
||||
) : DeviceMessage() {
|
||||
|
@ -68,15 +68,22 @@ public suspend fun Device.respondMessage(deviceTarget: Name, request: DeviceMess
|
||||
}
|
||||
|
||||
/**
|
||||
* Process incoming [DeviceMessage], using hub naming to evaluate target.
|
||||
* Process incoming [DeviceMessage], using hub naming to find target.
|
||||
* If the `targetDevice` is `null`, then message is sent to each device in this hub
|
||||
*/
|
||||
public suspend fun DeviceHub.respondHubMessage(request: DeviceMessage): DeviceMessage? {
|
||||
public suspend fun DeviceHub.respondHubMessage(request: DeviceMessage): List<DeviceMessage> {
|
||||
return try {
|
||||
val targetName = request.targetDevice ?: return null
|
||||
val targetName = request.targetDevice
|
||||
if(targetName == null) {
|
||||
buildDeviceTree().mapNotNull {
|
||||
it.value.respondMessage(it.key, request)
|
||||
}
|
||||
} else {
|
||||
val device = getOrNull(targetName) ?: error("The device with name $targetName not found in $this")
|
||||
device.respondMessage(targetName, request)
|
||||
listOfNotNull(device.respondMessage(targetName, request))
|
||||
}
|
||||
} catch (ex: Exception) {
|
||||
DeviceMessage.error(ex, sourceDevice = Name.EMPTY, targetDevice = request.sourceDevice)
|
||||
listOf(DeviceMessage.error(ex, sourceDevice = Name.EMPTY, targetDevice = request.sourceDevice))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -39,10 +39,10 @@ public fun DeviceManager.launchMagixService(
|
||||
): Job = context.launch {
|
||||
endpoint.subscribe(controlsMagixFormat, targetFilter = listOf(endpointID)).onEach { (request, payload) ->
|
||||
val responsePayload = respondHubMessage(payload)
|
||||
if (responsePayload != null) {
|
||||
responsePayload.forEach {
|
||||
endpoint.send(
|
||||
format = controlsMagixFormat,
|
||||
payload = responsePayload,
|
||||
payload = it,
|
||||
source = endpointID,
|
||||
target = request.sourceEndpoint,
|
||||
id = generateId(request),
|
||||
|
@ -157,8 +157,8 @@ public fun Application.deviceManagerModule(
|
||||
val body = call.receiveText()
|
||||
val request: DeviceMessage = MagixEndpoint.magixJson.decodeFromString(DeviceMessage.serializer(), body)
|
||||
val response = manager.respondHubMessage(request)
|
||||
if (response != null) {
|
||||
call.respondMessage(response)
|
||||
if (response.isNotEmpty()) {
|
||||
call.respondMessages(response)
|
||||
} else {
|
||||
call.respondText("No response")
|
||||
}
|
||||
@ -177,9 +177,9 @@ public fun Application.deviceManagerModule(
|
||||
property = property,
|
||||
)
|
||||
|
||||
val response = manager.respondHubMessage(request)
|
||||
if (response != null) {
|
||||
call.respondMessage(response)
|
||||
val responses = manager.respondHubMessage(request)
|
||||
if (responses.isNotEmpty()) {
|
||||
call.respondMessages(responses)
|
||||
} else {
|
||||
call.respond(HttpStatusCode.InternalServerError)
|
||||
}
|
||||
@ -197,9 +197,9 @@ public fun Application.deviceManagerModule(
|
||||
value = json.toMeta()
|
||||
)
|
||||
|
||||
val response = manager.respondHubMessage(request)
|
||||
if (response != null) {
|
||||
call.respondMessage(response)
|
||||
val responses = manager.respondHubMessage(request)
|
||||
if (responses.isNotEmpty()) {
|
||||
call.respondMessages(responses)
|
||||
} else {
|
||||
call.respond(HttpStatusCode.InternalServerError)
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import io.ktor.server.application.ApplicationCall
|
||||
import io.ktor.server.response.respondText
|
||||
import kotlinx.serialization.json.JsonObjectBuilder
|
||||
import kotlinx.serialization.json.buildJsonObject
|
||||
import kotlinx.serialization.serializer
|
||||
import space.kscience.controls.api.DeviceMessage
|
||||
import space.kscience.magix.api.MagixEndpoint
|
||||
|
||||
@ -25,7 +26,7 @@ internal suspend fun ApplicationCall.respondJson(builder: JsonObjectBuilder.() -
|
||||
respondText(json.toString(), contentType = ContentType.Application.Json)
|
||||
}
|
||||
|
||||
internal suspend fun ApplicationCall.respondMessage(message: DeviceMessage): Unit = respondText(
|
||||
MagixEndpoint.magixJson.encodeToString(DeviceMessage.serializer(), message),
|
||||
internal suspend fun ApplicationCall.respondMessages(messages: List<DeviceMessage>): Unit = respondText(
|
||||
MagixEndpoint.magixJson.encodeToString(serializer<List<DeviceMessage>>(), messages),
|
||||
contentType = ContentType.Application.Json
|
||||
)
|
@ -24,7 +24,7 @@ dependencies {
|
||||
|
||||
implementation("io.ktor:ktor-client-cio:$ktorVersion")
|
||||
implementation("no.tornado:tornadofx:1.7.20")
|
||||
implementation("space.kscience:plotlykt-server:0.6.0")
|
||||
implementation("space.kscience:plotlykt-server:0.6.1")
|
||||
// implementation("com.github.Ricky12Awesome:json-schema-serialization:0.6.6")
|
||||
implementation(spclibs.logback.classic)
|
||||
}
|
||||
|
@ -47,7 +47,12 @@ class DemoDevice(context: Context, meta: Meta) : DeviceBySpec<IDemoDevice>(Compa
|
||||
description = "Real to virtual time scale"
|
||||
}
|
||||
|
||||
val sinScale by mutableProperty(MetaConverter.double, IDemoDevice::sinScaleState)
|
||||
val sinScale by mutableProperty(MetaConverter.double, IDemoDevice::sinScaleState){
|
||||
description = "The scale of sin plot"
|
||||
metaDescriptor {
|
||||
valueType(ValueType.NUMBER)
|
||||
}
|
||||
}
|
||||
val cosScale by mutableProperty(MetaConverter.double, IDemoDevice::cosScaleState)
|
||||
|
||||
val sin by doubleProperty { sinValue() }
|
||||
@ -74,6 +79,10 @@ class DemoDevice(context: Context, meta: Meta) : DeviceBySpec<IDemoDevice>(Compa
|
||||
write(cosScale, 1.0)
|
||||
}
|
||||
|
||||
val setSinScale by action(MetaConverter.double, MetaConverter.unit){ value: Double ->
|
||||
write(sinScale, value)
|
||||
}
|
||||
|
||||
override suspend fun IDemoDevice.onOpen() {
|
||||
launch {
|
||||
read(sinScale)
|
||||
|
Loading…
Reference in New Issue
Block a user