From 6ba095248658a9a8842e34d8b278786bef8316cb Mon Sep 17 00:00:00 2001 From: Florian Schrofner Date: Sat, 19 Feb 2022 17:37:09 +0100 Subject: [PATCH] add apply command functionality --- build.gradle.kts | 1 + .../fi/schro/data/ConfigurationRepository.kt | 41 +++++++++++++++++-- src/nativeMain/kotlin/fi/schro/di/Modules.kt | 2 +- .../kotlin/fi/schro/ui/HappyCatCommand.kt | 9 +++- .../kotlin/fi/schro/util/TimeUtil.kt | 38 +++++++++++++++++ 5 files changed, 84 insertions(+), 7 deletions(-) create mode 100644 src/nativeMain/kotlin/fi/schro/util/TimeUtil.kt diff --git a/build.gradle.kts b/build.gradle.kts index 542fb31..d9b64fa 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -41,6 +41,7 @@ kotlin { 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("org.jetbrains.kotlinx:kotlinx-datetime:0.3.2") implementation("io.ktor:ktor-client-core:1.6.7") implementation("io.ktor:ktor-client-cio:1.6.7") implementation("io.ktor:ktor-client-serialization:1.6.7") diff --git a/src/nativeMain/kotlin/fi/schro/data/ConfigurationRepository.kt b/src/nativeMain/kotlin/fi/schro/data/ConfigurationRepository.kt index 70d5e89..3921a31 100644 --- a/src/nativeMain/kotlin/fi/schro/data/ConfigurationRepository.kt +++ b/src/nativeMain/kotlin/fi/schro/data/ConfigurationRepository.kt @@ -1,9 +1,12 @@ package fi.schro.data -import fi.schro.util.FileUtil +import com.github.ajalt.clikt.output.TermUi.echo +import fi.schro.util.* +import kotlinx.datetime.* +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable import kotlinx.serialization.decodeFromString import kotlinx.serialization.json.Json -import platform.posix.fopen interface ConfigurationRepository { suspend fun applyConfiguration(configurationFilePath: String, lightAddress: String, port: Int? = null) @@ -14,7 +17,25 @@ class ConfigurationRepositoryImpl( ): ConfigurationRepository { override suspend fun applyConfiguration(configurationFilePath: String, lightAddress: String, port: Int?) { val configString = FileUtil.readAllText(configurationFilePath) - TODO("Not yet implemented") + val configuration = Json.decodeFromString(configString) + val statusToApply = determineCurrentStatus(configuration) + + statusToApply?.let { newStatus -> + echo("applying new status:") + echo(newStatus.toString()) + applyLightStatus(lightAddress, port, newStatus) + } + } + + private fun determineCurrentStatus(configuration: Configuration): LightStatus? { + val currentTime = Clock.System.now().toLocalDateTime(TimeZone.currentSystemDefault()) + val currentDate = TimeUtil.getCurrentDate() + + return configuration.config.firstOrNull { timedConfiguration -> + val start = currentDate.atTime(timedConfiguration.start) + val end = currentDate.atTime(timedConfiguration.end) + currentTime in start..end + }?.status } private suspend fun applyLightStatus(lightAddress: String, port: Int?, status: LightStatus){ @@ -23,4 +44,16 @@ class ConfigurationRepositoryImpl( lightRepository.setLightStatus(lightAddress, port, statusUpdate) } } -} \ No newline at end of file +} + +@Serializable +data class Configuration( + @SerialName("config") val config: List +) + +@Serializable +data class TimedStatusConfiguration( + @SerialName("start") @Serializable(with = LocalTimeSerializer::class) val start: LocalTime, + @SerialName("end") @Serializable(with = LocalTimeSerializer::class) val end: LocalTime, + @SerialName("status") val status: LightStatus +) \ No newline at end of file diff --git a/src/nativeMain/kotlin/fi/schro/di/Modules.kt b/src/nativeMain/kotlin/fi/schro/di/Modules.kt index b47d0b7..d25d2ca 100644 --- a/src/nativeMain/kotlin/fi/schro/di/Modules.kt +++ b/src/nativeMain/kotlin/fi/schro/di/Modules.kt @@ -13,7 +13,7 @@ import io.ktor.client.features.json.* import org.koin.dsl.module val commandModule = module { - single{ ApplyCommand() } + single{ ApplyCommand(get()) } single{ SetCommand(get()) } single{ GetCommand(get()) } } diff --git a/src/nativeMain/kotlin/fi/schro/ui/HappyCatCommand.kt b/src/nativeMain/kotlin/fi/schro/ui/HappyCatCommand.kt index c491f65..521bb66 100644 --- a/src/nativeMain/kotlin/fi/schro/ui/HappyCatCommand.kt +++ b/src/nativeMain/kotlin/fi/schro/ui/HappyCatCommand.kt @@ -7,6 +7,7 @@ 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.ConfigurationRepository import fi.schro.data.LightRepository import fi.schro.data.LightStatus import kotlinx.coroutines.runBlocking @@ -77,12 +78,16 @@ class GetCommand( } } -class ApplyCommand: CliktCommand(name = "apply", help = "Applies the given configuration to the specified light"){ +class ApplyCommand( + private val configurationRepository: ConfigurationRepository +): 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") + runBlocking { + configurationRepository.applyConfiguration(configurationFile, targetLamp) + } } } diff --git a/src/nativeMain/kotlin/fi/schro/util/TimeUtil.kt b/src/nativeMain/kotlin/fi/schro/util/TimeUtil.kt new file mode 100644 index 0000000..cd75e95 --- /dev/null +++ b/src/nativeMain/kotlin/fi/schro/util/TimeUtil.kt @@ -0,0 +1,38 @@ +package fi.schro.util + +import kotlinx.datetime.* +import kotlinx.serialization.KSerializer +import kotlinx.serialization.Serializable +import kotlinx.serialization.descriptors.PrimitiveKind +import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor +import kotlinx.serialization.descriptors.SerialDescriptor +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder + +object TimeUtil { + fun getCurrentDate(): LocalDate { + val currentTime = Clock.System.now() + return currentTime.toLocalDateTime(TimeZone.currentSystemDefault()).date + } +} + +fun LocalDate.atTime(time: LocalTime): LocalDateTime{ + return LocalDateTime(year, month, dayOfMonth, time.hour, time.minute, 0, 0) +} + +@Serializable +data class LocalTime(val hour: Int, val minute: Int) + +object LocalTimeSerializer: KSerializer{ + override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("Time", PrimitiveKind.STRING) + + override fun deserialize(decoder: Decoder): LocalTime { + val stringValue = decoder.decodeString() + val values = stringValue.split(":").map { it.toInt() } + return LocalTime(values[0], values[1]) + } + + override fun serialize(encoder: Encoder, value: LocalTime) { + encoder.encodeString("${value.hour}:${value.minute}") + } +} \ No newline at end of file