diff --git a/app/src/main/kotlin/de/timklge/karooheadwind/DataStore.kt b/app/src/main/kotlin/de/timklge/karooheadwind/DataStore.kt index 99e2fe2..7784138 100644 --- a/app/src/main/kotlin/de/timklge/karooheadwind/DataStore.kt +++ b/app/src/main/kotlin/de/timklge/karooheadwind/DataStore.kt @@ -294,9 +294,9 @@ fun lerpWeather( weatherCode = closestWeatherData.weatherCode, isForecast = closestWeatherData.isForecast, isNight = closestWeatherData.isNight, + uvi = start.uvi + (end.uvi - start.uvi) * factor ) } - fun lerpWeatherTime( weatherData: List?, currentWeatherData: WeatherData diff --git a/app/src/main/kotlin/de/timklge/karooheadwind/KarooHeadwindExtension.kt b/app/src/main/kotlin/de/timklge/karooheadwind/KarooHeadwindExtension.kt index cdc92a0..27f9de9 100644 --- a/app/src/main/kotlin/de/timklge/karooheadwind/KarooHeadwindExtension.kt +++ b/app/src/main/kotlin/de/timklge/karooheadwind/KarooHeadwindExtension.kt @@ -17,6 +17,7 @@ import de.timklge.karooheadwind.datatypes.SealevelPressureDataType import de.timklge.karooheadwind.datatypes.SurfacePressureDataType import de.timklge.karooheadwind.datatypes.TailwindAndRideSpeedDataType import de.timklge.karooheadwind.datatypes.TemperatureDataType +import de.timklge.karooheadwind.datatypes.UviDataType import de.timklge.karooheadwind.datatypes.TemperatureForecastDataType import de.timklge.karooheadwind.datatypes.WeatherForecastDataType import de.timklge.karooheadwind.datatypes.WindDirectionAndSpeedDataType @@ -83,7 +84,8 @@ class KarooHeadwindExtension : KarooExtension("karoo-headwind", BuildConfig.VERS WindDirectionAndSpeedDataType(karooSystem, applicationContext), RelativeGradeDataType(karooSystem, applicationContext), RelativeElevationGainDataType(karooSystem, applicationContext), - TemperatureDataType(karooSystem, applicationContext) + TemperatureDataType(karooSystem, applicationContext), + UviDataType(karooSystem, applicationContext) ) } 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 49077b2..3cf1df5 100644 --- a/app/src/main/kotlin/de/timklge/karooheadwind/datatypes/ForecastDataType.kt +++ b/app/src/main/kotlin/de/timklge/karooheadwind/datatypes/ForecastDataType.kt @@ -65,27 +65,29 @@ import kotlinx.coroutines.flow.flow import kotlinx.coroutines.launch import java.time.Instant import java.time.ZoneId -import java.time.format.DateTimeFormatter import java.time.temporal.ChronoUnit import kotlin.math.abs import kotlin.math.roundToInt abstract class ForecastDataType(private val karooSystem: KarooSystemService, typeId: String) : DataTypeImpl("karoo-headwind", typeId) { @Composable - abstract fun RenderWidget(arrowBitmap: Bitmap, - current: WeatherInterpretation, - windBearing: Int, - windSpeed: Int, - windGusts: Int, - precipitation: Double, - precipitationProbability: Int?, - temperature: Int, - temperatureUnit: TemperatureUnit, - timeLabel: String, - dateLabel: String?, - distance: Double?, - isImperial: Boolean, - isNight: Boolean) + abstract fun RenderWidget( + arrowBitmap: Bitmap, + current: WeatherInterpretation, + windBearing: Int, + windSpeed: Int, + windGusts: Int, + precipitation: Double, + precipitationProbability: Int?, + temperature: Int, + temperatureUnit: TemperatureUnit, + timeLabel: String, + dateLabel: String?, + distance: Double?, + isImperial: Boolean, + isNight: Boolean, + uvi: Double + ) @OptIn(ExperimentalGlanceRemoteViewsApi::class) private val glance = GlanceRemoteViews() @@ -107,6 +109,7 @@ abstract class ForecastDataType(private val karooSystem: KarooSystemService, typ val weatherData = (0..<12).map { val forecastTime = timeAtFullHour + it * 60 * 60 val forecastTemperature = 20.0 + (-20..20).random() + val forecastUvi = 0.0 + (0..12).random().toDouble() val forecastPrecipitation = 0.0 + (0..10).random() val forecastPrecipitationProbability = (0..100).random() val forecastWeatherCode = WeatherInterpretation.getKnownWeatherCodes().random() @@ -127,7 +130,8 @@ abstract class ForecastDataType(private val karooSystem: KarooSystemService, typ windGusts = forecastWindGusts, weatherCode = forecastWeatherCode, isForecast = true, - isNight = it < 2 + isNight = it < 2, + uvi = forecastUvi ) } @@ -149,7 +153,8 @@ abstract class ForecastDataType(private val karooSystem: KarooSystemService, typ windGusts = 10.0, weatherCode = WeatherInterpretation.getKnownWeatherCodes().random(), isForecast = false, - isNight = false + isNight = false, + uvi = 2.0 ), coords = GpsCoordinates(0.0, 0.0, distanceAlongRoute = index * distancePerHour), timezone = "UTC", @@ -333,7 +338,8 @@ abstract class ForecastDataType(private val karooSystem: KarooSystemService, typ dateLabel = if (hasNewDate) formattedDate else null, distance = null, isImperial = settingsAndProfile.isImperial, - isNight = data.current.isNight + isNight = data.current.isNight, + uvi = data.current.uvi ) previousDate = formattedDate @@ -359,7 +365,8 @@ abstract class ForecastDataType(private val karooSystem: KarooSystemService, typ dateLabel = if (hasNewDate) formattedDate else null, distance = if (settingsAndProfile.settings.showDistanceInForecast) distanceFromCurrent else null, isImperial = settingsAndProfile.isImperial, - isNight = weatherData?.isNight == true + isNight = weatherData?.isNight == true, + uvi = weatherData?.uvi ?: 0.0 ) previousDate = formattedDate diff --git a/app/src/main/kotlin/de/timklge/karooheadwind/datatypes/LineGraphForecastDataType.kt b/app/src/main/kotlin/de/timklge/karooheadwind/datatypes/LineGraphForecastDataType.kt index a3c434c..331e23d 100644 --- a/app/src/main/kotlin/de/timklge/karooheadwind/datatypes/LineGraphForecastDataType.kt +++ b/app/src/main/kotlin/de/timklge/karooheadwind/datatypes/LineGraphForecastDataType.kt @@ -94,6 +94,7 @@ abstract class LineGraphForecastDataType(private val karooSystem: KarooSystemSer val forecastWindSpeed = 0.0 + (0..10).random() val forecastWindDirection = 0.0 + (0..360).random() val forecastWindGusts = 0.0 + (0..10).random() + val forcastUvi = 0.0 + (0..12).random() WeatherData( time = forecastTime, temperature = forecastTemperature, @@ -108,7 +109,8 @@ abstract class LineGraphForecastDataType(private val karooSystem: KarooSystemSer windGusts = forecastWindGusts, weatherCode = forecastWeatherCode, isForecast = true, - isNight = it < 2 + isNight = it < 2, + uvi = forcastUvi ) } @@ -130,7 +132,8 @@ abstract class LineGraphForecastDataType(private val karooSystem: KarooSystemSer windGusts = 10.0, weatherCode = WeatherInterpretation.getKnownWeatherCodes().random(), isForecast = false, - isNight = false + isNight = false, + uvi = 2.0 ), coords = GpsCoordinates(0.0, 0.0, distanceAlongRoute = index * distancePerHour), timezone = "UTC", diff --git a/app/src/main/kotlin/de/timklge/karooheadwind/datatypes/UviDataType.kt b/app/src/main/kotlin/de/timklge/karooheadwind/datatypes/UviDataType.kt new file mode 100644 index 0000000..5418977 --- /dev/null +++ b/app/src/main/kotlin/de/timklge/karooheadwind/datatypes/UviDataType.kt @@ -0,0 +1,12 @@ +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.UserProfile + +class UviDataType(karooSystemService: KarooSystemService, context: Context) : BaseDataType(karooSystemService, context, "uvi"){ + override fun getValue(data: WeatherData, userProfile: UserProfile): Double { + return data.uvi + } +} \ No newline at end of file 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 7d6f3d2..c2cda51 100644 --- a/app/src/main/kotlin/de/timklge/karooheadwind/datatypes/WeatherForecastDataType.kt +++ b/app/src/main/kotlin/de/timklge/karooheadwind/datatypes/WeatherForecastDataType.kt @@ -23,6 +23,7 @@ class WeatherForecastDataType(karooSystem: KarooSystemService) : ForecastDataTyp distance: Double?, isImperial: Boolean, isNight: Boolean, + uvi: Double, ) { Weather( arrowBitmap = arrowBitmap, diff --git a/app/src/main/kotlin/de/timklge/karooheadwind/weatherprovider/WeatherData.kt b/app/src/main/kotlin/de/timklge/karooheadwind/weatherprovider/WeatherData.kt index db4ea4f..a7921ef 100644 --- a/app/src/main/kotlin/de/timklge/karooheadwind/weatherprovider/WeatherData.kt +++ b/app/src/main/kotlin/de/timklge/karooheadwind/weatherprovider/WeatherData.kt @@ -17,6 +17,7 @@ data class WeatherData( val windGusts: Double, val weatherCode: Int, val isForecast: Boolean, - val isNight: Boolean + val isNight: Boolean, + val uvi: Double, ) diff --git a/app/src/main/kotlin/de/timklge/karooheadwind/weatherprovider/openmeteo/OpenMeteoWeatherData.kt b/app/src/main/kotlin/de/timklge/karooheadwind/weatherprovider/openmeteo/OpenMeteoWeatherData.kt index 6cf5281..dec8a9f 100644 --- a/app/src/main/kotlin/de/timklge/karooheadwind/weatherprovider/openmeteo/OpenMeteoWeatherData.kt +++ b/app/src/main/kotlin/de/timklge/karooheadwind/weatherprovider/openmeteo/OpenMeteoWeatherData.kt @@ -18,6 +18,7 @@ data class OpenMeteoWeatherData( @SerialName("wind_gusts_10m") val windGusts: Double, @SerialName("weather_code") val weatherCode: Int, @SerialName("is_day") val isDay: Int, + @SerialName("uv_index") val uvi: Double, ) { fun toWeatherData(): WeatherData = WeatherData( temperature = temperature, @@ -33,6 +34,7 @@ data class OpenMeteoWeatherData( time = time, isForecast = false, isNight = isDay == 0, + uvi = uvi ) } diff --git a/app/src/main/kotlin/de/timklge/karooheadwind/weatherprovider/openmeteo/OpenMeteoWeatherForecastData.kt b/app/src/main/kotlin/de/timklge/karooheadwind/weatherprovider/openmeteo/OpenMeteoWeatherForecastData.kt index 5a4d702..573853c 100644 --- a/app/src/main/kotlin/de/timklge/karooheadwind/weatherprovider/openmeteo/OpenMeteoWeatherForecastData.kt +++ b/app/src/main/kotlin/de/timklge/karooheadwind/weatherprovider/openmeteo/OpenMeteoWeatherForecastData.kt @@ -19,6 +19,7 @@ data class OpenMeteoWeatherForecastData( @SerialName("pressure_msl") val sealevelPressure: List, @SerialName("is_day") val isDay: List, @SerialName("relative_humidity_2m") val relativeHumidity: List, + @SerialName("uv_index") val uvi: List, ) { fun toWeatherData(): List { return time.mapIndexed { index, t -> @@ -37,6 +38,7 @@ data class OpenMeteoWeatherForecastData( surfacePressure = surfacePressure[index], sealevelPressure = sealevelPressure[index], relativeHumidity = relativeHumidity[index], + uvi = uvi[index] ) } } 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 f9f4a6f..6018621 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 @@ -30,7 +30,7 @@ class OpenMeteoWeatherProvider : WeatherProvider { // 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,surface_pressure,pressure_msl,relative_humidity_2m,cloud_cover&timeformat=unixtime&past_hours=0&forecast_days=1&forecast_hours=12&wind_speed_unit=ms" + val url = "https://api.open-meteo.com/v1/forecast?latitude=${lats}&longitude=${lons}¤t=is_day,surface_pressure,pressure_msl,uv_index,temperature_2m,relative_humidity_2m,precipitation,weather_code,cloud_cover,wind_speed_10m,wind_direction_10m,wind_gusts_10m&hourly=uv_index,temperature_2m,precipitation_probability,precipitation,weather_code,wind_speed_10m,wind_direction_10m,wind_gusts_10m,is_day,surface_pressure,pressure_msl,relative_humidity_2m,cloud_cover&timeformat=unixtime&past_hours=0&forecast_days=1&forecast_hours=12&wind_speed_unit=ms" Log.d(KarooHeadwindExtension.TAG, "Http request to ${url}...") diff --git a/app/src/main/kotlin/de/timklge/karooheadwind/weatherprovider/openweathermap/OpenWeatherMapForecastData.kt b/app/src/main/kotlin/de/timklge/karooheadwind/weatherprovider/openweathermap/OpenWeatherMapForecastData.kt index 6bf45ed..5fbb604 100644 --- a/app/src/main/kotlin/de/timklge/karooheadwind/weatherprovider/openweathermap/OpenWeatherMapForecastData.kt +++ b/app/src/main/kotlin/de/timklge/karooheadwind/weatherprovider/openweathermap/OpenWeatherMapForecastData.kt @@ -20,7 +20,8 @@ data class OpenWeatherMapForecastData( val pop: Double, val rain: Rain? = null, val snow: Snow? = null, - val weather: List + val weather: List, + val uvi: Double, ) { fun toWeatherData(currentWeatherData: OpenWeatherMapWeatherData): WeatherData { val dtInstant = Instant.ofEpochSecond(dt) @@ -32,6 +33,7 @@ data class OpenWeatherMapForecastData( val sunsetTime = sunsetInstant.atZone(ZoneOffset.UTC).toLocalTime() return WeatherData( + uvi = uvi, temperature = temp, relativeHumidity = humidity, precipitation = rain?.h1 ?: 0.0, diff --git a/app/src/main/kotlin/de/timklge/karooheadwind/weatherprovider/openweathermap/OpenWeatherMapWeatherData.kt b/app/src/main/kotlin/de/timklge/karooheadwind/weatherprovider/openweathermap/OpenWeatherMapWeatherData.kt index 6c19fd2..2eb08fb 100644 --- a/app/src/main/kotlin/de/timklge/karooheadwind/weatherprovider/openweathermap/OpenWeatherMapWeatherData.kt +++ b/app/src/main/kotlin/de/timklge/karooheadwind/weatherprovider/openweathermap/OpenWeatherMapWeatherData.kt @@ -19,9 +19,11 @@ data class OpenWeatherMapWeatherData( val wind_gust: Double? = null, val rain: Rain? = null, val snow: Snow? = null, + val uvi: Double, val weather: List){ fun toWeatherData(): WeatherData = WeatherData( + uvi = uvi, temperature = temp, relativeHumidity = humidity, precipitation = rain?.h1 ?: 0.0, diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 40b3880..3bae51b 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -22,6 +22,8 @@ Sealevel pressure Atmospheric pressure at sea level in configured unit Weather Forecast + UV Index + Current UV Index at current location Current hourly weather forecast Temperature Forecast Current hourly temperature forecast diff --git a/app/src/main/res/xml/extension_info.xml b/app/src/main/res/xml/extension_info.xml index f10c54d..72dbe70 100644 --- a/app/src/main/res/xml/extension_info.xml +++ b/app/src/main/res/xml/extension_info.xml @@ -131,6 +131,13 @@ icon="@drawable/thermometer" typeId="temperature" /> + +