From bc70fcfa442fc07724ec4bc4688fd3c2a52e0828 Mon Sep 17 00:00:00 2001 From: Florian Schrofner Date: Sun, 13 Feb 2022 17:31:48 +0100 Subject: [PATCH] setup koin, add light repository, start network setup --- build.gradle.kts | 4 + gradle.properties | 1 + src/nativeMain/kotlin/fi/schro/Main.kt | 13 ++- .../fi/schro/data/ElgatoLightRepository.kt | 46 +++++++++++ .../kotlin/fi/schro/data/LightRepository.kt | 22 +++++ src/nativeMain/kotlin/fi/schro/di/Modules.kt | 29 +++++++ .../kotlin/fi/schro/ui/HappyCatCommand.kt | 82 ++++++++++++++++++- 7 files changed, 194 insertions(+), 3 deletions(-) create mode 100644 src/nativeMain/kotlin/fi/schro/data/ElgatoLightRepository.kt create mode 100644 src/nativeMain/kotlin/fi/schro/data/LightRepository.kt diff --git a/build.gradle.kts b/build.gradle.kts index 51e25b8..b2c445c 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,5 +1,6 @@ plugins { kotlin("multiplatform") version "1.6.10" + kotlin("plugin.serialization") version "1.6.10" } group = "fi.schro" @@ -32,6 +33,9 @@ kotlin { dependencies { implementation("io.insert-koin:koin-core:3.1.5") implementation("com.github.ajalt.clikt:clikt:3.4.0") + implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.3.2") + implementation("io.ktor:ktor-client-core:1.6.7") + implementation("io.ktor:ktor-client-cio:1.6.7") } } val nativeTest by getting diff --git a/gradle.properties b/gradle.properties index 9f8ac5f..550aa4e 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,3 +1,4 @@ kotlin.code.style=official kotlin.mpp.enableGranularSourceSetsMetadata=true kotlin.native.enableDependencyPropagation=false +kotlin.native.cacheKind.linuxX64=none \ No newline at end of file diff --git a/src/nativeMain/kotlin/fi/schro/Main.kt b/src/nativeMain/kotlin/fi/schro/Main.kt index 1700a5a..0db9629 100644 --- a/src/nativeMain/kotlin/fi/schro/Main.kt +++ b/src/nativeMain/kotlin/fi/schro/Main.kt @@ -1,5 +1,14 @@ package fi.schro -fun main() { - println("Hello, Kotlin/Native!") +import fi.schro.di.mainModule +import fi.schro.ui.HappyCatCommand +import org.koin.core.context.startKoin + +fun main(args: Array) { + startKoin { + modules(mainModule) + } + + HappyCatCommand() + .main(args) } \ No newline at end of file diff --git a/src/nativeMain/kotlin/fi/schro/data/ElgatoLightRepository.kt b/src/nativeMain/kotlin/fi/schro/data/ElgatoLightRepository.kt new file mode 100644 index 0000000..945ab56 --- /dev/null +++ b/src/nativeMain/kotlin/fi/schro/data/ElgatoLightRepository.kt @@ -0,0 +1,46 @@ +package fi.schro.data + +import fi.schro.ui.LightPowerState +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable +import kotlin.math.roundToInt + +class ElgatoLightRepository: LightRepository { + override fun setLightStatus(lightAddress: String, status: LightStatus) { + TODO("Not yet implemented") + } + + override fun getLightStatus(lightAddress: String): LightStatus { + TODO("Not yet implemented") + } +} + +@Serializable +data class ElgatoLightStatus( + @SerialName("lights") val lights: List, + @SerialName("numberOfLights") val numberOfLights: Int = lights.size +) + +@Serializable +data class ElgatoLight( + @SerialName("on") val on: Int? = null, + @SerialName("brightness") val brightness: Int? = null, + @SerialName("temperature") val temperature: Int? = null +){ + fun toLightStatus(){ + LightStatus( + powerStatus = on?.let { LightPowerState.fromInt(it) }, + brightness = brightness, + temperature = temperature?.let { convertElgatoTemperatureToKelvin(it) } + ) + } +} + +private fun convertKelvinToElgatoTemperature(kelvinTemperature: Int): Int { + TODO("todo") +} + +private fun convertElgatoTemperatureToKelvin(elgatoTemperature: Int): Int { + //based on: https://github.com/justinforlenza/keylight-control/blob/main/src/keylight.js + return (((-4100*elgatoTemperature) / 201f) + 1993300/201f).roundToInt() +} \ No newline at end of file diff --git a/src/nativeMain/kotlin/fi/schro/data/LightRepository.kt b/src/nativeMain/kotlin/fi/schro/data/LightRepository.kt new file mode 100644 index 0000000..c8b2cb5 --- /dev/null +++ b/src/nativeMain/kotlin/fi/schro/data/LightRepository.kt @@ -0,0 +1,22 @@ +package fi.schro.data + +import fi.schro.ui.LightPowerState + +interface LightRepository { + fun setLightStatus(lightAddress: String, status: LightStatus) + fun getLightStatus(lightAddress: String): LightStatus +} + +data class LightStatus( + val powerStatus: LightPowerState?, + val brightness: Int?, + val temperature: Int? +){ + override fun toString(): String { + val stringList = mutableListOf() + powerStatus?.let { stringList.add("status: ${powerStatus.stringValue}") } + brightness?.let { stringList.add("brightness: $brightness") } + temperature?.let { stringList.add("temperature: $temperature") } + return stringList.joinToString(separator = "\n") + } +} diff --git a/src/nativeMain/kotlin/fi/schro/di/Modules.kt b/src/nativeMain/kotlin/fi/schro/di/Modules.kt index 2803e6e..367a3ab 100644 --- a/src/nativeMain/kotlin/fi/schro/di/Modules.kt +++ b/src/nativeMain/kotlin/fi/schro/di/Modules.kt @@ -1 +1,30 @@ package fi.schro.di + +import fi.schro.data.ElgatoLightRepository +import fi.schro.data.LightRepository +import fi.schro.ui.ApplyCommand +import fi.schro.ui.GetCommand +import fi.schro.ui.SetCommand +import io.ktor.client.* +import io.ktor.client.engine.cio.* +import org.koin.dsl.module + +val commandModule = module { + single{ ApplyCommand() } + single{ SetCommand() } + single{ GetCommand(get()) } +} + +val dataModule = module { + single { ElgatoLightRepository() } +} + +val networkModule = module { + single { HttpClient(CIO) } +} + +val mainModule = listOf( + commandModule, + dataModule, + networkModule +) \ No newline at end of file diff --git a/src/nativeMain/kotlin/fi/schro/ui/HappyCatCommand.kt b/src/nativeMain/kotlin/fi/schro/ui/HappyCatCommand.kt index 33ae60e..33225ce 100644 --- a/src/nativeMain/kotlin/fi/schro/ui/HappyCatCommand.kt +++ b/src/nativeMain/kotlin/fi/schro/ui/HappyCatCommand.kt @@ -1,4 +1,84 @@ package fi.schro.ui -class HappyCatCommand { +import com.github.ajalt.clikt.core.CliktCommand +import com.github.ajalt.clikt.core.subcommands +import com.github.ajalt.clikt.parameters.arguments.argument +import com.github.ajalt.clikt.parameters.options.check +import com.github.ajalt.clikt.parameters.options.option +import com.github.ajalt.clikt.parameters.types.enum +import com.github.ajalt.clikt.parameters.types.int +import fi.schro.data.LightRepository +import org.koin.core.component.KoinComponent +import org.koin.core.component.inject + +const val ARG_TARGET_LAMP = "TARGET_LAMP" +const val ARG_CONFIGURATION_FILE = "CONFIGURATION_FILE" + +class HappyCatCommand: CliktCommand(), KoinComponent { + private val applyCommand: ApplyCommand by inject() + private val getCommand: GetCommand by inject() + private val setCommand: SetCommand by inject() + + init { + subcommands( + applyCommand, + getCommand, + setCommand + ) + } + + override fun run() = Unit +} + +class SetCommand: CliktCommand(name = "set", help = "Sets the defined values to the specified light"){ + private val targetLamp: String by argument(ARG_TARGET_LAMP) + private val brightness: Int? by option( + "-b", + "--brightness", + help = "The brightness to be set in percent of the maximum" + ).int().check("Value must be between 0 and 100") { + it in 0..100 + } + private val temperature: Int? by option("-t", "--temperature", help = "The temperature to be set in Kelvin").int() + .check("Value must be between 1,000 and 10,000") { + it in 1000..10000 + } + + private val powerState: LightPowerState? by option("-p", "--powerstate", help = "The state to be set").enum() + + + override fun run() { + echo("Values set") + } +} + +class GetCommand( + private val lightRepository: LightRepository +) : CliktCommand(name = "get", help = "Gets and prints the current setting of the specified light") { + private val targetLamp: String by argument(ARG_TARGET_LAMP) + + override fun run() { + val status = lightRepository.getLightStatus(targetLamp) + echo(status) + } +} + +class ApplyCommand: CliktCommand(name = "apply", help = "Applies the given configuration to the specified light"){ + private val configurationFile: String by argument(ARG_CONFIGURATION_FILE) + private val targetLamp: String by argument(ARG_TARGET_LAMP) + + override fun run() { + echo("Configuration applied") + } +} + +enum class LightPowerState(val stringValue: String, val intValue: Int) { + ON("ON", 1), + OFF("OFF", 0); + + companion object { + fun fromInt(intValue: Int): LightPowerState? { + return values().firstOrNull { it.intValue == intValue } + } + } } \ No newline at end of file