ControlsMagix refactor
This commit is contained in:
parent
a9f29f92ca
commit
641daec7e9
@ -4,7 +4,7 @@ plugins {
|
|||||||
}
|
}
|
||||||
|
|
||||||
description = """
|
description = """
|
||||||
Magix service for binding controls devices (both as RPC client and server
|
Magix service for binding controls devices (both as RPC client and server)
|
||||||
""".trimIndent()
|
""".trimIndent()
|
||||||
|
|
||||||
kscience {
|
kscience {
|
||||||
@ -16,7 +16,7 @@ kscience {
|
|||||||
dependencies {
|
dependencies {
|
||||||
api(projects.magix.magixApi)
|
api(projects.magix.magixApi)
|
||||||
api(projects.controlsCore)
|
api(projects.controlsCore)
|
||||||
api("com.benasher44:uuid:0.7.0")
|
api("com.benasher44:uuid:0.8.0")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -19,7 +19,7 @@ import kotlin.coroutines.CoroutineContext
|
|||||||
private fun stringUID() = uuid4().leastSignificantBits.toString(16)
|
private fun stringUID() = uuid4().leastSignificantBits.toString(16)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An implementation of device via RPC
|
* A remote accessible device that relies on connection via Magix
|
||||||
*/
|
*/
|
||||||
public class DeviceClient(
|
public class DeviceClient(
|
||||||
override val context: Context,
|
override val context: Context,
|
||||||
@ -103,11 +103,15 @@ public class DeviceClient(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Connect to a remote device via this client.
|
* Connect to a remote device via this endpoint.
|
||||||
|
*
|
||||||
|
* @param context a [Context] to run device in
|
||||||
|
* @param endpointName the name of endpoint in Magix to connect to
|
||||||
|
* @param deviceName the name of device within endpoint
|
||||||
*/
|
*/
|
||||||
public fun MagixEndpoint.remoteDevice(context: Context, magixTarget: String, deviceName: Name): DeviceClient {
|
public fun MagixEndpoint.remoteDevice(context: Context, endpointName: String, deviceName: Name): DeviceClient {
|
||||||
val subscription = subscribe(DeviceManager.magixFormat, originFilter = listOf(magixTarget)).map { it.second }
|
val subscription = subscribe(DeviceManager.magixFormat, originFilter = listOf(endpointName)).map { it.second }
|
||||||
return DeviceClient(context, deviceName, subscription) {
|
return DeviceClient(context, deviceName, subscription) {
|
||||||
send(DeviceManager.magixFormat, it, magixTarget, id = stringUID())
|
send(DeviceManager.magixFormat, it, endpointName, id = stringUID())
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -33,7 +33,7 @@ internal fun generateId(request: MagixMessage): String = if (request.id != null)
|
|||||||
/**
|
/**
|
||||||
* Communicate with server in [Magix format](https://github.com/waltz-controls/rfc/tree/master/1)
|
* Communicate with server in [Magix format](https://github.com/waltz-controls/rfc/tree/master/1)
|
||||||
*/
|
*/
|
||||||
public fun DeviceManager.connectToMagix(
|
public fun DeviceManager.launchMagixService(
|
||||||
endpoint: MagixEndpoint,
|
endpoint: MagixEndpoint,
|
||||||
endpointID: String = controlsMagixFormat.defaultFormat,
|
endpointID: String = controlsMagixFormat.defaultFormat,
|
||||||
): Job = context.launch {
|
): Job = context.launch {
|
||||||
@ -42,9 +42,9 @@ public fun DeviceManager.connectToMagix(
|
|||||||
if (responsePayload != null) {
|
if (responsePayload != null) {
|
||||||
endpoint.send(
|
endpoint.send(
|
||||||
format = controlsMagixFormat,
|
format = controlsMagixFormat,
|
||||||
target = request.sourceEndpoint,
|
|
||||||
origin = endpointID,
|
|
||||||
payload = responsePayload,
|
payload = responsePayload,
|
||||||
|
source = endpointID,
|
||||||
|
target = request.sourceEndpoint,
|
||||||
id = generateId(request),
|
id = generateId(request),
|
||||||
parentId = request.id
|
parentId = request.id
|
||||||
)
|
)
|
||||||
@ -56,8 +56,8 @@ public fun DeviceManager.connectToMagix(
|
|||||||
hubMessageFlow(this).onEach { payload ->
|
hubMessageFlow(this).onEach { payload ->
|
||||||
endpoint.send(
|
endpoint.send(
|
||||||
format = controlsMagixFormat,
|
format = controlsMagixFormat,
|
||||||
origin = endpointID,
|
|
||||||
payload = payload,
|
payload = payload,
|
||||||
|
source = endpointID,
|
||||||
id = "df[${payload.hashCode()}]"
|
id = "df[${payload.hashCode()}]"
|
||||||
)
|
)
|
||||||
}.catch { error ->
|
}.catch { error ->
|
@ -77,10 +77,10 @@ public fun DeviceManager.launchTangoMagix(
|
|||||||
suspend fun respond(request: MagixMessage, payload: TangoPayload, payloadBuilder: (TangoPayload) -> TangoPayload) {
|
suspend fun respond(request: MagixMessage, payload: TangoPayload, payloadBuilder: (TangoPayload) -> TangoPayload) {
|
||||||
endpoint.send(
|
endpoint.send(
|
||||||
tangoMagixFormat,
|
tangoMagixFormat,
|
||||||
|
payload = payloadBuilder(payload),
|
||||||
|
source = endpointID,
|
||||||
id = generateId(request),
|
id = generateId(request),
|
||||||
parentId = request.id,
|
parentId = request.id
|
||||||
origin = endpointID,
|
|
||||||
payload = payloadBuilder(payload)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,10 +127,10 @@ public fun DeviceManager.launchTangoMagix(
|
|||||||
logger.error(ex) { "Error while responding to message" }
|
logger.error(ex) { "Error while responding to message" }
|
||||||
endpoint.send(
|
endpoint.send(
|
||||||
tangoMagixFormat,
|
tangoMagixFormat,
|
||||||
|
payload = payload.copy(quality = TangoQuality.WARNING),
|
||||||
|
source = endpointID,
|
||||||
id = generateId(request),
|
id = generateId(request),
|
||||||
parentId = request.id,
|
parentId = request.id
|
||||||
origin = endpointID,
|
|
||||||
payload = payload.copy(quality = TangoQuality.WARNING)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}.launchIn(this)
|
}.launchIn(this)
|
@ -13,7 +13,7 @@ kscience{
|
|||||||
}
|
}
|
||||||
dependencies(jvmMain){
|
dependencies(jvmMain){
|
||||||
api(projects.magix.magixApi)
|
api(projects.magix.magixApi)
|
||||||
api(projects.controlsMagixClient)
|
api(projects.controlsMagix)
|
||||||
api(projects.magix.magixServer)
|
api(projects.magix.magixServer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@ dependencies {
|
|||||||
implementation(projects.controlsCore)
|
implementation(projects.controlsCore)
|
||||||
//implementation(projects.controlsServer)
|
//implementation(projects.controlsServer)
|
||||||
implementation(projects.magix.magixServer)
|
implementation(projects.magix.magixServer)
|
||||||
implementation(projects.controlsMagixClient)
|
implementation(projects.controlsMagix)
|
||||||
implementation(projects.magix.magixRsocket)
|
implementation(projects.magix.magixRsocket)
|
||||||
implementation(projects.magix.magixZmq)
|
implementation(projects.magix.magixZmq)
|
||||||
implementation(projects.controlsOpcua)
|
implementation(projects.controlsOpcua)
|
||||||
|
@ -8,7 +8,7 @@ import javafx.stage.Stage
|
|||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import org.eclipse.milo.opcua.sdk.server.OpcUaServer
|
import org.eclipse.milo.opcua.sdk.server.OpcUaServer
|
||||||
import org.eclipse.milo.opcua.stack.core.types.builtin.LocalizedText
|
import org.eclipse.milo.opcua.stack.core.types.builtin.LocalizedText
|
||||||
import space.kscience.controls.client.connectToMagix
|
import space.kscience.controls.client.launchMagixService
|
||||||
import space.kscience.controls.demo.DemoDevice.Companion.cosScale
|
import space.kscience.controls.demo.DemoDevice.Companion.cosScale
|
||||||
import space.kscience.controls.demo.DemoDevice.Companion.sinScale
|
import space.kscience.controls.demo.DemoDevice.Companion.sinScale
|
||||||
import space.kscience.controls.demo.DemoDevice.Companion.timeScale
|
import space.kscience.controls.demo.DemoDevice.Companion.timeScale
|
||||||
@ -59,7 +59,7 @@ class DemoController : Controller(), ContextAware {
|
|||||||
)
|
)
|
||||||
//Launch a device client and connect it to the server
|
//Launch a device client and connect it to the server
|
||||||
val deviceEndpoint = MagixEndpoint.rSocketWithTcp("localhost")
|
val deviceEndpoint = MagixEndpoint.rSocketWithTcp("localhost")
|
||||||
deviceManager.connectToMagix(deviceEndpoint)
|
deviceManager.launchMagixService(deviceEndpoint)
|
||||||
//connect visualization to a magix endpoint
|
//connect visualization to a magix endpoint
|
||||||
val visualEndpoint = MagixEndpoint.rSocketWithWebSockets("localhost")
|
val visualEndpoint = MagixEndpoint.rSocketWithWebSockets("localhost")
|
||||||
visualizer = startDemoDeviceServer(visualEndpoint)
|
visualizer = startDemoDeviceServer(visualEndpoint)
|
||||||
|
@ -19,7 +19,7 @@ dependencies {
|
|||||||
implementation(projects.magix.magixServer)
|
implementation(projects.magix.magixServer)
|
||||||
implementation(projects.magix.magixRsocket)
|
implementation(projects.magix.magixRsocket)
|
||||||
implementation(projects.magix.magixZmq)
|
implementation(projects.magix.magixZmq)
|
||||||
implementation(projects.controlsMagixClient)
|
implementation(projects.controlsMagix)
|
||||||
implementation(projects.controlsStorage.controlsXodus)
|
implementation(projects.controlsStorage.controlsXodus)
|
||||||
implementation(projects.magix.magixStorage.magixStorageXodus)
|
implementation(projects.magix.magixStorage.magixStorageXodus)
|
||||||
// implementation(projects.controlsMongo)
|
// implementation(projects.controlsMongo)
|
||||||
|
@ -8,7 +8,7 @@ import javafx.scene.layout.Priority
|
|||||||
import javafx.stage.Stage
|
import javafx.stage.Stage
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import space.kscience.controls.client.connectToMagix
|
import space.kscience.controls.client.launchMagixService
|
||||||
import space.kscience.controls.demo.car.IVirtualCar.Companion.acceleration
|
import space.kscience.controls.demo.car.IVirtualCar.Companion.acceleration
|
||||||
import space.kscience.controls.manager.DeviceManager
|
import space.kscience.controls.manager.DeviceManager
|
||||||
import space.kscience.controls.manager.install
|
import space.kscience.controls.manager.install
|
||||||
@ -63,7 +63,7 @@ class VirtualCarController : Controller(), ContextAware {
|
|||||||
//mongoStorageJob = deviceManager.storeMessages(DefaultAsynchronousMongoClientFactory)
|
//mongoStorageJob = deviceManager.storeMessages(DefaultAsynchronousMongoClientFactory)
|
||||||
//Launch device client and connect it to the server
|
//Launch device client and connect it to the server
|
||||||
val deviceEndpoint = MagixEndpoint.rSocketWithTcp("localhost")
|
val deviceEndpoint = MagixEndpoint.rSocketWithTcp("localhost")
|
||||||
deviceManager.connectToMagix(deviceEndpoint)
|
deviceManager.launchMagixService(deviceEndpoint)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ val rsocketVersion: String by rootProject.extra
|
|||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation(projects.magix.magixServer)
|
implementation(projects.magix.magixServer)
|
||||||
implementation(projects.controlsMagixClient)
|
implementation(projects.controlsMagix)
|
||||||
implementation(projects.magix.magixRsocket)
|
implementation(projects.magix.magixRsocket)
|
||||||
implementation(projects.magix.magixZmq)
|
implementation(projects.magix.magixZmq)
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@ import kotlinx.coroutines.flow.onEach
|
|||||||
import kotlinx.coroutines.sync.Mutex
|
import kotlinx.coroutines.sync.Mutex
|
||||||
import kotlinx.coroutines.sync.withLock
|
import kotlinx.coroutines.sync.withLock
|
||||||
import kotlinx.datetime.Clock
|
import kotlinx.datetime.Clock
|
||||||
import space.kscience.controls.client.connectToMagix
|
import space.kscience.controls.client.launchMagixService
|
||||||
import space.kscience.controls.client.magixFormat
|
import space.kscience.controls.client.magixFormat
|
||||||
import space.kscience.controls.manager.DeviceManager
|
import space.kscience.controls.manager.DeviceManager
|
||||||
import space.kscience.controls.manager.install
|
import space.kscience.controls.manager.install
|
||||||
@ -78,7 +78,7 @@ suspend fun main() {
|
|||||||
|
|
||||||
val endpointId = "device$it"
|
val endpointId = "device$it"
|
||||||
val deviceEndpoint = MagixEndpoint.rSocketWithTcp("localhost")
|
val deviceEndpoint = MagixEndpoint.rSocketWithTcp("localhost")
|
||||||
deviceManager.connectToMagix(deviceEndpoint, endpointId)
|
deviceManager.launchMagixService(deviceEndpoint, endpointId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,6 +24,6 @@ val dataforgeVersion: String by extra
|
|||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation(project(":controls-ports-ktor"))
|
implementation(project(":controls-ports-ktor"))
|
||||||
implementation(project(":controls-magix-client"))
|
implementation(projects.controlsMagix)
|
||||||
implementation("no.tornado:tornadofx:1.7.20")
|
implementation("no.tornado:tornadofx:1.7.20")
|
||||||
}
|
}
|
||||||
|
@ -41,16 +41,16 @@ public fun <T> MagixEndpoint.subscribe(
|
|||||||
public suspend fun <T> MagixEndpoint.send(
|
public suspend fun <T> MagixEndpoint.send(
|
||||||
format: MagixFormat<T>,
|
format: MagixFormat<T>,
|
||||||
payload: T,
|
payload: T,
|
||||||
|
source: String,
|
||||||
target: String? = null,
|
target: String? = null,
|
||||||
id: String? = null,
|
id: String? = null,
|
||||||
parentId: String? = null,
|
parentId: String? = null,
|
||||||
user: JsonElement? = null,
|
user: JsonElement? = null,
|
||||||
origin: String = format.defaultFormat,
|
|
||||||
) {
|
) {
|
||||||
val message = MagixMessage(
|
val message = MagixMessage(
|
||||||
format = format.defaultFormat,
|
format = format.defaultFormat,
|
||||||
payload = magixJson.encodeToJsonElement(format.serializer, payload),
|
payload = magixJson.encodeToJsonElement(format.serializer, payload),
|
||||||
sourceEndpoint = origin,
|
sourceEndpoint = source,
|
||||||
targetEndpoint = target,
|
targetEndpoint = target,
|
||||||
id = id,
|
id = id,
|
||||||
parentId = parentId,
|
parentId = parentId,
|
||||||
|
@ -20,13 +20,17 @@ import space.kscience.magix.api.subscribe
|
|||||||
*/
|
*/
|
||||||
public interface MagixRegistry {
|
public interface MagixRegistry {
|
||||||
/**
|
/**
|
||||||
* Request a property with name [propertyName] and user authentication data [user].
|
* Request a property with name [propertyName].
|
||||||
*
|
*
|
||||||
* Return a property value in its generic form or null if it is not present.
|
* Return a property value in its generic form or null if it is not present.
|
||||||
*
|
*
|
||||||
* Throw exception access is denied, or request failed.
|
* Throw exception access is denied, or request failed.
|
||||||
*/
|
*/
|
||||||
public suspend fun request(propertyName: String, user: JsonElement? = null): JsonElement?
|
public suspend fun get(propertyName: String): JsonElement?
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface MutableMagixRegistry {
|
||||||
|
public suspend fun set(propertyName: String, value: JsonElement?, user: JsonElement?)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
@ -48,7 +52,7 @@ public class MagixRegistryRequestMessage(
|
|||||||
@SerialName("registry.value")
|
@SerialName("registry.value")
|
||||||
public class MagixRegistryValueMessage(
|
public class MagixRegistryValueMessage(
|
||||||
override val propertyName: String,
|
override val propertyName: String,
|
||||||
public val value: JsonElement,
|
public val value: JsonElement?,
|
||||||
) : MagixRegistryMessage()
|
) : MagixRegistryMessage()
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
@ -59,29 +63,58 @@ public class MagixRegistryErrorMessage(
|
|||||||
public val errorMessage: String? = null,
|
public val errorMessage: String? = null,
|
||||||
) : MagixRegistryMessage()
|
) : MagixRegistryMessage()
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
@SerialName("registry.modify")
|
||||||
|
public class MagixRegistryModifyMessage(
|
||||||
|
override val propertyName: String,
|
||||||
|
public val value: JsonElement,
|
||||||
|
) : MagixRegistryMessage()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Launch a magix registry loop service based on local registry
|
* Launch a magix registry loop service based on local registry
|
||||||
*/
|
*/
|
||||||
public fun CoroutineScope.launchMagixRegistry(
|
public fun CoroutineScope.launchMagixRegistry(
|
||||||
|
endpointName: String,
|
||||||
endpoint: MagixEndpoint,
|
endpoint: MagixEndpoint,
|
||||||
registry: MagixRegistry,
|
registry: MagixRegistry,
|
||||||
originFilter: Collection<String>? = null,
|
originFilter: Collection<String>? = null,
|
||||||
targetFilter: Collection<String>? = null,
|
targetFilter: Collection<String>? = null,
|
||||||
): Job = endpoint.subscribe(MagixRegistryMessage.format, originFilter, targetFilter)
|
): Job = endpoint.subscribe(MagixRegistryMessage.format, originFilter, targetFilter)
|
||||||
.onEach { (magixMessage, payload) ->
|
.onEach { (magixMessage, payload) ->
|
||||||
if (payload is MagixRegistryRequestMessage) {
|
try {
|
||||||
try {
|
when {
|
||||||
val value = registry.request(payload.propertyName, magixMessage.user)
|
payload is MagixRegistryRequestMessage -> {
|
||||||
endpoint.send(
|
endpoint.send(
|
||||||
MagixRegistryMessage.format,
|
MagixRegistryMessage.format,
|
||||||
MagixRegistryValueMessage(payload.propertyName, value ?: JsonNull)
|
MagixRegistryValueMessage(payload.propertyName, registry.get(payload.propertyName) ?: JsonNull),
|
||||||
)
|
source = endpointName,
|
||||||
} catch (ex: Exception) {
|
target = magixMessage.sourceEndpoint,
|
||||||
endpoint.send(
|
parentId = magixMessage.id
|
||||||
MagixRegistryMessage.format,
|
)
|
||||||
MagixRegistryErrorMessage(payload.propertyName, ex::class.simpleName, ex.message)
|
}
|
||||||
)
|
|
||||||
|
payload is MagixRegistryModifyMessage && registry is MutableMagixRegistry -> {
|
||||||
|
registry.set(payload.propertyName, payload.value, magixMessage.user)
|
||||||
|
// Broadcast updates. Do not set target
|
||||||
|
endpoint.send(
|
||||||
|
MagixRegistryMessage.format,
|
||||||
|
MagixRegistryValueMessage(
|
||||||
|
payload.propertyName,
|
||||||
|
registry.get(payload.propertyName)
|
||||||
|
),
|
||||||
|
source = endpointName,
|
||||||
|
parentId = magixMessage.id
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} catch (ex: Exception) {
|
||||||
|
endpoint.send(
|
||||||
|
MagixRegistryMessage.format,
|
||||||
|
MagixRegistryErrorMessage(payload.propertyName, ex::class.simpleName, ex.message),
|
||||||
|
source = endpointName,
|
||||||
|
target = magixMessage.sourceEndpoint,
|
||||||
|
parentId = magixMessage.id
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}.launchIn(this)
|
}.launchIn(this)
|
||||||
|
|
||||||
@ -92,20 +125,29 @@ public fun CoroutineScope.launchMagixRegistry(
|
|||||||
* The subscriber can terminate the flow at any moment to stop subscription, or use it indefinitely to continue observing changes.
|
* The subscriber can terminate the flow at any moment to stop subscription, or use it indefinitely to continue observing changes.
|
||||||
* To request a single value, use [Flow.first] function.
|
* To request a single value, use [Flow.first] function.
|
||||||
*
|
*
|
||||||
* If [targetEndpoint] field is provided, send request only to given endpoint.
|
* If [registryEndpoint] field is provided, send request only to given endpoint.
|
||||||
|
*
|
||||||
|
* @param endpointName the name of endpoint requesting a property
|
||||||
*/
|
*/
|
||||||
public suspend fun MagixEndpoint.getProperty(
|
public suspend fun MagixEndpoint.getProperty(
|
||||||
propertyName: String,
|
propertyName: String,
|
||||||
|
endpointName: String,
|
||||||
user: JsonElement? = null,
|
user: JsonElement? = null,
|
||||||
targetEndpoint: String? = null,
|
registryEndpoint: String? = null,
|
||||||
): Flow<Pair<String, JsonElement>> {
|
): Flow<Pair<String, JsonElement>> = subscribe(
|
||||||
send(MagixRegistryMessage.format, MagixRegistryRequestMessage(propertyName), target = targetEndpoint, user = user)
|
MagixRegistryMessage.format,
|
||||||
return subscribe(
|
originFilter = registryEndpoint?.let { setOf(it) }
|
||||||
|
).mapNotNull { (message, response) ->
|
||||||
|
if (response is MagixRegistryValueMessage && response.propertyName == propertyName) {
|
||||||
|
message.sourceEndpoint to (response.value ?: return@mapNotNull null)
|
||||||
|
} else null
|
||||||
|
}.also {
|
||||||
|
//send the initial request after subscription
|
||||||
|
send(
|
||||||
MagixRegistryMessage.format,
|
MagixRegistryMessage.format,
|
||||||
originFilter = targetEndpoint?.let { setOf(it) }
|
MagixRegistryRequestMessage(propertyName),
|
||||||
).mapNotNull { (message, response) ->
|
source = endpointName,
|
||||||
if (response is MagixRegistryValueMessage && response.propertyName == propertyName) {
|
target = registryEndpoint,
|
||||||
message.sourceEndpoint to response.value
|
user = user
|
||||||
} else null
|
)
|
||||||
}
|
|
||||||
}
|
}
|
@ -50,11 +50,11 @@ public fun MagixEndpoint.launchHistory(
|
|||||||
send(
|
send(
|
||||||
format = MagixHistory.magixFormat,
|
format = MagixHistory.magixFormat,
|
||||||
payload = sendPayload,
|
payload = sendPayload,
|
||||||
|
source = origin,
|
||||||
target = request.sourceEndpoint,
|
target = request.sourceEndpoint,
|
||||||
id = generateId(request),
|
id = generateId(request),
|
||||||
parentId = request.id,
|
parentId = request.id,
|
||||||
user = user,
|
user = user,
|
||||||
origin = origin,
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -60,7 +60,7 @@ include(
|
|||||||
":magix:magix-mqtt",
|
":magix:magix-mqtt",
|
||||||
":magix:magix-storage",
|
":magix:magix-storage",
|
||||||
":magix:magix-storage:magix-storage-xodus",
|
":magix:magix-storage:magix-storage-xodus",
|
||||||
":controls-magix-client",
|
":controls-magix",
|
||||||
":demo:all-things",
|
":demo:all-things",
|
||||||
":demo:many-devices",
|
":demo:many-devices",
|
||||||
":demo:magix-demo",
|
":demo:magix-demo",
|
||||||
|
Loading…
Reference in New Issue
Block a user