Skip to content

Commit f592b08

Browse files
author
Robert Winkler
committed
Updated code
1 parent 8e317c9 commit f592b08

File tree

17 files changed

+394
-437
lines changed

17 files changed

+394
-437
lines changed

.idea/misc.xml

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

kotlin-wot-binding-http/src/main/kotlin/http/HttpProtocolServer.kt

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import ai.ancf.lmos.wot.thing.form.Form
1010
import ai.ancf.lmos.wot.thing.form.Operation
1111
import ai.ancf.lmos.wot.thing.schema.ContentListener
1212
import ai.ancf.lmos.wot.thing.schema.DataSchemaValue
13+
import ai.ancf.lmos.wot.thing.schema.DataSchemaValue.*
1314
import ai.ancf.lmos.wot.thing.schema.InteractionAffordance
1415
import ai.ancf.lmos.wot.thing.schema.WoTExposedThing
1516
import ai.anfc.lmos.wot.binding.ProtocolServer
@@ -230,25 +231,25 @@ fun Application.setupRouting(servient: Servient) {
230231
for ((key, value) in properties) {
231232
// Assuming content is not null as it's checked earlier
232233
when (val schemaValue: DataSchemaValue = ContentManager.contentToValue(value, null)) {
233-
is DataSchemaValue.BooleanValue -> {
234+
is BooleanValue -> {
234235
response[key] = schemaValue.value
235236
}
236-
is DataSchemaValue.IntegerValue -> {
237+
is IntegerValue -> {
237238
response[key] = schemaValue.value
238239
}
239-
is DataSchemaValue.NumberValue -> {
240+
is NumberValue -> {
240241
response[key] = schemaValue.value
241242
}
242-
is DataSchemaValue.StringValue -> {
243+
is StringValue -> {
243244
response[key] = schemaValue.value
244245
}
245-
is DataSchemaValue.ObjectValue -> {
246+
is ObjectValue -> {
246247
response[key] = schemaValue.value
247248
}
248-
is DataSchemaValue.ArrayValue -> {
249+
is ArrayValue -> {
249250
response[key] = schemaValue.value
250251
}
251-
is DataSchemaValue.NullValue -> {
252+
is NullValue -> {
252253
response[key] = null
253254
}
254255
}

kotlin-wot-binding-mqtt/src/main/kotlin/mqtt/MqttProtocolClientFactory.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ open class MqttProtocolClientFactory(private val mqttClientConfig: MqttClientCon
1010
.identifier(mqttClientConfig.clientId)
1111
.serverHost(mqttClientConfig.host)
1212
.serverPort(mqttClientConfig.port)
13-
.automaticReconnect()
14-
.applyAutomaticReconnect()
13+
//.automaticReconnect()
14+
//.applyAutomaticReconnect()
1515
.build()
1616
.toAsync()
1717
)

kotlin-wot-binding-mqtt/src/main/kotlin/mqtt/MqttProtocolServer.kt

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ class MqttProtocolServer(
2727
.identifier(mqttClientConfig.clientId)
2828
.serverHost(mqttClientConfig.host)
2929
.serverPort(mqttClientConfig.port)
30-
.automaticReconnect().applyAutomaticReconnect().buildAsync()
30+
//.automaticReconnect().applyAutomaticReconnect()
31+
.buildAsync()
3132

3233
private val log: Logger = LoggerFactory.getLogger(MqttProtocolServer::class.java)
3334
private val things = mutableMapOf<String, ExposedThing>()
@@ -38,15 +39,17 @@ class MqttProtocolServer(
3839
}
3940

4041
override suspend fun start(servient: Servient) {
41-
log.info("Connect Mqtt server client")
42+
log.info("Starting MqttProtocolServer")
4243
client.connect().await()
4344
started = true
45+
log.info("MqttProtocolServer started and connected to ${client.config.serverHost}:${client.config.serverPort} ")
4446
}
4547

4648
override suspend fun stop() {
47-
log.info("Disconnect Mqtt server client")
49+
log.info("Stopping MqttProtocolServer")
4850
client.disconnect().await()
4951
started = false
52+
log.info("MqttProtocolServer stopped")
5053
}
5154

5255
override suspend fun expose(thing: ExposedThing) {

kotlin-wot-integration-tests/build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,5 @@ dependencies {
99
implementation("dev.langchain4j:langchain4j-azure-open-ai:0.35.0")
1010
implementation("dev.langchain4j:langchain4j:0.35.0")
1111
testImplementation("com.hivemq:hivemq-mqtt-client:1.3.3")
12-
testImplementation("org.testcontainers:testcontainers:1.20.3")
12+
implementation("org.testcontainers:testcontainers:1.20.3")
1313
}

kotlin-wot-integration-tests/src/main/kotlin/integration/Agent.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package integration
1+
package ai.ancf.lmos.wot.integration
22

33
import dev.langchain4j.model.azure.AzureOpenAiChatModel
44

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package integration
2+
3+
import kotlinx.coroutines.runBlocking
4+
import org.testcontainers.containers.GenericContainer
5+
import org.testcontainers.utility.DockerImageName
6+
7+
fun main(): Unit = runBlocking {
8+
9+
val hiveMqContainer = GenericContainer(DockerImageName.parse("hivemq/hivemq-ce:latest"))
10+
.withExposedPorts(1883)
11+
12+
println("Starting HiveMQ container...")
13+
hiveMqContainer.start()
14+
15+
println(hiveMqContainer.getMappedPort(1883))
16+
17+
println("Application is running. Press Ctrl+C to stop.")
18+
19+
// Register a shutdown hook for cleanup on termination
20+
Runtime.getRuntime().addShutdownHook(Thread {
21+
println("Application is shutting down. Performing cleanup...")
22+
// Perform any necessary cleanup here
23+
})
24+
25+
// Block the main thread indefinitely
26+
kotlinx.coroutines.suspendCancellableCoroutine<Unit> { /* Suspends forever */ }
27+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package ai.ancf.lmos.wot.integration
2+
3+
import ai.ancf.lmos.wot.Wot
4+
import kotlinx.coroutines.Dispatchers
5+
import kotlinx.coroutines.Job
6+
import kotlinx.coroutines.launch
7+
import kotlinx.coroutines.runBlocking
8+
9+
10+
fun main(): Unit = runBlocking {
11+
12+
val agent = Agent()
13+
14+
// Protocol can be "HTTP" or "MQTT"
15+
val servient = createServient("HTTP")
16+
17+
// Register a shutdown hook
18+
Runtime.getRuntime().addShutdownHook(Thread {
19+
println("Application is shutting down. Performing cleanup...")
20+
launch { servient.shutdown() }
21+
})
22+
23+
val wot = Wot.create(servient)
24+
val exposedThing = createExposedThing(wot, agent)
25+
26+
// Start `servient` in a separate coroutine
27+
servient.start()
28+
// Add and expose the thing after `start()` has had time to begin
29+
servient.addThing(exposedThing)
30+
servient.expose("agent")
31+
32+
println("Exposed Agent on HTTP Server")
33+
// Keep the application running until process is stopped
34+
Job().join()
35+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package ai.ancf.lmos.wot.integration
2+
3+
import ai.ancf.lmos.wot.Wot
4+
import kotlinx.coroutines.*
5+
6+
7+
fun main(): Unit = runBlocking {
8+
val agent = Agent()
9+
10+
// Protocol can be "HTTP" or "MQTT"
11+
val servient = createServient("MQTT")
12+
13+
// Register a shutdown hook
14+
Runtime.getRuntime().addShutdownHook(Thread {
15+
println("Application is shutting down. Performing cleanup...")
16+
launch { servient.shutdown() }
17+
})
18+
19+
val wot = Wot.create(servient)
20+
val exposedThing = createExposedThing(wot, agent)
21+
22+
// Start `servient` in a separate coroutine
23+
servient.start()
24+
// Add and expose the thing after `start()` has had time to begin
25+
servient.addThing(exposedThing)
26+
servient.expose("agent")
27+
println("Exposed Agent on MQTT Server")
28+
// Keep the application running until process is stopped
29+
Job().join()
30+
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
package ai.ancf.lmos.wot.integration
2+
3+
import ai.ancf.lmos.wot.Servient
4+
import ai.ancf.lmos.wot.Wot
5+
import ai.ancf.lmos.wot.binding.http.HttpProtocolClientFactory
6+
import ai.ancf.lmos.wot.binding.http.HttpProtocolServer
7+
import ai.ancf.lmos.wot.binding.mqtt.MqttClientConfig
8+
import ai.ancf.lmos.wot.binding.mqtt.MqttProtocolServer
9+
import ai.ancf.lmos.wot.thing.ExposedThing
10+
import ai.ancf.lmos.wot.thing.Type
11+
import ai.ancf.lmos.wot.thing.schema.*
12+
13+
private const val PROPERTY_NAME = "property1"
14+
private const val PROPERTY_NAME_2 = "property2"
15+
16+
private const val ACTION_NAME = "ask"
17+
18+
private const val EVENT_NAME = "event1"
19+
20+
fun createServient(protocol: String): Servient {
21+
return when (protocol) {
22+
"HTTP" -> Servient(
23+
servers = listOf(HttpProtocolServer()),
24+
clientFactories = listOf(HttpProtocolClientFactory())
25+
)
26+
"MQTT" -> {
27+
val mqttConfig = MqttClientConfig("localhost", 54884, "wotServer")
28+
Servient(
29+
servers = listOf(MqttProtocolServer(mqttConfig))
30+
)
31+
}
32+
else -> throw IllegalArgumentException("Unsupported protocol: $protocol")
33+
}
34+
}
35+
36+
fun createExposedThing(wot: Wot, agent: Agent): ExposedThing {
37+
return wot.produce {
38+
id = "agent"
39+
title = "Agent"
40+
objectType = Type("Agent")
41+
intProperty(PROPERTY_NAME) { observable = true }
42+
intProperty(PROPERTY_NAME_2) { observable = true }
43+
action<String, Map<*, *>>(ACTION_NAME) {
44+
title = ACTION_NAME
45+
description = "Ask a question to the agent"
46+
input = stringSchema {
47+
title = "Action Input"
48+
description = "Question"
49+
minLength = 10
50+
default = "test"
51+
}
52+
output = objectSchema {
53+
stringProperty("response") {
54+
description = "Answer of the agent"
55+
}
56+
}
57+
}
58+
event<String, Nothing, Nothing>(EVENT_NAME) { data = StringSchema() }
59+
}.apply {
60+
setPropertyReadHandler(PROPERTY_NAME) { 10.toInteractionInputValue() }
61+
setPropertyReadHandler(PROPERTY_NAME_2) { 5.toInteractionInputValue() }
62+
setPropertyWriteHandler(PROPERTY_NAME) { input, _ ->
63+
val inputInt = input.value() as DataSchemaValue.IntegerValue
64+
inputInt.value.toInteractionInputValue()
65+
}
66+
setActionHandler(ACTION_NAME) { input, _ ->
67+
val inputString = input.value() as DataSchemaValue.StringValue
68+
agent.ask(inputString.value).toInteractionInputValue()
69+
}
70+
}
71+
}

0 commit comments

Comments
 (0)