diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 727a8b4..fb7a69c 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -15,8 +15,8 @@ android { applicationId = "de.timklge.karooheadwind" minSdk = 26 targetSdk = 35 - versionCode = 12 - versionName = "1.2.4" + versionCode = 13 + versionName = "1.2.5" } signingConfigs { diff --git a/app/manifest.json b/app/manifest.json index 31276bb..18e5b70 100644 --- a/app/manifest.json +++ b/app/manifest.json @@ -3,9 +3,9 @@ "packageName": "de.timklge.karooheadwind", "iconUrl": "https://github.com/timklge/karoo-headwind/releases/latest/download/karoo-headwind.png", "latestApkUrl": "https://github.com/timklge/karoo-headwind/releases/latest/download/app-release.apk", - "latestVersion": "1.2.4", - "latestVersionCode": 12, + "latestVersion": "1.2.5", + "latestVersionCode": 13, "developer": "timklge", "description": "Provides headwind direction, wind speed and other weather data fields", - "releaseNotes": "Add sealevel pressure data type" + "releaseNotes": "Include more directions in wind direction data field, do not use streams for secondary data fields to work around issue in current karoo release" } \ No newline at end of file diff --git a/app/src/main/kotlin/de/timklge/karooheadwind/KarooHeadwindExtension.kt b/app/src/main/kotlin/de/timklge/karooheadwind/KarooHeadwindExtension.kt index a88db23..982e284 100644 --- a/app/src/main/kotlin/de/timklge/karooheadwind/KarooHeadwindExtension.kt +++ b/app/src/main/kotlin/de/timklge/karooheadwind/KarooHeadwindExtension.kt @@ -43,7 +43,7 @@ import kotlin.math.absoluteValue import kotlin.time.Duration.Companion.hours import kotlin.time.Duration.Companion.minutes -class KarooHeadwindExtension : KarooExtension("karoo-headwind", "1.2.4") { +class KarooHeadwindExtension : KarooExtension("karoo-headwind", "1.2.5") { companion object { const val TAG = "karoo-headwind" } diff --git a/app/src/main/kotlin/de/timklge/karooheadwind/datatypes/HeadwindDirectionDataType.kt b/app/src/main/kotlin/de/timklge/karooheadwind/datatypes/HeadwindDirectionDataType.kt index 8ef6d5d..1de55c4 100644 --- a/app/src/main/kotlin/de/timklge/karooheadwind/datatypes/HeadwindDirectionDataType.kt +++ b/app/src/main/kotlin/de/timklge/karooheadwind/datatypes/HeadwindDirectionDataType.kt @@ -42,45 +42,51 @@ class HeadwindDirectionDataType( ) : DataTypeImpl("karoo-headwind", "headwind") { private val glance = GlanceRemoteViews() - override fun startStream(emitter: Emitter) { - val job = CoroutineScope(Dispatchers.IO).launch { - karooSystem.getRelativeHeadingFlow(applicationContext) - .combine(applicationContext.streamCurrentWeatherData()) { headingResponse, data -> StreamData(headingResponse, data?.current?.windDirection, data?.current?.windSpeed) } - .combine(applicationContext.streamSettings(karooSystem)) { data, settings -> data.copy(settings = settings) } - .collect { streamData -> - val value = (streamData.headingResponse as? HeadingResponse.Value)?.diff + private fun streamValues(): Flow = flow { + karooSystem.getRelativeHeadingFlow(applicationContext) + .combine(applicationContext.streamCurrentWeatherData()) { headingResponse, data -> StreamData(headingResponse, data?.current?.windDirection, data?.current?.windSpeed) } + .combine(applicationContext.streamSettings(karooSystem)) { data, settings -> data.copy(settings = settings) } + .collect { streamData -> + val value = (streamData.headingResponse as? HeadingResponse.Value)?.diff - var returnValue = 0.0 - if (value == null || streamData.absoluteWindDirection == null || streamData.settings == null || streamData.windSpeed == null){ - var errorCode = 1.0 - var headingResponse = streamData.headingResponse + var returnValue = 0.0 + if (value == null || streamData.absoluteWindDirection == null || streamData.settings == null || streamData.windSpeed == null){ + var errorCode = 1.0 + var headingResponse = streamData.headingResponse - if (headingResponse is HeadingResponse.Value && (streamData.absoluteWindDirection == null || streamData.windSpeed == null)){ - headingResponse = HeadingResponse.NoWeatherData - } - - if (streamData.settings?.welcomeDialogAccepted == false){ - errorCode = ERROR_APP_NOT_SET_UP.toDouble() - } else if (headingResponse is HeadingResponse.NoGps){ - errorCode = ERROR_NO_GPS.toDouble() - } else { - errorCode = ERROR_NO_WEATHER_DATA.toDouble() - } - - returnValue = errorCode - } else { - var windDirection = when (streamData.settings.windDirectionIndicatorSetting){ - WindDirectionIndicatorSetting.HEADWIND_DIRECTION -> value - WindDirectionIndicatorSetting.WIND_DIRECTION -> streamData.absoluteWindDirection + 180 - } - - if (windDirection < 0) windDirection += 360 - - returnValue = windDirection + if (headingResponse is HeadingResponse.Value && (streamData.absoluteWindDirection == null || streamData.windSpeed == null)){ + headingResponse = HeadingResponse.NoWeatherData } - emitter.onNext(StreamState.Streaming(DataPoint(dataTypeId, mapOf(DataType.Field.SINGLE to returnValue)))) + if (streamData.settings?.welcomeDialogAccepted == false){ + errorCode = ERROR_APP_NOT_SET_UP.toDouble() + } else if (headingResponse is HeadingResponse.NoGps){ + errorCode = ERROR_NO_GPS.toDouble() + } else { + errorCode = ERROR_NO_WEATHER_DATA.toDouble() + } + + returnValue = errorCode + } else { + var windDirection = when (streamData.settings.windDirectionIndicatorSetting){ + WindDirectionIndicatorSetting.HEADWIND_DIRECTION -> value + WindDirectionIndicatorSetting.WIND_DIRECTION -> streamData.absoluteWindDirection + 180 + } + + if (windDirection < 0) windDirection += 360 + + returnValue = windDirection } + + emit(returnValue) + } + } + + override fun startStream(emitter: Emitter) { + val job = CoroutineScope(Dispatchers.IO).launch { + streamValues().collect { returnValue -> + emitter.onNext(StreamState.Streaming(DataPoint(dataTypeId, mapOf(DataType.Field.SINGLE to returnValue)))) + } } emitter.setCancellable { job.cancel() @@ -121,8 +127,8 @@ class HeadwindDirectionDataType( val flow = if (config.preview) { previewFlow() } else { - val directionFlow = karooSystem.streamDataFlow(dataTypeId).mapNotNull { (it as? StreamState.Streaming)?.dataPoint?.singleValue } - val speedFlow = karooSystem.streamDataFlow(DataType.dataTypeId("karoo-headwind", "userwindSpeed")).map { (it as? StreamState.Streaming)?.dataPoint?.singleValue } + val directionFlow = streamValues() + val speedFlow = UserWindSpeedDataType.streamValues(context, karooSystem) combine(directionFlow, speedFlow) { direction, speed -> DirectionAndSpeed(direction, speed) diff --git a/app/src/main/kotlin/de/timklge/karooheadwind/datatypes/TailwindAndRideSpeedDataType.kt b/app/src/main/kotlin/de/timklge/karooheadwind/datatypes/TailwindAndRideSpeedDataType.kt index 8b94884..eaeaeb6 100644 --- a/app/src/main/kotlin/de/timklge/karooheadwind/datatypes/TailwindAndRideSpeedDataType.kt +++ b/app/src/main/kotlin/de/timklge/karooheadwind/datatypes/TailwindAndRideSpeedDataType.kt @@ -24,10 +24,9 @@ import de.timklge.karooheadwind.streamSettings import de.timklge.karooheadwind.streamUserProfile import io.hammerhead.karooext.KarooSystemService import io.hammerhead.karooext.extension.DataTypeImpl -import io.hammerhead.karooext.internal.Emitter import io.hammerhead.karooext.internal.ViewEmitter -import io.hammerhead.karooext.models.DataPoint import io.hammerhead.karooext.models.DataType +import io.hammerhead.karooext.models.ShowCustomStreamState import io.hammerhead.karooext.models.StreamState import io.hammerhead.karooext.models.UpdateGraphicConfig import io.hammerhead.karooext.models.UserProfile @@ -71,19 +70,6 @@ class TailwindAndRideSpeedDataType( ) : DataTypeImpl("karoo-headwind", "tailwind-and-ride-speed") { private val glance = GlanceRemoteViews() - override fun startStream(emitter: Emitter) { - val job = CoroutineScope(Dispatchers.IO).launch { - karooSystem.getRelativeHeadingFlow(applicationContext) - .collect { diff -> - val value = (diff as? HeadingResponse.Value)?.diff ?: 0.0 - emitter.onNext(StreamState.Streaming(DataPoint(dataTypeId, mapOf(DataType.Field.SINGLE to value)))) - } - } - emitter.setCancellable { - job.cancel() - } - } - data class StreamData(val headingResponse: HeadingResponse, val absoluteWindDirection: Double?, val windSpeed: Double?, @@ -146,6 +132,8 @@ class TailwindAndRideSpeedDataType( } val viewJob = CoroutineScope(Dispatchers.IO).launch { + emitter.onNext(ShowCustomStreamState("", null)) + flow.collect { streamData -> Log.d(KarooHeadwindExtension.TAG, "Updating headwind direction view") diff --git a/app/src/main/kotlin/de/timklge/karooheadwind/datatypes/UserWindSpeedDataType.kt b/app/src/main/kotlin/de/timklge/karooheadwind/datatypes/UserWindSpeedDataType.kt index cca613b..abca4b5 100644 --- a/app/src/main/kotlin/de/timklge/karooheadwind/datatypes/UserWindSpeedDataType.kt +++ b/app/src/main/kotlin/de/timklge/karooheadwind/datatypes/UserWindSpeedDataType.kt @@ -16,8 +16,10 @@ import io.hammerhead.karooext.models.DataType import io.hammerhead.karooext.models.StreamState import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.filter +import kotlinx.coroutines.flow.flow import kotlinx.coroutines.launch import kotlin.math.cos @@ -28,8 +30,8 @@ class UserWindSpeedDataType( data class StreamData(val headingResponse: HeadingResponse, val weatherResponse: OpenMeteoCurrentWeatherResponse?, val settings: HeadwindSettings) - override fun startStream(emitter: Emitter) { - val job = CoroutineScope(Dispatchers.IO).launch { + companion object { + fun streamValues(context: Context, karooSystem: KarooSystemService): Flow = flow { karooSystem.getRelativeHeadingFlow(context) .combine(context.streamCurrentWeatherData()) { value, data -> value to data } .combine(context.streamSettings(karooSystem)) { (value, data), settings -> StreamData(value, data, settings) } @@ -41,24 +43,26 @@ class UserWindSpeedDataType( if (streamData.settings.windDirectionIndicatorTextSetting == WindDirectionIndicatorTextSetting.HEADWIND_SPEED){ val headwindSpeed = cos((windDirection + 180) * Math.PI / 180.0) * windSpeed - emitter.onNext( - StreamState.Streaming( - DataPoint( - dataTypeId, - mapOf(DataType.Field.SINGLE to headwindSpeed) - ) - ) - ) + emit(headwindSpeed) } else { - emitter.onNext( - StreamState.Streaming( - DataPoint( - dataTypeId, - mapOf(DataType.Field.SINGLE to windSpeed) - ) + emit(windSpeed) + } + } + } + } + + override fun startStream(emitter: Emitter) { + val job = CoroutineScope(Dispatchers.IO).launch { + streamValues(context, karooSystem) + .collect { value -> + emitter.onNext( + StreamState.Streaming( + DataPoint( + dataTypeId, + mapOf(DataType.Field.SINGLE to value) ) ) - } + ) } } diff --git a/app/src/main/kotlin/de/timklge/karooheadwind/datatypes/WeatherDataType.kt b/app/src/main/kotlin/de/timklge/karooheadwind/datatypes/WeatherDataType.kt index 625938b..94c9e95 100644 --- a/app/src/main/kotlin/de/timklge/karooheadwind/datatypes/WeatherDataType.kt +++ b/app/src/main/kotlin/de/timklge/karooheadwind/datatypes/WeatherDataType.kt @@ -28,6 +28,7 @@ import io.hammerhead.karooext.internal.Emitter import io.hammerhead.karooext.internal.ViewEmitter import io.hammerhead.karooext.models.DataPoint import io.hammerhead.karooext.models.DataType +import io.hammerhead.karooext.models.ShowCustomStreamState import io.hammerhead.karooext.models.StreamState import io.hammerhead.karooext.models.UpdateGraphicConfig import io.hammerhead.karooext.models.UserProfile @@ -57,22 +58,6 @@ class WeatherDataType( val timeFormatter = DateTimeFormatter.ofPattern("HH:mm").withZone(ZoneId.systemDefault()) } - // FIXME: Remove. Currently, the data field will permanently show "no sensor" if no data stream is provided - override fun startStream(emitter: Emitter) { - val job = CoroutineScope(Dispatchers.IO).launch { - val currentWeatherData = applicationContext.streamCurrentWeatherData() - - currentWeatherData - .collect { data -> - Log.d(KarooHeadwindExtension.TAG, "Wind code: ${data?.current?.weatherCode}") - emitter.onNext(StreamState.Streaming(DataPoint(dataTypeId, mapOf(DataType.Field.SINGLE to (data?.current?.weatherCode?.toDouble() ?: 0.0))))) - } - } - emitter.setCancellable { - job.cancel() - } - } - data class StreamData(val data: OpenMeteoCurrentWeatherResponse?, val settings: HeadwindSettings, val profile: UserProfile? = null, val headingResponse: HeadingResponse? = null) @@ -113,8 +98,9 @@ class WeatherDataType( } val viewJob = CoroutineScope(Dispatchers.IO).launch { - dataFlow - .collect { (data, settings, userProfile, headingResponse) -> + emitter.onNext(ShowCustomStreamState("", null)) + + dataFlow.collect { (data, settings, userProfile, headingResponse) -> Log.d(KarooHeadwindExtension.TAG, "Updating weather view") if (data == null){ diff --git a/app/src/main/kotlin/de/timklge/karooheadwind/datatypes/WeatherForecastDataType.kt b/app/src/main/kotlin/de/timklge/karooheadwind/datatypes/WeatherForecastDataType.kt index 0fcd683..f9d43d1 100644 --- a/app/src/main/kotlin/de/timklge/karooheadwind/datatypes/WeatherForecastDataType.kt +++ b/app/src/main/kotlin/de/timklge/karooheadwind/datatypes/WeatherForecastDataType.kt @@ -45,6 +45,7 @@ import io.hammerhead.karooext.internal.Emitter import io.hammerhead.karooext.internal.ViewEmitter import io.hammerhead.karooext.models.DataPoint import io.hammerhead.karooext.models.DataType +import io.hammerhead.karooext.models.ShowCustomStreamState import io.hammerhead.karooext.models.StreamState import io.hammerhead.karooext.models.UpdateGraphicConfig import io.hammerhead.karooext.models.UserProfile @@ -97,22 +98,6 @@ class WeatherForecastDataType( val timeFormatter = DateTimeFormatter.ofPattern("HH:mm").withZone(ZoneId.systemDefault()) } - // FIXME: Remove. Currently, the data field will permanently show "no sensor" if no data stream is provided - override fun startStream(emitter: Emitter) { - val job = CoroutineScope(Dispatchers.IO).launch { - val currentWeatherData = applicationContext.streamCurrentWeatherData() - - currentWeatherData - .collect { data -> - Log.d(KarooHeadwindExtension.TAG, "Wind code: ${data?.current?.weatherCode}") - emitter.onNext(StreamState.Streaming(DataPoint(dataTypeId, mapOf(DataType.Field.SINGLE to (data?.current?.weatherCode?.toDouble() ?: 0.0))))) - } - } - emitter.setCancellable { - job.cancel() - } - } - data class StreamData(val data: OpenMeteoCurrentWeatherResponse?, val settings: HeadwindSettings, val widgetSettings: HeadwindWidgetSettings? = null, val profile: UserProfile? = null, val headingResponse: HeadingResponse? = null) @@ -167,6 +152,8 @@ class WeatherForecastDataType( } val viewJob = CoroutineScope(Dispatchers.IO).launch { + emitter.onNext(ShowCustomStreamState("", null)) + dataFlow.collect { (data, settings, widgetSettings, userProfile, headingResponse) -> Log.d(KarooHeadwindExtension.TAG, "Updating weather forecast view") diff --git a/app/src/main/kotlin/de/timklge/karooheadwind/datatypes/WindDirectionDataType.kt b/app/src/main/kotlin/de/timklge/karooheadwind/datatypes/WindDirectionDataType.kt index 20df2d8..f074192 100644 --- a/app/src/main/kotlin/de/timklge/karooheadwind/datatypes/WindDirectionDataType.kt +++ b/app/src/main/kotlin/de/timklge/karooheadwind/datatypes/WindDirectionDataType.kt @@ -21,6 +21,7 @@ import de.timklge.karooheadwind.OpenMeteoCurrentWeatherResponse import de.timklge.karooheadwind.streamDataFlow import io.hammerhead.karooext.KarooSystemService import io.hammerhead.karooext.internal.ViewEmitter +import io.hammerhead.karooext.models.ShowCustomStreamState import io.hammerhead.karooext.models.StreamState import io.hammerhead.karooext.models.UpdateGraphicConfig import io.hammerhead.karooext.models.ViewConfig @@ -69,6 +70,8 @@ class WindDirectionDataType(val karooSystem: KarooSystemService, context: Contex } val viewJob = CoroutineScope(Dispatchers.IO).launch { + emitter.onNext(ShowCustomStreamState("", null)) + val flow = if (config.preview){ previewFlow() } else { @@ -77,10 +80,6 @@ class WindDirectionDataType(val karooSystem: KarooSystemService, context: Contex } flow - .onCompletion { - val result = glance.compose(context, DpSize.Unspecified) { } - emitter.updateView(result.remoteViews) - } .collect { windBearing -> val windCardinalDirectionIndex = ((windBearing % 360) / 22.5).roundToInt() % 16