Skip to content

Commit

Permalink
Speed up device controls/Wear OS loading by doing network async (#2636)
Browse files Browse the repository at this point in the history
* Speed up loading device controls by running network async

 - Speed up loading the device controls menu and initial controls by launching all requests in an async block, which allows the server to respond out of order
 - For individual controls, only start listening for changes once we have provided initial controls

* Speed up Wear OS cold boot by running network async

 - Speed up a cold boot of the Wear OS app by launching all network requests in an async block, which allows the server to respond out of order
  • Loading branch information
jpelgrom authored Jun 26, 2022
1 parent f91c469 commit 71b1fe1
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import io.homeassistant.companion.android.common.data.websocket.impl.entities.En
import io.homeassistant.companion.android.util.RegistriesDataHandler
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.cancel
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
Expand Down Expand Up @@ -67,11 +68,16 @@ class HaControlsProviderService : ControlsProviderService() {
return Flow.Publisher { subscriber ->
ioScope.launch {
try {
val areaRegistry = webSocketRepository.getAreaRegistry()
val deviceRegistry = webSocketRepository.getDeviceRegistry()
val entityRegistry = webSocketRepository.getEntityRegistry()
val getAreaRegistry = async { webSocketRepository.getAreaRegistry() }
val getDeviceRegistry = async { webSocketRepository.getDeviceRegistry() }
val getEntityRegistry = async { webSocketRepository.getEntityRegistry() }
val getEntities = async { integrationRepository.getEntities() }

val areaRegistry = getAreaRegistry.await()
val deviceRegistry = getDeviceRegistry.await()
val entityRegistry = getEntityRegistry.await()
val entities = getEntities.await()

val entities = integrationRepository.getEntities()
val areaForEntity = entities.orEmpty().associate {
it.entityId to RegistriesDataHandler.getAreaForEntity(it.entityId, areaRegistry, deviceRegistry, entityRegistry)
}
Expand Down Expand Up @@ -109,16 +115,12 @@ class HaControlsProviderService : ControlsProviderService() {
override fun request(n: Long) {
Log.d(TAG, "request $n")
ioScope.launch {
val entityFlow = integrationRepository.getEntityUpdates()
val areaRegistryFlow = webSocketRepository.getAreaRegistryUpdates()
val deviceRegistryFlow = webSocketRepository.getDeviceRegistryUpdates()
val entityRegistryFlow = webSocketRepository.getEntityRegistryUpdates()
// Load up initial values
// This should use the cached values that we should store in the DB.
// For now we'll use the rest API
var areaRegistry = webSocketRepository.getAreaRegistry()
var deviceRegistry = webSocketRepository.getDeviceRegistry()
var entityRegistry = webSocketRepository.getEntityRegistry()
val getAreaRegistry = async { webSocketRepository.getAreaRegistry() }
val getDeviceRegistry = async { webSocketRepository.getDeviceRegistry() }
val getEntityRegistry = async { webSocketRepository.getEntityRegistry() }
val entities = mutableMapOf<String, Entity<Map<String, Any>>>()
controlIds.forEach {
try {
Expand All @@ -133,11 +135,15 @@ class HaControlsProviderService : ControlsProviderService() {
Log.e(TAG, "Unable to get $it from Home Assistant, caught exception.", e)
}
}
var areaRegistry = getAreaRegistry.await()
var deviceRegistry = getDeviceRegistry.await()
var entityRegistry = getEntityRegistry.await()

sendEntitiesToSubscriber(subscriber, entities, areaRegistry, deviceRegistry, entityRegistry)

// Listen for the state changed events.
webSocketScope.launch {
entityFlow?.collect {
integrationRepository.getEntityUpdates()?.collect {
if (controlIds.contains(it.entityId)) {
val control = domainToHaControl[it.domain]?.createControl(
applicationContext,
Expand All @@ -149,19 +155,19 @@ class HaControlsProviderService : ControlsProviderService() {
}
}
webSocketScope.launch {
areaRegistryFlow?.collect {
webSocketRepository.getAreaRegistryUpdates()?.collect {
areaRegistry = webSocketRepository.getAreaRegistry()
sendEntitiesToSubscriber(subscriber, entities, areaRegistry, deviceRegistry, entityRegistry)
}
}
webSocketScope.launch {
deviceRegistryFlow?.collect {
webSocketRepository.getDeviceRegistryUpdates()?.collect {
deviceRegistry = webSocketRepository.getDeviceRegistry()
sendEntitiesToSubscriber(subscriber, entities, areaRegistry, deviceRegistry, entityRegistry)
}
}
webSocketScope.launch {
entityRegistryFlow?.collect { event ->
webSocketRepository.getEntityRegistryUpdates()?.collect { event ->
if (event.action == "update" && controlIds.contains(event.entityId)) {
entityRegistry = webSocketRepository.getEntityRegistry()
sendEntitiesToSubscriber(subscriber, entities, areaRegistry, deviceRegistry, entityRegistry)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import io.homeassistant.companion.android.database.sensor.SensorDao
import io.homeassistant.companion.android.database.wear.FavoritesDao
import io.homeassistant.companion.android.database.wear.getAllFlow
import io.homeassistant.companion.android.util.RegistriesDataHandler
import kotlinx.coroutines.async
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.launch
import javax.inject.Inject
Expand Down Expand Up @@ -124,13 +125,17 @@ class MainViewModel @Inject constructor(
try {
// Load initial state
loadingState.value = LoadingState.LOADING
homePresenter.getAreaRegistry()?.let {
areaRegistry = it
val getAreaRegistry = async { homePresenter.getAreaRegistry() }
val getDeviceRegistry = async { homePresenter.getDeviceRegistry() }
val getEntityRegistry = async { homePresenter.getEntityRegistry() }
val getEntities = async { homePresenter.getEntities() }

areaRegistry = getAreaRegistry.await()?.also {
areas.addAll(it)
}
deviceRegistry = homePresenter.getDeviceRegistry()
entityRegistry = homePresenter.getEntityRegistry()
homePresenter.getEntities()?.forEach {
deviceRegistry = getDeviceRegistry.await()
entityRegistry = getEntityRegistry.await()
getEntities.await()?.forEach {
if (supportedDomains().contains(it.domain)) {
entities[it.entityId] = it
}
Expand Down

0 comments on commit 71b1fe1

Please sign in to comment.