102 lines
3.6 KiB
Kotlin
102 lines
3.6 KiB
Kotlin
package dev.coffeeco.homenative.data
|
|
|
|
import io.ktor.client.HttpClient
|
|
import io.ktor.client.call.body
|
|
import io.ktor.client.engine.okhttp.OkHttp
|
|
import io.ktor.client.plugins.DefaultRequest
|
|
import io.ktor.client.plugins.contentnegotiation.ContentNegotiation
|
|
import io.ktor.client.plugins.websocket.WebSockets
|
|
import io.ktor.client.plugins.websocket.receiveDeserialized
|
|
import io.ktor.client.plugins.websocket.sendSerialized
|
|
import io.ktor.client.plugins.websocket.webSocket
|
|
import io.ktor.client.request.get
|
|
import io.ktor.client.request.header
|
|
import io.ktor.client.request.post
|
|
import io.ktor.client.request.setBody
|
|
import io.ktor.client.statement.HttpResponse
|
|
import io.ktor.http.ContentType
|
|
import io.ktor.http.HttpHeaders
|
|
import io.ktor.http.contentType
|
|
import io.ktor.serialization.kotlinx.KotlinxWebsocketSerializationConverter
|
|
import io.ktor.serialization.kotlinx.json.json
|
|
import kotlinx.coroutines.CoroutineScope
|
|
import kotlinx.coroutines.GlobalScope
|
|
import kotlinx.coroutines.launch
|
|
import kotlinx.serialization.json.Json
|
|
|
|
class HomeClient(private val baseUrl: String, private val accessToken: String) {
|
|
private val client: HttpClient = HttpClient(OkHttp) {
|
|
install(WebSockets) {
|
|
contentConverter = KotlinxWebsocketSerializationConverter(Json)
|
|
}
|
|
install(ContentNegotiation) {
|
|
json(Json { // isLenient = true
|
|
// useArrayPolymorphism = true
|
|
allowStructuredMapKeys = true
|
|
ignoreUnknownKeys = true // explicitNulls = false
|
|
// namingStrategy = JsonNamingStrategy.SnakeCase
|
|
})
|
|
}
|
|
|
|
install(DefaultRequest) {
|
|
header(HttpHeaders.Authorization, "Bearer $accessToken")
|
|
}
|
|
}
|
|
|
|
suspend fun apiStatus(): HttpResponse {
|
|
val res = client.get("$baseUrl/api/")
|
|
return res
|
|
}
|
|
|
|
private suspend fun getState(): List<StatesResItem> {
|
|
val res = client.get("$baseUrl/api/states")
|
|
val body = res.body<List<StatesResItem>>()
|
|
|
|
return body
|
|
}
|
|
|
|
suspend fun getUsefulState(): List<StatesResItem> {
|
|
val all = getState()
|
|
val filtered = all.filter { i -> i.entityId.startsWith("switch.") }
|
|
return filtered
|
|
}
|
|
|
|
private suspend fun updateService(
|
|
entityId: String, domain: String, service: String
|
|
): HttpResponse {
|
|
return client.post("$baseUrl/api/services/$domain/$service") {
|
|
contentType(ContentType.Application.Json)
|
|
setBody(PostServiceBody(entityId))
|
|
}
|
|
}
|
|
|
|
suspend fun updateSwitch(entityId: String, service: String) {
|
|
if (service !in switchServices) {
|
|
throw Exception("Illegal/unknown service was specified")
|
|
}
|
|
val res = updateService(entityId, "switch", service)
|
|
}
|
|
|
|
fun connect(coroutineScope: CoroutineScope) {
|
|
GlobalScope.launch {
|
|
client.webSocket(
|
|
"${baseUrl.replace("http", "ws")}/api/websocket"
|
|
) {
|
|
var iteratingNumber = 0
|
|
var isReady = false
|
|
while (true) {
|
|
val data = receiveDeserialized<WebSocketIncoming>()
|
|
if (data.type == "auth_required") sendSerialized(WSAuth("auth", accessToken))
|
|
if (data.type == "auth_ok") {
|
|
isReady = true
|
|
sendSerialized(WSSubscribe(iteratingNumber, "state_changed"))
|
|
}
|
|
println(data)
|
|
iteratingNumber++
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
val switchServices = listOf("turn_off", "turn_on", "toggle")
|