Skip to content

Commit

Permalink
Switched to Ktor WebSocket client
Browse files Browse the repository at this point in the history
  • Loading branch information
StefanOltmann committed May 11, 2024
1 parent f3b4c0a commit f291ed7
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 145 deletions.
6 changes: 4 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ buildscript {
kotlinVersion = '1.9.24'
slf4jVersion = '1.7.30'
sonarqubeVersion = '3.2.0'
websocketJettyClientVersion = '11.0.4'
ktorVersion = '2.3.11'
}
}

Expand Down Expand Up @@ -110,7 +110,9 @@ dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8"

// WebSocket client
implementation "org.eclipse.jetty.websocket:websocket-jetty-client:$websocketJettyClientVersion"
implementation "io.ktor:ktor-client-core:$ktorVersion"
implementation "io.ktor:ktor-client-cio:$ktorVersion"
implementation "io.ktor:ktor-client-websockets:$ktorVersion"

// Logging
implementation "org.slf4j:slf4j-simple:$slf4jVersion"
Expand Down
117 changes: 64 additions & 53 deletions src/main/java/de/stefan_oltmann/smarthome/vallox/ValloxClientImpl.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,54 +10,60 @@
*/
package de.stefan_oltmann.smarthome.vallox

import org.eclipse.jetty.websocket.api.Session
import org.eclipse.jetty.websocket.client.ClientUpgradeRequest
import org.eclipse.jetty.websocket.client.WebSocketClient
import java.net.URI
import io.ktor.client.HttpClient
import io.ktor.client.plugins.HttpTimeout
import io.ktor.client.plugins.websocket.WebSockets
import io.ktor.client.plugins.websocket.webSocket
import io.ktor.http.HttpMethod
import io.ktor.util.moveToByteArray
import io.ktor.websocket.send
import kotlinx.coroutines.runBlocking
import java.nio.ByteBuffer
import java.util.concurrent.Future
import java.util.concurrent.TimeUnit

/**
* The [ValloxClientImpl] is responsible for socket communication with the vallox ventilation unit
*
* @author Björn Brings - Initial contribution
* @author Stefan Oltmann - Refactorings and Kotlin conversion
*/
class ValloxClientImpl(private val uri: URI) : ValloxClient {
class ValloxClientImpl(
val host: String
) : ValloxClient {

private val webSocketClient = WebSocketClient()
private val httpClient = HttpClient {

private val messageHandler = ValloxMessageHandler
install(HttpTimeout) {
this.requestTimeoutMillis = 5000
}

init {
webSocketClient.start()
install(WebSockets)
}

override fun readStatus(): ValloxStatus {

val requestBytes = messageHandler.generateReadRequestBytes()

return sendBytesToService(requestBytes, ValloxDataMode.READ_TABLES)!!
return sendBytesToService(
ValloxMessageHandler.generateReadRequestBytes(),
ValloxDataMode.READ_TABLES
)!!
}

override fun turnOn() {
sendBytesToService(
requestBytes = messageHandler.generateWriteRequestBytesOnOff(1),
requestBytes = ValloxMessageHandler.generateWriteRequestBytesOnOff(1),
dataMode = ValloxDataMode.WRITE_DATA
)
}

override fun turnOff() {
sendBytesToService(
requestBytes = messageHandler.generateWriteRequestBytesOnOff(0),
requestBytes = ValloxMessageHandler.generateWriteRequestBytesOnOff(0),
dataMode = ValloxDataMode.WRITE_DATA
)
}

override fun switchProfile(profile: Profile) {
sendBytesToService(
requestBytes = messageHandler.generateWriteRequestBytesSwitchToProfile(profile),
requestBytes = ValloxMessageHandler.generateWriteRequestBytesSwitchToProfile(profile),
dataMode = ValloxDataMode.WRITE_DATA
)
}
Expand All @@ -67,7 +73,9 @@ class ValloxClientImpl(private val uri: URI) : ValloxClient {
require(fanSpeed in 0..100)

sendBytesToService(
requestBytes = messageHandler.generateWriteRequestBytesExtractFanBalanceBase(fanSpeed),
requestBytes = ValloxMessageHandler.generateWriteRequestBytesExtractFanBalanceBase(
fanSpeed
),
dataMode = ValloxDataMode.WRITE_DATA
)
}
Expand All @@ -77,7 +85,9 @@ class ValloxClientImpl(private val uri: URI) : ValloxClient {
require(fanSpeed in 0..100)

sendBytesToService(
requestBytes = messageHandler.generateWriteRequestBytesSupplyFanBalanceBase(fanSpeed),
requestBytes = ValloxMessageHandler.generateWriteRequestBytesSupplyFanBalanceBase(
fanSpeed
),
dataMode = ValloxDataMode.WRITE_DATA
)
}
Expand All @@ -87,7 +97,10 @@ class ValloxClientImpl(private val uri: URI) : ValloxClient {
require(fanSpeed in 0..100)

sendBytesToService(
requestBytes = messageHandler.generateWriteRequestBytesFanSpeed(profile, fanSpeed),
requestBytes = ValloxMessageHandler.generateWriteRequestBytesFanSpeed(
profile,
fanSpeed
),
dataMode = ValloxDataMode.WRITE_DATA
)
}
Expand All @@ -97,7 +110,9 @@ class ValloxClientImpl(private val uri: URI) : ValloxClient {
require(fanSpeed in 0..100)

sendBytesToService(
requestBytes = messageHandler.generateWriteRequestBytesFireplaceExtractFanSpeed(fanSpeed),
requestBytes = ValloxMessageHandler.generateWriteRequestBytesFireplaceExtractFanSpeed(
fanSpeed
),
dataMode = ValloxDataMode.WRITE_DATA
)
}
Expand All @@ -107,7 +122,9 @@ class ValloxClientImpl(private val uri: URI) : ValloxClient {
require(fanSpeed in 0..100)

sendBytesToService(
requestBytes = messageHandler.generateWriteRequestBytesFireplaceSupplyFanSpeed(fanSpeed),
requestBytes = ValloxMessageHandler.generateWriteRequestBytesFireplaceSupplyFanSpeed(
fanSpeed
),
dataMode = ValloxDataMode.WRITE_DATA
)
}
Expand All @@ -117,7 +134,7 @@ class ValloxClientImpl(private val uri: URI) : ValloxClient {
require(targetTemperature in 5..25)

sendBytesToService(
requestBytes = messageHandler.generateWriteRequestBytesTargetTemperature(
requestBytes = ValloxMessageHandler.generateWriteRequestBytesTargetTemperature(
profile,
targetTemperature
),
Expand All @@ -127,72 +144,66 @@ class ValloxClientImpl(private val uri: URI) : ValloxClient {

override fun setBytesBoostTime(boostTimeInMinutes: Int) {
sendBytesToService(
requestBytes = messageHandler.generateWriteRequestBytesBoostTime(boostTimeInMinutes),
requestBytes = ValloxMessageHandler.generateWriteRequestBytesBoostTime(
boostTimeInMinutes
),
dataMode = ValloxDataMode.WRITE_DATA
)
}

override fun setBoostTimerEnabled(enabled: Boolean) {
sendBytesToService(
requestBytes = messageHandler.generateWriteRequestBytesBoostTimerEnabled(enabled),
requestBytes = ValloxMessageHandler.generateWriteRequestBytesBoostTimerEnabled(enabled),
dataMode = ValloxDataMode.WRITE_DATA
)
}

override fun setFireplaceTime(fireplaceTimeInMinutes: Int) {
sendBytesToService(
requestBytes = messageHandler.generateWriteRequestBytesFireplaceTime(fireplaceTimeInMinutes),
requestBytes = ValloxMessageHandler.generateWriteRequestBytesFireplaceTime(
fireplaceTimeInMinutes
),
dataMode = ValloxDataMode.WRITE_DATA
)
}

override fun setFireplaceTimerEnabled(enabled: Boolean) {
sendBytesToService(
requestBytes = messageHandler.generateWriteRequestBytesFireplaceTimerEnabled(enabled),
requestBytes = ValloxMessageHandler.generateWriteRequestBytesFireplaceTimerEnabled(
enabled
),
dataMode = ValloxDataMode.WRITE_DATA
)
}

override fun setWeeklyTimerEnabled(enabled: Boolean) {
sendBytesToService(
requestBytes = messageHandler.generateWriteRequestBytesWeeklyTimerEnabled(enabled),
requestBytes = ValloxMessageHandler.generateWriteRequestBytesWeeklyTimerEnabled(enabled),
dataMode = ValloxDataMode.WRITE_DATA
)
}

private fun sendBytesToService(
requestBytes: ByteBuffer,
dataMode: ValloxDataMode
): ValloxStatus? {

var sessionFuture: Future<Session>? = null

var valloxStatus: ValloxStatus? = null

try {

val socket = ValloxWebSocketListener { bytes ->
valloxStatus = messageHandler.readMessage(dataMode, bytes)
}
): ValloxStatus? = runBlocking {

val request = ClientUpgradeRequest()
var status: ValloxStatus? = null

sessionFuture = webSocketClient.connect(socket, uri, request)
httpClient.webSocket(
method = HttpMethod.Get,
host = host,
port = 80,
path = "/"
) {

/* Blocked wait until connection is established. */
val session = sessionFuture.get()
send(requestBytes.moveToByteArray())

session.remote.sendBytes(requestBytes)
val responseBytes = incoming.receive().data

/* Wait that the request has finished. */
socket.awaitClose(2, TimeUnit.SECONDS)

return valloxStatus

} finally {

if (sessionFuture != null && !sessionFuture.isDone)
sessionFuture.cancel(true)
status = ValloxMessageHandler.readMessage(dataMode, responseBytes)
}

return@runBlocking status
}
}

This file was deleted.

0 comments on commit f291ed7

Please sign in to comment.