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