Simplify UI management in constructor

This commit is contained in:
Alexander Nozik 2023-11-05 09:47:58 +03:00
parent 811477a636
commit 0e963a7b13
5 changed files with 95 additions and 57 deletions

View File

@ -8,6 +8,7 @@ import space.kscience.controls.manager.DeviceManager
import space.kscience.controls.manager.install import space.kscience.controls.manager.install
import space.kscience.dataforge.context.Context import space.kscience.dataforge.context.Context
import space.kscience.dataforge.context.Factory import space.kscience.dataforge.context.Factory
import space.kscience.dataforge.context.request
import space.kscience.dataforge.meta.Laminate import space.kscience.dataforge.meta.Laminate
import space.kscience.dataforge.meta.Meta import space.kscience.dataforge.meta.Meta
import space.kscience.dataforge.meta.MutableMeta import space.kscience.dataforge.meta.MutableMeta
@ -158,6 +159,12 @@ public fun DeviceManager.deviceGroup(
return group return group
} }
public fun Context.deviceGroup(
name: String = "@group",
meta: Meta = Meta.EMPTY,
block: DeviceGroup.() -> Unit,
): DeviceGroup = request(DeviceManager).deviceGroup(name, meta, block)
private fun DeviceGroup.getOrCreateGroup(name: Name): DeviceGroup { private fun DeviceGroup.getOrCreateGroup(name: Name): DeviceGroup {
return when (name.length) { return when (name.length) {
0 -> this 0 -> this

View File

@ -12,6 +12,8 @@ val visionforgeVersion = "0.3.0-dev-10"
kscience { kscience {
jvm() jvm()
js() js()
useKtor()
useContextReceivers()
dependencies { dependencies {
api(projects.controlsCore) api(projects.controlsCore)
api(projects.controlsConstructor) api(projects.controlsConstructor)
@ -21,6 +23,7 @@ kscience {
jvmMain{ jvmMain{
api("space.kscience:visionforge-server:$visionforgeVersion") api("space.kscience:visionforge-server:$visionforgeVersion")
api("io.ktor:ktor-server-cio")
} }
} }

View File

@ -0,0 +1,61 @@
package space.kscience.controls.vision
import io.ktor.server.cio.CIO
import io.ktor.server.engine.ApplicationEngine
import io.ktor.server.engine.embeddedServer
import io.ktor.server.http.content.staticResources
import io.ktor.server.routing.Routing
import io.ktor.server.routing.routing
import kotlinx.html.TagConsumer
import space.kscience.dataforge.context.Context
import space.kscience.plotly.Plot
import space.kscience.plotly.PlotlyConfig
import space.kscience.visionforge.html.HtmlVisionFragment
import space.kscience.visionforge.html.VisionPage
import space.kscience.visionforge.html.VisionTagConsumer
import space.kscience.visionforge.plotly.plotly
import space.kscience.visionforge.server.VisionRoute
import space.kscience.visionforge.server.close
import space.kscience.visionforge.server.openInBrowser
import space.kscience.visionforge.server.visionPage
import space.kscience.visionforge.visionManager
public fun Context.showDashboard(
port: Int = 7777,
routes: Routing.() -> Unit = {},
configurationBuilder: VisionRoute.() -> Unit = {},
visionFragment: HtmlVisionFragment,
): ApplicationEngine = embeddedServer(CIO, port = port) {
routing {
staticResources("", null, null)
routes()
}
visionPage(
visionManager,
VisionPage.scriptHeader("js/constructor.js"),
configurationBuilder = configurationBuilder,
visionFragment = visionFragment
)
}.also {
it.start(false)
it.openInBrowser()
println("Enter 'exit' to close server")
while (readlnOrNull() != "exit") {
//
}
it.close()
}
context(VisionTagConsumer<*>)
public fun TagConsumer<*>.plot(
config: PlotlyConfig = PlotlyConfig(),
block: Plot.() -> Unit,
) {
vision {
plotly(config, block)
}
}

View File

@ -6,6 +6,7 @@ plugins {
kscience { kscience {
fullStack("js/constructor.js", jvmConfig = {withJava()}) fullStack("js/constructor.js", jvmConfig = {withJava()})
useKtor() useKtor()
useContextReceivers()
dependencies { dependencies {
api(projects.controlsVision) api(projects.controlsVision)
} }

View File

@ -1,9 +1,5 @@
package space.kscience.controls.demo.constructor package space.kscience.controls.demo.constructor
import io.ktor.server.cio.CIO
import io.ktor.server.engine.embeddedServer
import io.ktor.server.http.content.staticResources
import io.ktor.server.routing.routing
import space.kscience.controls.api.get import space.kscience.controls.api.get
import space.kscience.controls.constructor.* import space.kscience.controls.constructor.*
import space.kscience.controls.manager.ClockManager import space.kscience.controls.manager.ClockManager
@ -12,18 +8,13 @@ import space.kscience.controls.manager.clock
import space.kscience.controls.spec.doRecurring import space.kscience.controls.spec.doRecurring
import space.kscience.controls.spec.name import space.kscience.controls.spec.name
import space.kscience.controls.spec.write import space.kscience.controls.spec.write
import space.kscience.controls.vision.plot
import space.kscience.controls.vision.plotDeviceProperty import space.kscience.controls.vision.plotDeviceProperty
import space.kscience.controls.vision.plotNumberState import space.kscience.controls.vision.plotNumberState
import space.kscience.controls.vision.showDashboard
import space.kscience.dataforge.context.Context import space.kscience.dataforge.context.Context
import space.kscience.dataforge.context.request
import space.kscience.plotly.models.ScatterMode import space.kscience.plotly.models.ScatterMode
import space.kscience.visionforge.VisionManager
import space.kscience.visionforge.html.VisionPage
import space.kscience.visionforge.plotly.PlotlyPlugin import space.kscience.visionforge.plotly.PlotlyPlugin
import space.kscience.visionforge.plotly.plotly
import space.kscience.visionforge.server.close
import space.kscience.visionforge.server.openInBrowser
import space.kscience.visionforge.server.visionPage
import kotlin.math.PI import kotlin.math.PI
import kotlin.math.sin import kotlin.math.sin
import kotlin.time.Duration.Companion.milliseconds import kotlin.time.Duration.Companion.milliseconds
@ -38,9 +29,6 @@ public fun main() {
plugin(ClockManager) plugin(ClockManager)
} }
val deviceManager = context.request(DeviceManager)
val visionManager = context.request(VisionManager)
val state = DoubleRangeState(0.0, -5.0..5.0) val state = DoubleRangeState(0.0, -5.0..5.0)
val pidParameters = PidParameters( val pidParameters = PidParameters(
@ -50,7 +38,7 @@ public fun main() {
timeStep = 0.005.seconds timeStep = 0.005.seconds
) )
val device = deviceManager.deviceGroup { val device = context.deviceGroup {
val drive = virtualDrive("drive", 0.005, state) val drive = virtualDrive("drive", 0.005, state)
val pid = pid("pid", drive, pidParameters) val pid = pid("pid", drive, pidParameters)
virtualLimitSwitch("start", state.atStartState) virtualLimitSwitch("start", state.atStartState)
@ -69,59 +57,37 @@ public fun main() {
} }
} }
val server = embeddedServer(CIO, port = 7777) {
routing {
staticResources("", null, null)
}
visionPage( context.showDashboard {
visionManager, plot {
VisionPage.scriptHeader("js/constructor.js") plotNumberState(context, state) {
) { name = "real position"
vision { }
plotly { plotDeviceProperty(device["pid"], Regulator.position.name) {
plotNumberState(context, state) { name = "read position"
name = "real position"
}
plotDeviceProperty(device["pid"], Regulator.position.name) {
name = "read position"
}
plotDeviceProperty(device["pid"], Regulator.target.name) {
name = "target"
}
}
} }
vision { plotDeviceProperty(device["pid"], Regulator.target.name) {
plotly { name = "target"
}
}
plot {
// plotBooleanState(context, state.atStartState) { // plotBooleanState(context, state.atStartState) {
// name = "start" // name = "start"
// } // }
// plotBooleanState(context, state.atEndState) { // plotBooleanState(context, state.atEndState) {
// name = "end" // name = "end"
// } // }
plotDeviceProperty(device["start"], LimitSwitch.locked.name) { plotDeviceProperty(device["start"], LimitSwitch.locked.name) {
name = "start measured" name = "start measured"
mode = ScatterMode.markers mode = ScatterMode.markers
} }
plotDeviceProperty(device["end"], LimitSwitch.locked.name) { plotDeviceProperty(device["end"], LimitSwitch.locked.name) {
name = "end measured" name = "end measured"
mode = ScatterMode.markers mode = ScatterMode.markers
}
}
} }
} }
}.start(false)
server.openInBrowser()
println("Enter 'exit' to close server")
while (readlnOrNull() != "exit") {
//
} }
server.close()
} }