1
0
Fork 0

add support for setting temperature, start apply command, refactor

master
Florian Schrofner 2022-02-16 23:10:26 +01:00
parent 6451ede58a
commit ddd7fb7ed6
6 changed files with 94 additions and 16 deletions

View File

@ -0,0 +1,26 @@
package fi.schro.data
import fi.schro.util.FileUtil
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)
}
class ConfigurationRepositoryImpl(
private val lightRepository: LightRepository
): ConfigurationRepository {
override suspend fun applyConfiguration(configurationFilePath: String, lightAddress: String, port: Int?) {
val configString = FileUtil.readAllText(configurationFilePath)
TODO("Not yet implemented")
}
private suspend fun applyLightStatus(lightAddress: String, port: Int?, status: LightStatus){
val currentStatus = lightRepository.getLightStatus(lightAddress)
currentStatus.getNecessaryChanges(status)?.let { statusUpdate ->
lightRepository.setLightStatus(lightAddress, port, statusUpdate)
}
}
}

View File

@ -1,6 +1,6 @@
package fi.schro.data
import fi.schro.ui.LightPowerState
import fi.schro.ui.LightPowerStatus
import io.ktor.client.*
import io.ktor.client.request.*
import io.ktor.client.statement.*
@ -8,7 +8,6 @@ import io.ktor.http.*
import io.ktor.utils.io.core.*
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import platform.posix.stat
import kotlin.math.roundToInt
class ElgatoLightRepository(private val httpClient: HttpClient): LightRepository {
@ -73,7 +72,7 @@ data class ElgatoLight(
){
fun toLightStatus(): LightStatus {
return LightStatus(
powerState = on?.let { LightPowerState.fromInt(it) },
powerStatus = on?.let { LightPowerStatus.fromInt(it) },
brightness = brightness,
temperature = temperature?.let { convertElgatoTemperatureToKelvin(it) }
)
@ -82,7 +81,7 @@ data class ElgatoLight(
companion object {
fun fromLightStatus(status: LightStatus): ElgatoLight {
return ElgatoLight(
on = status.powerState?.intValue,
on = status.powerStatus?.intValue,
brightness = status.brightness,
temperature = status.temperature?.let { convertKelvinToElgatoTemperature(it) }
)
@ -90,9 +89,10 @@ data class ElgatoLight(
}
}
//TODO: these calculations seem weird, maybe they could be improved
private fun convertKelvinToElgatoTemperature(kelvinTemperature: Int): Int {
//TODO: implement real conversion
return 319
//based on: https://github.com/justinforlenza/keylight-control/blob/main/src/keylight.js
return (((kelvinTemperature - 1993300/201f) * 201f)/-4100f).roundToInt()
}
private fun convertElgatoTemperatureToKelvin(elgatoTemperature: Int): Int {

View File

@ -1,22 +1,37 @@
package fi.schro.data
import fi.schro.ui.LightPowerState
import fi.schro.ui.LightPowerStatus
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
interface LightRepository {
suspend fun setLightStatus(lightAddress: String, port: Int? = null, status: LightStatus)
suspend fun getLightStatus(lightAddress: String, port: Int? = null): LightStatus
}
@Serializable
data class LightStatus(
val powerState: LightPowerState?,
val brightness: Int?,
val temperature: Int?
@SerialName("power") val powerStatus: LightPowerStatus?,
@SerialName("brightness") val brightness: Int?,
@SerialName("temperature") val temperature: Int?
){
override fun toString(): String {
val stringList = mutableListOf<String>()
powerState?.let { stringList.add("status: ${powerState.stringValue}") }
powerStatus?.let { stringList.add("power: ${powerStatus.stringValue}") }
brightness?.let { stringList.add("brightness: $brightness") }
temperature?.let { stringList.add("temperature: $temperature") }
return stringList.joinToString(separator = "\n")
}
fun getNecessaryChanges(otherStatus: LightStatus): LightStatus? {
val statusUpdates = LightStatus(
powerStatus = if(powerStatus != otherStatus.powerStatus) otherStatus.powerStatus else null,
brightness = if(brightness != otherStatus.brightness) otherStatus.brightness else null,
temperature = if(temperature != otherStatus.temperature) otherStatus.temperature else null
)
return if(statusUpdates.powerStatus != null || statusUpdates.brightness != null || statusUpdates.temperature != null){
statusUpdates
} else null
}
}

View File

@ -1,5 +1,7 @@
package fi.schro.di
import fi.schro.data.ConfigurationRepository
import fi.schro.data.ConfigurationRepositoryImpl
import fi.schro.data.ElgatoLightRepository
import fi.schro.data.LightRepository
import fi.schro.ui.ApplyCommand
@ -18,6 +20,7 @@ val commandModule = module {
val dataModule = module {
single<LightRepository> { ElgatoLightRepository(get()) }
single<ConfigurationRepository> { ConfigurationRepositoryImpl(get()) }
}
val networkModule = module {

View File

@ -16,7 +16,7 @@ import org.koin.core.component.inject
const val ARG_TARGET_LAMP = "TARGET_LAMP"
const val ARG_CONFIGURATION_FILE = "CONFIGURATION_FILE"
class HappyCatCommand: CliktCommand(), KoinComponent {
class HappyCatCommand: CliktCommand(name = "hc", help = "A commandline utility to control your elgato keylight"), KoinComponent {
private val applyCommand: ApplyCommand by inject()
private val getCommand: GetCommand by inject()
private val setCommand: SetCommand by inject()
@ -48,12 +48,12 @@ class SetCommand(
it in 1000..10000
}
private val powerState: LightPowerState? by option("-p", "--powerstate", help = "The state to be set").enum<LightPowerState>()
private val powerStatus: LightPowerStatus? by option("-p", "--power", help = "The power status to be set").enum<LightPowerStatus>()
override fun run() {
val status = LightStatus(
powerState = powerState,
powerStatus = powerStatus,
brightness = brightness,
temperature = temperature
)
@ -86,12 +86,12 @@ class ApplyCommand: CliktCommand(name = "apply", help = "Applies the given confi
}
}
enum class LightPowerState(val stringValue: String, val intValue: Int) {
enum class LightPowerStatus(val stringValue: String, val intValue: Int) {
ON("ON", 1),
OFF("OFF", 0);
companion object {
fun fromInt(intValue: Int): LightPowerState? {
fun fromInt(intValue: Int): LightPowerStatus? {
return values().firstOrNull { it.intValue == intValue }
}
}

View File

@ -0,0 +1,34 @@
package fi.schro.util
import kotlinx.cinterop.ByteVar
import kotlinx.cinterop.allocArray
import kotlinx.cinterop.memScoped
import kotlinx.cinterop.toKString
import platform.posix.fclose
import platform.posix.fgets
import platform.posix.fopen
object FileUtil {
fun readAllText(filePath: String): String {
val returnBuffer = StringBuilder()
val file = fopen(filePath, "r") ?:
throw IllegalArgumentException("Cannot open input file $filePath")
try {
memScoped {
val readBufferLength = 64 * 1024
val buffer = allocArray<ByteVar>(readBufferLength)
var line = fgets(buffer, readBufferLength, file)?.toKString()
while (line != null) {
returnBuffer.append(line)
line = fgets(buffer, readBufferLength, file)?.toKString()
}
}
} finally {
fclose(file)
}
return returnBuffer.toString()
}
}