add support for setting temperature, start apply command, refactor
parent
6451ede58a
commit
ddd7fb7ed6
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue