forked from kscience/visionforge
Server is alive!
This commit is contained in:
parent
faddb8a393
commit
6a742658af
@ -2,7 +2,7 @@ plugins {
|
|||||||
id("ru.mipt.npm.project")
|
id("ru.mipt.npm.project")
|
||||||
}
|
}
|
||||||
|
|
||||||
val dataforgeVersion by extra("0.2.0")
|
val dataforgeVersion by extra("0.2.1-dev-4")
|
||||||
val ktorVersion by extra("1.4.2")
|
val ktorVersion by extra("1.4.2")
|
||||||
val htmlVersion by extra("0.7.2")
|
val htmlVersion by extra("0.7.2")
|
||||||
val kotlinWrappersVersion by extra("pre.129-kotlin-1.4.20")
|
val kotlinWrappersVersion by extra("pre.129-kotlin-1.4.20")
|
||||||
|
@ -3,8 +3,8 @@ package ru.mipt.npm.sat
|
|||||||
|
|
||||||
import hep.dataforge.context.Global
|
import hep.dataforge.context.Global
|
||||||
import hep.dataforge.names.asName
|
import hep.dataforge.names.asName
|
||||||
|
import hep.dataforge.names.toName
|
||||||
import hep.dataforge.vision.VisionManager
|
import hep.dataforge.vision.VisionManager
|
||||||
import hep.dataforge.vision.get
|
|
||||||
import hep.dataforge.vision.server.close
|
import hep.dataforge.vision.server.close
|
||||||
import hep.dataforge.vision.server.serve
|
import hep.dataforge.vision.server.serve
|
||||||
import hep.dataforge.vision.server.show
|
import hep.dataforge.vision.server.show
|
||||||
@ -40,11 +40,12 @@ fun main() {
|
|||||||
vision("main".asName(), sat)
|
vision("main".asName(), sat)
|
||||||
}
|
}
|
||||||
launch {
|
launch {
|
||||||
|
delay(1000)
|
||||||
while (isActive) {
|
while (isActive) {
|
||||||
val currentLayer = Random.nextInt(10)
|
val target = "layer[${Random.nextInt(1,10)}].segment[${Random.nextInt(3)},${Random.nextInt(3)}]".toName()
|
||||||
(sat["layer[$currentLayer]"] as? Solid)?.color(123)
|
(sat[target] as? Solid)?.color("red")
|
||||||
delay(300)
|
delay(300)
|
||||||
(sat["layer[$currentLayer]"] as? Solid)?.color = null
|
(sat[target] as? Solid)?.color = "green"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
package hep.dataforge.vision
|
package hep.dataforge.vision
|
||||||
|
|
||||||
import hep.dataforge.meta.Meta
|
|
||||||
import hep.dataforge.meta.MetaItem
|
import hep.dataforge.meta.MetaItem
|
||||||
import hep.dataforge.meta.get
|
import hep.dataforge.meta.get
|
||||||
import hep.dataforge.meta.number
|
import hep.dataforge.meta.number
|
||||||
import hep.dataforge.values.ValueType
|
import hep.dataforge.values.ValueType
|
||||||
import hep.dataforge.values.int
|
import hep.dataforge.values.int
|
||||||
|
import hep.dataforge.values.string
|
||||||
import kotlin.math.max
|
import kotlin.math.max
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -3,10 +3,9 @@ package hep.dataforge.vision
|
|||||||
import hep.dataforge.meta.*
|
import hep.dataforge.meta.*
|
||||||
import hep.dataforge.names.Name
|
import hep.dataforge.names.Name
|
||||||
import hep.dataforge.names.plus
|
import hep.dataforge.names.plus
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.*
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.flow.flow
|
import kotlinx.coroutines.flow.flow
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import kotlinx.coroutines.sync.Mutex
|
import kotlinx.coroutines.sync.Mutex
|
||||||
import kotlinx.coroutines.sync.withLock
|
import kotlinx.coroutines.sync.withLock
|
||||||
import kotlinx.serialization.*
|
import kotlinx.serialization.*
|
||||||
@ -15,7 +14,7 @@ import kotlin.time.Duration
|
|||||||
/**
|
/**
|
||||||
* An update for a [Vision] or a [VisionGroup]
|
* An update for a [Vision] or a [VisionGroup]
|
||||||
*/
|
*/
|
||||||
public class VisionChangeBuilder: VisionContainerBuilder<Vision> {
|
public class VisionChangeBuilder : VisionContainerBuilder<Vision> {
|
||||||
private val propertyChange = HashMap<Name, Config>()
|
private val propertyChange = HashMap<Name, Config>()
|
||||||
private val childrenChange = HashMap<Name, Vision?>()
|
private val childrenChange = HashMap<Name, Vision?>()
|
||||||
|
|
||||||
@ -47,7 +46,8 @@ private fun Vision.isolate(manager: VisionManager): Vision {
|
|||||||
@Serializable
|
@Serializable
|
||||||
public data class VisionChange(
|
public data class VisionChange(
|
||||||
val propertyChange: Map<Name, @Serializable(MetaSerializer::class) Meta>,
|
val propertyChange: Map<Name, @Serializable(MetaSerializer::class) Meta>,
|
||||||
val childrenChange: Map<Name, Vision?>) {
|
val childrenChange: Map<Name, Vision?>,
|
||||||
|
) {
|
||||||
public fun isEmpty(): Boolean = propertyChange.isEmpty() && childrenChange.isEmpty()
|
public fun isEmpty(): Boolean = propertyChange.isEmpty() && childrenChange.isEmpty()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -64,7 +64,7 @@ private fun CoroutineScope.collectChange(
|
|||||||
name: Name,
|
name: Name,
|
||||||
source: Vision,
|
source: Vision,
|
||||||
mutex: Mutex,
|
mutex: Mutex,
|
||||||
collector: ()->VisionChangeBuilder,
|
collector: () -> VisionChangeBuilder,
|
||||||
) {
|
) {
|
||||||
//Collect properties change
|
//Collect properties change
|
||||||
source.config.onChange(mutex) { propertyName, oldItem, newItem ->
|
source.config.onChange(mutex) { propertyName, oldItem, newItem ->
|
||||||
@ -107,17 +107,19 @@ public fun Vision.flowChanges(
|
|||||||
val mutex = Mutex()
|
val mutex = Mutex()
|
||||||
|
|
||||||
var collector = VisionChangeBuilder()
|
var collector = VisionChangeBuilder()
|
||||||
scope.collectChange(Name.EMPTY, this@flowChanges, mutex){collector}
|
scope.collectChange(Name.EMPTY, this@flowChanges, mutex) { collector }
|
||||||
|
|
||||||
while (true) {
|
while (currentCoroutineContext().isActive) {
|
||||||
//Wait for changes to accumulate
|
//Wait for changes to accumulate
|
||||||
kotlinx.coroutines.delay(collectionDuration)
|
delay(collectionDuration)
|
||||||
//Propagate updates only if something is changed
|
//Propagate updates only if something is changed
|
||||||
if (!collector.isEmpty()) {
|
if (!collector.isEmpty()) {
|
||||||
//emit changes
|
//emit changes
|
||||||
|
mutex.withLock {
|
||||||
emit(collector.isolate(manager))
|
emit(collector.isolate(manager))
|
||||||
//Reset the collector
|
//Reset the collector
|
||||||
collector = VisionChangeBuilder()
|
collector = VisionChangeBuilder()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -6,6 +6,7 @@ import hep.dataforge.names.asName
|
|||||||
import hep.dataforge.values.Null
|
import hep.dataforge.values.Null
|
||||||
import hep.dataforge.values.Value
|
import hep.dataforge.values.Value
|
||||||
import hep.dataforge.values.asValue
|
import hep.dataforge.values.asValue
|
||||||
|
import hep.dataforge.values.string
|
||||||
import javafx.scene.control.ColorPicker
|
import javafx.scene.control.ColorPicker
|
||||||
import javafx.scene.paint.Color
|
import javafx.scene.paint.Color
|
||||||
import org.slf4j.LoggerFactory
|
import org.slf4j.LoggerFactory
|
||||||
@ -22,7 +23,7 @@ public class ColorValueChooser : ValueChooserBase<ColorPicker>() {
|
|||||||
this.value = Color.valueOf(value.string)
|
this.value = Color.valueOf(value.string)
|
||||||
}
|
}
|
||||||
} catch (ex: Exception) {
|
} catch (ex: Exception) {
|
||||||
LoggerFactory.getLogger(javaClass).warn("Invalid color field value: " + value.string)
|
LoggerFactory.getLogger(javaClass).warn("Invalid color field value: $value")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,7 @@ import hep.dataforge.names.Name
|
|||||||
import hep.dataforge.names.asName
|
import hep.dataforge.names.asName
|
||||||
import hep.dataforge.values.Value
|
import hep.dataforge.values.Value
|
||||||
import hep.dataforge.values.parseValue
|
import hep.dataforge.values.parseValue
|
||||||
|
import hep.dataforge.values.string
|
||||||
import javafx.collections.FXCollections
|
import javafx.collections.FXCollections
|
||||||
import javafx.scene.control.ComboBox
|
import javafx.scene.control.ComboBox
|
||||||
import javafx.util.StringConverter
|
import javafx.util.StringConverter
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
package hep.dataforge.vision.editor
|
package hep.dataforge.vision.editor
|
||||||
|
|
||||||
import hep.dataforge.meta.Meta
|
import hep.dataforge.meta.Meta
|
||||||
|
import hep.dataforge.values.string
|
||||||
import hep.dataforge.vision.dfIconView
|
import hep.dataforge.vision.dfIconView
|
||||||
import javafx.beans.property.SimpleStringProperty
|
import javafx.beans.property.SimpleStringProperty
|
||||||
import javafx.scene.control.TreeItem
|
import javafx.scene.control.TreeItem
|
||||||
|
@ -5,38 +5,40 @@ import hep.dataforge.meta.double
|
|||||||
import hep.dataforge.meta.get
|
import hep.dataforge.meta.get
|
||||||
import hep.dataforge.meta.int
|
import hep.dataforge.meta.int
|
||||||
import hep.dataforge.values.ValueType
|
import hep.dataforge.values.ValueType
|
||||||
|
import hep.dataforge.values.int
|
||||||
|
import hep.dataforge.values.string
|
||||||
import hep.dataforge.vision.Colors
|
import hep.dataforge.vision.Colors
|
||||||
import javafx.scene.paint.Color
|
import javafx.scene.paint.Color
|
||||||
import javafx.scene.paint.Material
|
import javafx.scene.paint.Material
|
||||||
import javafx.scene.paint.PhongMaterial
|
import javafx.scene.paint.PhongMaterial
|
||||||
|
|
||||||
object FXMaterials {
|
public object FXMaterials {
|
||||||
val RED = PhongMaterial().apply {
|
public val RED: PhongMaterial = PhongMaterial().apply {
|
||||||
diffuseColor = Color.DARKRED
|
diffuseColor = Color.DARKRED
|
||||||
specularColor = Color.WHITE
|
specularColor = Color.WHITE
|
||||||
}
|
}
|
||||||
|
|
||||||
val WHITE = PhongMaterial().apply {
|
public val WHITE: PhongMaterial = PhongMaterial().apply {
|
||||||
diffuseColor = Color.WHITE
|
diffuseColor = Color.WHITE
|
||||||
specularColor = Color.LIGHTBLUE
|
specularColor = Color.LIGHTBLUE
|
||||||
}
|
}
|
||||||
|
|
||||||
val GREY = PhongMaterial().apply {
|
public val GREY: PhongMaterial = PhongMaterial().apply {
|
||||||
diffuseColor = Color.DARKGREY
|
diffuseColor = Color.DARKGREY
|
||||||
specularColor = Color.WHITE
|
specularColor = Color.WHITE
|
||||||
}
|
}
|
||||||
|
|
||||||
val BLUE = PhongMaterial(Color.BLUE)
|
public val BLUE: PhongMaterial = PhongMaterial(Color.BLUE)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Infer color based on meta item
|
* Infer color based on meta item
|
||||||
* @param opacity default opacity
|
* @param opacity default opacity
|
||||||
*/
|
*/
|
||||||
fun MetaItem<*>.color(opacity: Double = 1.0): Color {
|
public fun MetaItem<*>.color(opacity: Double = 1.0): Color {
|
||||||
return when (this) {
|
return when (this) {
|
||||||
is MetaItem.ValueItem -> if (this.value.type == ValueType.NUMBER) {
|
is MetaItem.ValueItem -> if (this.value.type == ValueType.NUMBER) {
|
||||||
val int = value.number.toInt()
|
val int = value.int
|
||||||
val red = int and 0x00ff0000 shr 16
|
val red = int and 0x00ff0000 shr 16
|
||||||
val green = int and 0x0000ff00 shr 8
|
val green = int and 0x0000ff00 shr 8
|
||||||
val blue = int and 0x000000ff
|
val blue = int and 0x000000ff
|
||||||
|
@ -37,7 +37,9 @@ import io.ktor.util.error
|
|||||||
import io.ktor.websocket.WebSockets
|
import io.ktor.websocket.WebSockets
|
||||||
import io.ktor.websocket.webSocket
|
import io.ktor.websocket.webSocket
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.flow.collect
|
import kotlinx.coroutines.flow.catch
|
||||||
|
import kotlinx.coroutines.flow.launchIn
|
||||||
|
import kotlinx.coroutines.flow.onEach
|
||||||
import kotlinx.html.*
|
import kotlinx.html.*
|
||||||
import kotlinx.html.stream.createHTML
|
import kotlinx.html.stream.createHTML
|
||||||
import java.awt.Desktop
|
import java.awt.Desktop
|
||||||
@ -115,15 +117,12 @@ public class VisionServer internal constructor(
|
|||||||
|
|
||||||
application.log.debug("Opened server socket for $name")
|
application.log.debug("Opened server socket for $name")
|
||||||
val vision: Vision = visions[name.toName()] ?: error("Plot with id='$name' not registered")
|
val vision: Vision = visions[name.toName()] ?: error("Plot with id='$name' not registered")
|
||||||
try {
|
vision.flowChanges(visionManager, updateInterval.milliseconds).onEach { update ->
|
||||||
vision.flowChanges(visionManager, updateInterval.milliseconds).collect { update ->
|
|
||||||
val json = VisionManager.defaultJson.encodeToString(VisionChange.serializer(), update)
|
val json = VisionManager.defaultJson.encodeToString(VisionChange.serializer(), update)
|
||||||
outgoing.send(Frame.Text(json))
|
outgoing.send(Frame.Text(json))
|
||||||
}
|
}.catch { ex ->
|
||||||
} catch (ex: Throwable) {
|
|
||||||
application.log.error("Closed server socket for $name with exception $ex")
|
|
||||||
application.log.error(ex)
|
application.log.error(ex)
|
||||||
}
|
}.launchIn(visionManager.context).join()
|
||||||
}
|
}
|
||||||
//Plots in their json representation
|
//Plots in their json representation
|
||||||
get("vision") {
|
get("vision") {
|
||||||
@ -208,7 +207,7 @@ public fun Application.visionModule(context: Context, route: String = DEFAULT_PA
|
|||||||
public fun VisionManager.serve(
|
public fun VisionManager.serve(
|
||||||
host: String = "localhost",
|
host: String = "localhost",
|
||||||
port: Int = 7777,
|
port: Int = 7777,
|
||||||
block: VisionServer.()->Unit
|
block: VisionServer.() -> Unit,
|
||||||
): ApplicationEngine = context.embeddedServer(CIO, port, host) {
|
): ApplicationEngine = context.embeddedServer(CIO, port, host) {
|
||||||
visionModule(context).apply(block)
|
visionModule(context).apply(block)
|
||||||
}.start()
|
}.start()
|
||||||
|
@ -2,6 +2,8 @@ package hep.dataforge.vision.solid.three
|
|||||||
|
|
||||||
import hep.dataforge.meta.*
|
import hep.dataforge.meta.*
|
||||||
import hep.dataforge.values.ValueType
|
import hep.dataforge.values.ValueType
|
||||||
|
import hep.dataforge.values.int
|
||||||
|
import hep.dataforge.values.string
|
||||||
import hep.dataforge.vision.Colors
|
import hep.dataforge.vision.Colors
|
||||||
import hep.dataforge.vision.Vision
|
import hep.dataforge.vision.Vision
|
||||||
import hep.dataforge.vision.solid.SolidMaterial
|
import hep.dataforge.vision.solid.SolidMaterial
|
||||||
@ -90,7 +92,7 @@ public object ThreeMaterials {
|
|||||||
public fun MetaItem<*>.getColor(): Color {
|
public fun MetaItem<*>.getColor(): Color {
|
||||||
return when (this) {
|
return when (this) {
|
||||||
is MetaItem.ValueItem -> if (this.value.type == ValueType.NUMBER) {
|
is MetaItem.ValueItem -> if (this.value.type == ValueType.NUMBER) {
|
||||||
val int = value.number.toInt()
|
val int = value.int
|
||||||
Color(int)
|
Color(int)
|
||||||
} else {
|
} else {
|
||||||
Color(this.value.string)
|
Color(this.value.string)
|
||||||
|
Loading…
Reference in New Issue
Block a user