diff --git a/app/src/main/kotlin/de/timklge/karooheadwind/datatypes/BaseDataType.kt b/app/src/main/kotlin/de/timklge/karooheadwind/datatypes/BaseDataType.kt index d0d101e..07ff588 100644 --- a/app/src/main/kotlin/de/timklge/karooheadwind/datatypes/BaseDataType.kt +++ b/app/src/main/kotlin/de/timklge/karooheadwind/datatypes/BaseDataType.kt @@ -4,16 +4,21 @@ import android.content.Context import android.util.Log import de.timklge.karooheadwind.KarooHeadwindExtension import de.timklge.karooheadwind.streamCurrentWeatherData +import de.timklge.karooheadwind.streamUserProfile import de.timklge.karooheadwind.throttle import de.timklge.karooheadwind.weatherprovider.WeatherData 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.StreamState +import io.hammerhead.karooext.models.UpdateGraphicConfig +import io.hammerhead.karooext.models.ViewConfig import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.filterNotNull import kotlinx.coroutines.launch @@ -24,15 +29,17 @@ abstract class BaseDataType( ) : DataTypeImpl("karoo-headwind", dataTypeId) { abstract fun getValue(data: WeatherData): Double? + open fun getFormatDataType(): String? = null + override fun startStream(emitter: Emitter) { Log.d(KarooHeadwindExtension.TAG, "start $dataTypeId stream") val job = CoroutineScope(Dispatchers.IO).launch { val currentWeatherData = applicationContext.streamCurrentWeatherData(karooSystemService) + val userProfile = karooSystemService.streamUserProfile() val refreshRate = karooSystemService.getRefreshRateInMilliseconds(applicationContext) - currentWeatherData - .filterNotNull() + currentWeatherData.filterNotNull() .throttle(refreshRate) .collect { data -> val value = getValue(data) @@ -50,4 +57,12 @@ abstract class BaseDataType( job.cancel() } } + + override fun startView(context: Context, config: ViewConfig, emitter: ViewEmitter) { + Log.d(KarooHeadwindExtension.TAG, "Starting $dataTypeId view with $emitter") + + if (getFormatDataType() != null){ + emitter.onNext(UpdateGraphicConfig(formatDataTypeId = getFormatDataType())) + } + } } diff --git a/app/src/main/kotlin/de/timklge/karooheadwind/datatypes/ForecastDataType.kt b/app/src/main/kotlin/de/timklge/karooheadwind/datatypes/ForecastDataType.kt index 2bdbb4e..94fe006 100644 --- a/app/src/main/kotlin/de/timklge/karooheadwind/datatypes/ForecastDataType.kt +++ b/app/src/main/kotlin/de/timklge/karooheadwind/datatypes/ForecastDataType.kt @@ -37,6 +37,9 @@ import de.timklge.karooheadwind.streamUpcomingRoute import de.timklge.karooheadwind.streamUserProfile import de.timklge.karooheadwind.streamWidgetSettings import de.timklge.karooheadwind.throttle +import de.timklge.karooheadwind.util.celciusInUserUnit +import de.timklge.karooheadwind.util.millimetersInUserUnit +import de.timklge.karooheadwind.util.msInUserUnit import de.timklge.karooheadwind.weatherprovider.WeatherData import de.timklge.karooheadwind.weatherprovider.WeatherDataForLocation import de.timklge.karooheadwind.weatherprovider.WeatherDataResponse @@ -311,11 +314,11 @@ abstract class ForecastDataType(private val karooSystem: KarooSystemService, typ arrowBitmap = baseBitmap, current = interpretation, windBearing = data.current.windDirection.roundToInt(), - windSpeed = data.current.windSpeed.roundToInt(), - windGusts = data.current.windGusts.roundToInt(), - precipitation = data.current.precipitation, + windSpeed = msInUserUnit(data.current.windSpeed, settingsAndProfile.isImperial).roundToInt(), + windGusts = msInUserUnit(data.current.windGusts, settingsAndProfile.isImperial).roundToInt(), + precipitation = millimetersInUserUnit(data.current.precipitation, settingsAndProfile.isImperial), precipitationProbability = null, - temperature = data.current.temperature.roundToInt(), + temperature = celciusInUserUnit(data.current.temperature, settingsAndProfile.isImperialTemperature).roundToInt(), temperatureUnit = if (settingsAndProfile.isImperialTemperature) TemperatureUnit.FAHRENHEIT else TemperatureUnit.CELSIUS, timeLabel = formattedTime, dateLabel = if (hasNewDate) formattedDate else null, @@ -337,11 +340,11 @@ abstract class ForecastDataType(private val karooSystem: KarooSystemService, typ arrowBitmap = baseBitmap, current = interpretation, windBearing = weatherData?.windDirection?.roundToInt() ?: 0, - windSpeed = weatherData?.windSpeed?.roundToInt() ?: 0, - windGusts = weatherData?.windGusts?.roundToInt() ?: 0, - precipitation = weatherData?.precipitation ?: 0.0, + windSpeed = msInUserUnit(weatherData?.windSpeed ?: 0.0, settingsAndProfile.isImperial).roundToInt(), + windGusts = msInUserUnit(weatherData?.windGusts ?: 0.0, settingsAndProfile.isImperial).roundToInt(), + precipitation = millimetersInUserUnit(weatherData?.precipitation ?: 0.0, settingsAndProfile.isImperial), precipitationProbability = weatherData?.precipitationProbability?.toInt(), - temperature = weatherData?.temperature?.roundToInt() ?: 0, + temperature = celciusInUserUnit(weatherData?.temperature ?: 0.0, settingsAndProfile.isImperialTemperature).roundToInt(), temperatureUnit = if (settingsAndProfile.isImperialTemperature) TemperatureUnit.FAHRENHEIT else TemperatureUnit.CELSIUS, timeLabel = formattedTime, dateLabel = if (hasNewDate) formattedDate else null, 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 9dae1db..0133b53 100644 --- a/app/src/main/kotlin/de/timklge/karooheadwind/datatypes/HeadwindDirectionDataType.kt +++ b/app/src/main/kotlin/de/timklge/karooheadwind/datatypes/HeadwindDirectionDataType.kt @@ -14,7 +14,9 @@ import de.timklge.karooheadwind.getRelativeHeadingFlow import de.timklge.karooheadwind.streamCurrentWeatherData import de.timklge.karooheadwind.streamDatatypeIsVisible import de.timklge.karooheadwind.streamSettings +import de.timklge.karooheadwind.streamUserProfile import de.timklge.karooheadwind.throttle +import de.timklge.karooheadwind.util.msInUserUnit import io.hammerhead.karooext.KarooSystemService import io.hammerhead.karooext.extension.DataTypeImpl import io.hammerhead.karooext.internal.Emitter @@ -24,6 +26,7 @@ import io.hammerhead.karooext.models.DataType import io.hammerhead.karooext.models.HardwareType import io.hammerhead.karooext.models.StreamState import io.hammerhead.karooext.models.UpdateGraphicConfig +import io.hammerhead.karooext.models.UserProfile import io.hammerhead.karooext.models.ViewConfig import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers @@ -63,7 +66,7 @@ class HeadwindDirectionDataType( val value = (streamData.headingResponse as? HeadingResponse.Value)?.diff var returnValue = 0.0 - if (value == null || streamData.absoluteWindDirection == null || streamData.settings == null || streamData.windSpeed == null){ + if (value == null || streamData.absoluteWindDirection == null || streamData.windSpeed == null){ var errorCode = 1.0 var headingResponse = streamData.headingResponse @@ -71,7 +74,7 @@ class HeadwindDirectionDataType( headingResponse = HeadingResponse.NoWeatherData } - if (streamData.settings?.welcomeDialogAccepted == false){ + if (streamData.settings.welcomeDialogAccepted == false){ errorCode = ERROR_APP_NOT_SET_UP.toDouble() } else if (headingResponse is HeadingResponse.NoGps){ errorCode = ERROR_NO_GPS.toDouble() @@ -106,7 +109,12 @@ class HeadwindDirectionDataType( } } - data class DirectionAndSpeed(val bearing: Double, val speed: Double?, val isVisible: Boolean) + data class DirectionAndSpeed( + val bearing: Double, + val speed: Double?, + val isVisible: Boolean, + val isImperial: Boolean + ) private fun previewFlow(): Flow { return flow { @@ -114,7 +122,12 @@ class HeadwindDirectionDataType( val bearing = (0..360).random().toDouble() val windSpeed = (0..20).random() - emit(DirectionAndSpeed(bearing, windSpeed.toDouble(), true)) + emit(DirectionAndSpeed( + bearing, + windSpeed.toDouble(), + true, + true + )) delay(2_000) } @@ -144,8 +157,8 @@ class HeadwindDirectionDataType( emitAll(UserWindSpeedDataType.streamValues(context, karooSystem)) } - combine(directionFlow, speedFlow, karooSystem.streamDatatypeIsVisible(dataTypeId)) { direction, speed, isVisible -> - DirectionAndSpeed(direction, speed, isVisible) + combine(directionFlow, speedFlow, karooSystem.streamDatatypeIsVisible(dataTypeId), karooSystem.streamUserProfile()) { direction, speed, isVisible, profile -> + DirectionAndSpeed(direction, speed, isVisible, profile.preferredUnit.distance == UserProfile.PreferredUnit.UnitType.IMPERIAL) } } @@ -162,14 +175,15 @@ class HeadwindDirectionDataType( } val windDirection = streamData.bearing - val windSpeed = streamData.speed + val windSpeed = streamData.speed ?: 0.0 + val windSpeedUserUnit = msInUserUnit(windSpeed, streamData.isImperial) val result = glance.compose(context, DpSize.Unspecified) { HeadwindDirection( baseBitmap, windDirection.roundToInt(), config.textSize, - windSpeed?.toInt()?.toString() ?: "", + windSpeed.roundToInt().toString(), preview = config.preview, wideMode = false ) diff --git a/app/src/main/kotlin/de/timklge/karooheadwind/datatypes/HeadwindSpeedDataType.kt b/app/src/main/kotlin/de/timklge/karooheadwind/datatypes/HeadwindSpeedDataType.kt index 03abc3e..b0d834f 100644 --- a/app/src/main/kotlin/de/timklge/karooheadwind/datatypes/HeadwindSpeedDataType.kt +++ b/app/src/main/kotlin/de/timklge/karooheadwind/datatypes/HeadwindSpeedDataType.kt @@ -11,9 +11,12 @@ import de.timklge.karooheadwind.throttle 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.StreamState +import io.hammerhead.karooext.models.UpdateGraphicConfig +import io.hammerhead.karooext.models.ViewConfig import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.combine @@ -49,5 +52,9 @@ class HeadwindSpeedDataType( job.cancel() } } + + override fun startView(context: Context, config: ViewConfig, emitter: ViewEmitter) { + emitter.onNext(UpdateGraphicConfig(formatDataTypeId = DataType.Type.SPEED)) + } } diff --git a/app/src/main/kotlin/de/timklge/karooheadwind/datatypes/PrecipitationDataType.kt b/app/src/main/kotlin/de/timklge/karooheadwind/datatypes/PrecipitationDataType.kt index c983104..0a14010 100644 --- a/app/src/main/kotlin/de/timklge/karooheadwind/datatypes/PrecipitationDataType.kt +++ b/app/src/main/kotlin/de/timklge/karooheadwind/datatypes/PrecipitationDataType.kt @@ -1,11 +1,13 @@ package de.timklge.karooheadwind.datatypes import android.content.Context +import de.timklge.karooheadwind.util.millimetersInUserUnit import de.timklge.karooheadwind.weatherprovider.WeatherData import io.hammerhead.karooext.KarooSystemService +import io.hammerhead.karooext.models.UserProfile class PrecipitationDataType(karooSystemService: KarooSystemService, context: Context) : BaseDataType(karooSystemService, context, "precipitation"){ override fun getValue(data: WeatherData): Double { - return data.precipitation + return millimetersInUserUnit(data.precipitation, userProfile.preferredUnit.distance == UserProfile.PreferredUnit.UnitType.IMPERIAL) } } \ No newline at end of file diff --git a/app/src/main/kotlin/de/timklge/karooheadwind/datatypes/RelativeGradeDataType.kt b/app/src/main/kotlin/de/timklge/karooheadwind/datatypes/RelativeGradeDataType.kt index 9dffc65..55a8df4 100644 --- a/app/src/main/kotlin/de/timklge/karooheadwind/datatypes/RelativeGradeDataType.kt +++ b/app/src/main/kotlin/de/timklge/karooheadwind/datatypes/RelativeGradeDataType.kt @@ -129,29 +129,8 @@ class RelativeGradeDataType(private val karooSystemService: KarooSystemService, val refreshRate = karooSystemService.getRefreshRateInMilliseconds(context) - val windSpeedFlow = combine(context.streamSettings(karooSystemService), karooSystemService.streamUserProfile(), context.streamCurrentWeatherData(karooSystemService).filterNotNull()) { settings, profile, weatherData -> - val isOpenMeteo = settings.weatherProvider == WeatherDataProvider.OPEN_METEO - val profileIsImperial = profile.preferredUnit.distance == UserProfile.PreferredUnit.UnitType.IMPERIAL - - if (isOpenMeteo) { - if (profileIsImperial) { // OpenMeteo returns wind speed in mph - val windSpeedInMilesPerHour = weatherData.windSpeed - - windSpeedInMilesPerHour * 0.44704 - } else { // Wind speed reported by openmeteo is in km/h - val windSpeedInKmh = weatherData.windSpeed - - windSpeedInKmh * 0.277778 - } - } else { - if (profileIsImperial) { // OpenWeatherMap returns wind speed in mph - val windSpeedInMilesPerHour = weatherData.windSpeed - - windSpeedInMilesPerHour * 0.44704 - } else { // Wind speed reported by openweathermap is in m/s - weatherData.windSpeed - } - } + val windSpeedFlow = context.streamCurrentWeatherData(karooSystemService).filterNotNull().map { weatherData -> + weatherData.windSpeed } data class StreamValues( 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 5b3dbe7..c86f383 100644 --- a/app/src/main/kotlin/de/timklge/karooheadwind/datatypes/TailwindAndRideSpeedDataType.kt +++ b/app/src/main/kotlin/de/timklge/karooheadwind/datatypes/TailwindAndRideSpeedDataType.kt @@ -25,6 +25,7 @@ import de.timklge.karooheadwind.streamDatatypeIsVisible import de.timklge.karooheadwind.streamSettings import de.timklge.karooheadwind.streamUserProfile import de.timklge.karooheadwind.throttle +import de.timklge.karooheadwind.util.msInUserUnit import de.timklge.karooheadwind.weatherprovider.WeatherData import io.hammerhead.karooext.KarooSystemService import io.hammerhead.karooext.extension.DataTypeImpl @@ -133,11 +134,7 @@ class TailwindAndRideSpeedDataType( val absoluteWindDirection = weatherData?.windDirection val windSpeed = weatherData?.windSpeed val gustSpeed = weatherData?.windGusts - val rideSpeed = if (isImperial){ - rideSpeedInMs * 2.23694 - } else { - rideSpeedInMs * 3.6 - } + val rideSpeed = rideSpeedInMs StreamData(headingResponse, absoluteWindDirection, windSpeed, settings, rideSpeed = rideSpeed, isImperial = isImperial, gustSpeed = gustSpeed, isVisible = isVisible) } @@ -172,12 +169,17 @@ class TailwindAndRideSpeedDataType( val text = streamData.rideSpeed?.let { String.format(Locale.current.platformLocale, "%.1f", it) } ?: "" val wideMode = config.gridSize.first == 60 + + val gustSpeedInUserUnit = msInUserUnit(streamData.gustSpeed ?: 0.0, streamData.isImperial) + val gustSpeedAddon = if (wideMode) { - "-${streamData.gustSpeed?.roundToInt() ?: 0}" + "-${gustSpeedInUserUnit.roundToInt()}" } else { "" } + val windSpeedUserUnit = msInUserUnit(windSpeed, streamData.isImperial) + val subtextWithSign = when (streamData.settings.windDirectionIndicatorTextSetting) { WindDirectionIndicatorTextSetting.HEADWIND_SPEED -> { val headwindSpeed = cos( (windDirection + 180) * Math.PI / 180.0) * windSpeed @@ -186,9 +188,12 @@ class TailwindAndRideSpeedDataType( val sign = if (headwindSpeed < 0) "+" else { if (headwindSpeed > 0) "-" else "" } - "$sign${headwindSpeed.roundToInt().absoluteValue} ${windSpeed.roundToInt()}${gustSpeedAddon}" + + val headwindSpeedUserUnit = msInUserUnit(headwindSpeed, streamData.isImperial) + + "$sign${headwindSpeedUserUnit.roundToInt().absoluteValue} ${windSpeedUserUnit.roundToInt()}${gustSpeedAddon}" } - WindDirectionIndicatorTextSetting.WIND_SPEED -> "${windSpeed.roundToInt()}${gustSpeedAddon}" + WindDirectionIndicatorTextSetting.WIND_SPEED -> "${windSpeedUserUnit.roundToInt()}${gustSpeedAddon}" WindDirectionIndicatorTextSetting.NONE -> "" } @@ -197,11 +202,7 @@ class TailwindAndRideSpeedDataType( if (streamData.settings.windDirectionIndicatorSetting == WindDirectionIndicatorSetting.HEADWIND_DIRECTION) { val headwindSpeed = cos( (windDirection + 180) * Math.PI / 180.0) * windSpeed - val windSpeedInKmh = if (streamData.isImperial == true){ - headwindSpeed / 2.23694 * 3.6 - } else { - headwindSpeed - } + val windSpeedInKmh = headwindSpeed * 3.6 dayColor = interpolateWindColor(windSpeedInKmh, false, context) nightColor = interpolateWindColor(windSpeedInKmh, true, context) } diff --git a/app/src/main/kotlin/de/timklge/karooheadwind/datatypes/TailwindDataType.kt b/app/src/main/kotlin/de/timklge/karooheadwind/datatypes/TailwindDataType.kt index 6e41cbc..fc9782a 100644 --- a/app/src/main/kotlin/de/timklge/karooheadwind/datatypes/TailwindDataType.kt +++ b/app/src/main/kotlin/de/timklge/karooheadwind/datatypes/TailwindDataType.kt @@ -21,6 +21,7 @@ import de.timklge.karooheadwind.streamDatatypeIsVisible import de.timklge.karooheadwind.streamSettings import de.timklge.karooheadwind.streamUserProfile import de.timklge.karooheadwind.throttle +import de.timklge.karooheadwind.util.msInUserUnit import de.timklge.karooheadwind.weatherprovider.WeatherData import io.hammerhead.karooext.KarooSystemService import io.hammerhead.karooext.extension.DataTypeImpl @@ -120,13 +121,8 @@ class TailwindDataType( val absoluteWindDirection = weatherData?.windDirection val windSpeed = weatherData?.windSpeed val gustSpeed = weatherData?.windGusts - val rideSpeed = if (isImperial){ - rideSpeedInMs * 2.23694 - } else { - rideSpeedInMs * 3.6 - } - StreamData(headingResponse, absoluteWindDirection, windSpeed, settings, rideSpeed = rideSpeed, isImperial = isImperial, gustSpeed = gustSpeed, isVisible = isVisible) + StreamData(headingResponse, absoluteWindDirection, windSpeed, settings, rideSpeed = rideSpeedInMs, isImperial = isImperial, gustSpeed = gustSpeed, isVisible = isVisible) } } @@ -164,24 +160,26 @@ class TailwindDataType( val sign = if (headwindSpeed < 0) "+" else { if (headwindSpeed > 0) "-" else "" } - "$sign${headwindSpeed.roundToInt().absoluteValue}" + + val headwindSpeedUserUnit = msInUserUnit(headwindSpeed, streamData.isImperial) + + "$sign${headwindSpeedUserUnit.roundToInt().absoluteValue}" } - WindDirectionIndicatorTextSetting.WIND_SPEED -> windSpeed.roundToInt().toString() + WindDirectionIndicatorTextSetting.WIND_SPEED -> msInUserUnit(windSpeed, streamData.isImperial).roundToInt().toString() WindDirectionIndicatorTextSetting.NONE -> "" } - val subtext = "${windSpeed.roundToInt()}-${streamData.gustSpeed?.roundToInt()}" + val windSpeedUserUnit = msInUserUnit(windSpeed, streamData.isImperial) + val gustSpeedUserUnit = msInUserUnit(streamData.gustSpeed ?: 0.0, streamData.isImperial) + + val subtext = "${windSpeedUserUnit.roundToInt()}-${gustSpeedUserUnit.roundToInt()}" var dayColor = Color(ContextCompat.getColor(context, R.color.black)) var nightColor = Color(ContextCompat.getColor(context, R.color.white)) if (streamData.settings.windDirectionIndicatorSetting == WindDirectionIndicatorSetting.HEADWIND_DIRECTION) { val headwindSpeed = cos( (windDirection + 180) * Math.PI / 180.0) * windSpeed - val windSpeedInKmh = if (streamData.isImperial){ - headwindSpeed / 2.23694 * 3.6 - } else { - headwindSpeed - } + val windSpeedInKmh = headwindSpeed * 3.6 dayColor = interpolateWindColor(windSpeedInKmh, false, context) nightColor = interpolateWindColor(windSpeedInKmh, true, context) } diff --git a/app/src/main/kotlin/de/timklge/karooheadwind/datatypes/TemperatureDataType.kt b/app/src/main/kotlin/de/timklge/karooheadwind/datatypes/TemperatureDataType.kt index b5f0124..5b8d21e 100644 --- a/app/src/main/kotlin/de/timklge/karooheadwind/datatypes/TemperatureDataType.kt +++ b/app/src/main/kotlin/de/timklge/karooheadwind/datatypes/TemperatureDataType.kt @@ -3,9 +3,14 @@ package de.timklge.karooheadwind.datatypes import android.content.Context import de.timklge.karooheadwind.weatherprovider.WeatherData import io.hammerhead.karooext.KarooSystemService +import io.hammerhead.karooext.models.DataType class TemperatureDataType(karooSystemService: KarooSystemService, context: Context) : BaseDataType(karooSystemService, context, "temperature"){ override fun getValue(data: WeatherData): Double { return data.temperature } + + override fun getFormatDataType(): String? { + return DataType.Type.TEMPERATURE + } } \ No newline at end of file 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 22aff6e..741c9e6 100644 --- a/app/src/main/kotlin/de/timklge/karooheadwind/datatypes/WeatherDataType.kt +++ b/app/src/main/kotlin/de/timklge/karooheadwind/datatypes/WeatherDataType.kt @@ -24,6 +24,9 @@ import de.timklge.karooheadwind.streamDatatypeIsVisible import de.timklge.karooheadwind.streamSettings import de.timklge.karooheadwind.streamUserProfile import de.timklge.karooheadwind.throttle +import de.timklge.karooheadwind.util.celciusInUserUnit +import de.timklge.karooheadwind.util.millimetersInUserUnit +import de.timklge.karooheadwind.util.msInUserUnit import de.timklge.karooheadwind.weatherprovider.WeatherData import de.timklge.karooheadwind.weatherprovider.WeatherInterpretation import io.hammerhead.karooext.KarooSystemService @@ -147,11 +150,11 @@ class WeatherDataType( baseBitmap, current = interpretation, windBearing = data.windDirection.roundToInt(), - windSpeed = data.windSpeed.roundToInt(), - windGusts = data.windGusts.roundToInt(), - precipitation = data.precipitation, + windSpeed = msInUserUnit(data.windSpeed, userProfile?.preferredUnit?.distance == UserProfile.PreferredUnit.UnitType.IMPERIAL).roundToInt(), + windGusts = msInUserUnit(data.windGusts, userProfile?.preferredUnit?.distance == UserProfile.PreferredUnit.UnitType.IMPERIAL).roundToInt(), + precipitation = millimetersInUserUnit(data.precipitation, userProfile?.preferredUnit?.distance == UserProfile.PreferredUnit.UnitType.IMPERIAL), precipitationProbability = null, - temperature = data.temperature.roundToInt(), + temperature = celciusInUserUnit(data.temperature, userProfile?.preferredUnit?.temperature == UserProfile.PreferredUnit.UnitType.IMPERIAL).roundToInt(), temperatureUnit = if (userProfile?.preferredUnit?.temperature != UserProfile.PreferredUnit.UnitType.IMPERIAL) TemperatureUnit.CELSIUS else TemperatureUnit.FAHRENHEIT, timeLabel = formattedTime, rowAlignment = when (config.alignment){ diff --git a/app/src/main/kotlin/de/timklge/karooheadwind/screens/WeatherScreen.kt b/app/src/main/kotlin/de/timklge/karooheadwind/screens/WeatherScreen.kt index 66c1449..dd0c504 100644 --- a/app/src/main/kotlin/de/timklge/karooheadwind/screens/WeatherScreen.kt +++ b/app/src/main/kotlin/de/timklge/karooheadwind/screens/WeatherScreen.kt @@ -37,6 +37,9 @@ import de.timklge.karooheadwind.streamCurrentWeatherData import de.timklge.karooheadwind.streamStats import de.timklge.karooheadwind.streamUpcomingRoute import de.timklge.karooheadwind.streamUserProfile +import de.timklge.karooheadwind.util.celciusInUserUnit +import de.timklge.karooheadwind.util.millimetersInUserUnit +import de.timklge.karooheadwind.util.msInUserUnit import io.hammerhead.karooext.KarooSystemService import io.hammerhead.karooext.models.UserProfile import java.time.Instant @@ -110,10 +113,10 @@ fun WeatherScreen(onFinish: () -> Unit) { baseBitmap = baseBitmap, current = WeatherInterpretation.fromWeatherCode(currentWeatherData?.weatherCode), windBearing = currentWeatherData?.windDirection?.roundToInt() ?: 0, - windSpeed = currentWeatherData?.windSpeed?.roundToInt() ?: 0, - windGusts = currentWeatherData?.windGusts?.roundToInt() ?: 0, - precipitation = currentWeatherData?.precipitation ?: 0.0, - temperature = currentWeatherData?.temperature?.toInt() ?: 0, + windSpeed = msInUserUnit(currentWeatherData?.windSpeed ?: 0.0, profile?.preferredUnit?.distance == UserProfile.PreferredUnit.UnitType.IMPERIAL).roundToInt(), + windGusts = msInUserUnit(currentWeatherData?.windGusts ?: 0.0, profile?.preferredUnit?.distance == UserProfile.PreferredUnit.UnitType.IMPERIAL).roundToInt(), + precipitation = millimetersInUserUnit(currentWeatherData?.precipitation ?: 0.0, profile?.preferredUnit?.distance == UserProfile.PreferredUnit.UnitType.IMPERIAL), + temperature = celciusInUserUnit(currentWeatherData?.temperature ?: 0.0, profile?.preferredUnit?.temperature == UserProfile.PreferredUnit.UnitType.IMPERIAL).roundToInt(), temperatureUnit = if(profile?.preferredUnit?.temperature == UserProfile.PreferredUnit.UnitType.METRIC) TemperatureUnit.CELSIUS else TemperatureUnit.FAHRENHEIT, timeLabel = formattedTime, dateLabel = formattedDate, @@ -230,10 +233,10 @@ fun WeatherScreen(onFinish: () -> Unit) { baseBitmap, current = interpretation, windBearing = weatherData?.windDirection?.roundToInt() ?: 0, - windSpeed = weatherData?.windSpeed?.roundToInt() ?: 0, - windGusts = weatherData?.windGusts?.roundToInt() ?: 0, - precipitation = weatherData?.precipitation ?: 0.0, - temperature = weatherData?.temperature?.toInt() ?: 0, + windSpeed = msInUserUnit(currentWeatherData?.windSpeed ?: 0.0, profile?.preferredUnit?.distance == UserProfile.PreferredUnit.UnitType.IMPERIAL).roundToInt(), + windGusts = msInUserUnit(currentWeatherData?.windGusts ?: 0.0, profile?.preferredUnit?.distance == UserProfile.PreferredUnit.UnitType.IMPERIAL).roundToInt(), + precipitation = millimetersInUserUnit(weatherData?.precipitation ?: 0.0, profile?.preferredUnit?.distance == UserProfile.PreferredUnit.UnitType.IMPERIAL), + temperature = celciusInUserUnit(weatherData?.temperature ?: 0.0, profile?.preferredUnit?.temperature == UserProfile.PreferredUnit.UnitType.IMPERIAL).roundToInt(), temperatureUnit = if (profile?.preferredUnit?.temperature != UserProfile.PreferredUnit.UnitType.IMPERIAL) TemperatureUnit.CELSIUS else TemperatureUnit.FAHRENHEIT, timeLabel = formattedForecastTime, dateLabel = formattedForecastDate, diff --git a/app/src/main/kotlin/de/timklge/karooheadwind/util/Conversion.kt b/app/src/main/kotlin/de/timklge/karooheadwind/util/Conversion.kt new file mode 100644 index 0000000..cd32ed2 --- /dev/null +++ b/app/src/main/kotlin/de/timklge/karooheadwind/util/Conversion.kt @@ -0,0 +1,26 @@ +package de.timklge.karooheadwind.util + +fun celciusInUserUnit(celcius: Double, isImperial: Boolean): Double { + return if (isImperial) { + celcius * 9.0 / 5 + 32.0 + } else { + celcius + } +} + +fun millimetersInUserUnit(millimeters: Double, isImperial: Boolean): Double { + return if (isImperial) { + millimeters / 25.4 + } else { + millimeters + } +} + +// Returns the given speed value (m / s) in user unit (km/h or mph) +fun msInUserUnit(ms: Double, isImperial: Boolean): Double { + return if (isImperial) { + ms * 2.2369362920544 + } else { + ms * 3.6 + } +} \ No newline at end of file diff --git a/app/src/main/kotlin/de/timklge/karooheadwind/weatherprovider/openmeteo/OpenMeteoWeatherProvider.kt b/app/src/main/kotlin/de/timklge/karooheadwind/weatherprovider/openmeteo/OpenMeteoWeatherProvider.kt index b8eff6b..f4e2dcc 100644 --- a/app/src/main/kotlin/de/timklge/karooheadwind/weatherprovider/openmeteo/OpenMeteoWeatherProvider.kt +++ b/app/src/main/kotlin/de/timklge/karooheadwind/weatherprovider/openmeteo/OpenMeteoWeatherProvider.kt @@ -3,10 +3,7 @@ package de.timklge.karooheadwind.weatherprovider.openmeteo import android.util.Log import de.timklge.karooheadwind.HeadwindSettings import de.timklge.karooheadwind.KarooHeadwindExtension -import de.timklge.karooheadwind.PrecipitationUnit -import de.timklge.karooheadwind.TemperatureUnit import de.timklge.karooheadwind.WeatherDataProvider -import de.timklge.karooheadwind.WindUnit import de.timklge.karooheadwind.datatypes.GpsCoordinates import de.timklge.karooheadwind.jsonWithUnknownKeys import de.timklge.karooheadwind.weatherprovider.WeatherDataResponse @@ -28,16 +25,12 @@ import kotlin.time.Duration.Companion.seconds class OpenMeteoWeatherProvider : WeatherProvider { @OptIn(FlowPreview::class) - private suspend fun makeOpenMeteoWeatherRequest(karooSystemService: KarooSystemService, gpsCoordinates: List, settings: HeadwindSettings, profile: UserProfile?): HttpResponseState.Complete { - val precipitationUnit = if (profile?.preferredUnit?.distance != UserProfile.PreferredUnit.UnitType.IMPERIAL) PrecipitationUnit.MILLIMETERS else PrecipitationUnit.INCH - val temperatureUnit = if (profile?.preferredUnit?.temperature != UserProfile.PreferredUnit.UnitType.IMPERIAL) TemperatureUnit.CELSIUS else TemperatureUnit.FAHRENHEIT - val windUnit = if (profile?.preferredUnit?.distance != UserProfile.PreferredUnit.UnitType.IMPERIAL) WindUnit.KILOMETERS_PER_HOUR else WindUnit.MILES_PER_HOUR - + private suspend fun makeOpenMeteoWeatherRequest(karooSystemService: KarooSystemService, gpsCoordinates: List): HttpResponseState.Complete { val response = callbackFlow { // https://api.open-meteo.com/v1/forecast?latitude=52.52&longitude=13.41¤t=is_day,surface_pressure,pressure_msl,temperature_2m,relative_humidity_2m,precipitation,weather_code,cloud_cover,wind_speed_10m,wind_direction_10m,wind_gusts_10m&hourly=temperature_2m,precipitation_probability,precipitation,weather_code,wind_speed_10m,wind_direction_10m,wind_gusts_10m&timeformat=unixtime&past_hours=1&forecast_days=1&forecast_hours=12 val lats = gpsCoordinates.joinToString(",") { String.format(Locale.US, "%.6f", it.lat) } val lons = gpsCoordinates.joinToString(",") { String.format(Locale.US, "%.6f", it.lon) } - val url = "https://api.open-meteo.com/v1/forecast?latitude=${lats}&longitude=${lons}¤t=is_day,surface_pressure,pressure_msl,temperature_2m,relative_humidity_2m,precipitation,weather_code,cloud_cover,wind_speed_10m,wind_direction_10m,wind_gusts_10m&hourly=temperature_2m,precipitation_probability,precipitation,weather_code,wind_speed_10m,wind_direction_10m,wind_gusts_10m,is_day&timeformat=unixtime&past_hours=0&forecast_days=1&forecast_hours=12&wind_speed_unit=${windUnit.id}&precipitation_unit=${precipitationUnit.id}&temperature_unit=${temperatureUnit.id}" + val url = "https://api.open-meteo.com/v1/forecast?latitude=${lats}&longitude=${lons}¤t=is_day,surface_pressure,pressure_msl,temperature_2m,relative_humidity_2m,precipitation,weather_code,cloud_cover,wind_speed_10m,wind_direction_10m,wind_gusts_10m&hourly=temperature_2m,precipitation_probability,precipitation,weather_code,wind_speed_10m,wind_direction_10m,wind_gusts_10m,is_day&timeformat=unixtime&past_hours=0&forecast_days=1&forecast_hours=12&wind_speed_unit=ms" Log.d(KarooHeadwindExtension.TAG, "Http request to ${url}...") @@ -84,7 +77,7 @@ class OpenMeteoWeatherProvider : WeatherProvider { settings: HeadwindSettings, profile: UserProfile? ): WeatherDataResponse { - val openMeteoResponse = makeOpenMeteoWeatherRequest(karooSystem, coordinates, settings, profile) + val openMeteoResponse = makeOpenMeteoWeatherRequest(karooSystem, coordinates) val responseBody = openMeteoResponse.body?.let { String(it) } ?: throw WeatherProviderException(500, "Null response from OpenMeteo") val weatherData = if (coordinates.size == 1) { diff --git a/app/src/main/kotlin/de/timklge/karooheadwind/weatherprovider/openweathermap/OpenWeatherMapWeatherProvider.kt b/app/src/main/kotlin/de/timklge/karooheadwind/weatherprovider/openweathermap/OpenWeatherMapWeatherProvider.kt index 18a4eb0..4f1bf16 100644 --- a/app/src/main/kotlin/de/timklge/karooheadwind/weatherprovider/openweathermap/OpenWeatherMapWeatherProvider.kt +++ b/app/src/main/kotlin/de/timklge/karooheadwind/weatherprovider/openweathermap/OpenWeatherMapWeatherProvider.kt @@ -69,7 +69,7 @@ class OpenWeatherMapWeatherProvider(private val apiKey: String) : WeatherProvide profile: UserProfile? ): WeatherDataResponse { - val response = makeOpenWeatherMapRequest(karooSystem, coordinates, apiKey, profile) + val response = makeOpenWeatherMapRequest(karooSystem, coordinates, apiKey) val responseBody = response.body?.let { String(it) } ?: throw Exception("Null response from OpenWeatherMap") val responses = mutableListOf() @@ -89,21 +89,15 @@ class OpenWeatherMapWeatherProvider(private val apiKey: String) : WeatherProvide private suspend fun makeOpenWeatherMapRequest( service: KarooSystemService, coordinates: List, - apiKey: String, - profile: UserProfile? + apiKey: String ): HttpResponseState.Complete { val response = callbackFlow { // OpenWeatherMap only supports setting imperial or metric units for all measurements, not individually for distance / temperature - val unitsString = if (profile?.preferredUnit?.temperature == UserProfile.PreferredUnit.UnitType.IMPERIAL || profile?.preferredUnit?.distance == UserProfile.PreferredUnit.UnitType.IMPERIAL) { - "imperial" - } else { - "metric" - } val coordinate = coordinates.first() // URL API 3.0 with onecall endpoint val url = "https://api.openweathermap.org/data/3.0/onecall?lat=${coordinate.lat}&lon=${coordinate.lon}" + - "&appid=$apiKey&exclude=minutely,daily,alerts&units=${unitsString}" + "&appid=$apiKey&exclude=minutely,daily,alerts&units=metric" Log.d(KarooHeadwindExtension.TAG, "Http request to OpenWeatherMap API 3.0: $url")