Add moon icon to represent clear sky at night (#123)
This commit is contained in:
parent
cff4b07d7d
commit
96bee1b55c
@ -276,7 +276,8 @@ fun lerpWeather(
|
|||||||
windDirection = lerpAngle(start.windDirection, end.windDirection, factor),
|
windDirection = lerpAngle(start.windDirection, end.windDirection, factor),
|
||||||
windGusts = start.windGusts + (end.windGusts - start.windGusts) * factor,
|
windGusts = start.windGusts + (end.windGusts - start.windGusts) * factor,
|
||||||
weatherCode = closestWeatherData.weatherCode,
|
weatherCode = closestWeatherData.weatherCode,
|
||||||
isForecast = closestWeatherData.isForecast
|
isForecast = closestWeatherData.isForecast,
|
||||||
|
isNight = closestWeatherData.isNight,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -50,7 +50,6 @@ data class HeadwindWidgetSettings(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Moded with openweahtermap.org
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class HeadwindStats(
|
data class HeadwindStats(
|
||||||
val lastSuccessfulWeatherRequest: Long? = null,
|
val lastSuccessfulWeatherRequest: Long? = null,
|
||||||
|
|||||||
@ -28,11 +28,7 @@ import de.timklge.karooheadwind.KarooHeadwindExtension
|
|||||||
import de.timklge.karooheadwind.R
|
import de.timklge.karooheadwind.R
|
||||||
import de.timklge.karooheadwind.TemperatureUnit
|
import de.timklge.karooheadwind.TemperatureUnit
|
||||||
import de.timklge.karooheadwind.UpcomingRoute
|
import de.timklge.karooheadwind.UpcomingRoute
|
||||||
import de.timklge.karooheadwind.weatherprovider.WeatherData
|
|
||||||
import de.timklge.karooheadwind.weatherprovider.WeatherDataForLocation
|
|
||||||
import de.timklge.karooheadwind.WeatherDataProvider
|
import de.timklge.karooheadwind.WeatherDataProvider
|
||||||
import de.timklge.karooheadwind.weatherprovider.WeatherDataResponse
|
|
||||||
import de.timklge.karooheadwind.weatherprovider.WeatherInterpretation
|
|
||||||
import de.timklge.karooheadwind.getHeadingFlow
|
import de.timklge.karooheadwind.getHeadingFlow
|
||||||
import de.timklge.karooheadwind.streamCurrentForecastWeatherData
|
import de.timklge.karooheadwind.streamCurrentForecastWeatherData
|
||||||
import de.timklge.karooheadwind.streamSettings
|
import de.timklge.karooheadwind.streamSettings
|
||||||
@ -40,6 +36,10 @@ import de.timklge.karooheadwind.streamUpcomingRoute
|
|||||||
import de.timklge.karooheadwind.streamUserProfile
|
import de.timklge.karooheadwind.streamUserProfile
|
||||||
import de.timklge.karooheadwind.streamWidgetSettings
|
import de.timklge.karooheadwind.streamWidgetSettings
|
||||||
import de.timklge.karooheadwind.throttle
|
import de.timklge.karooheadwind.throttle
|
||||||
|
import de.timklge.karooheadwind.weatherprovider.WeatherData
|
||||||
|
import de.timklge.karooheadwind.weatherprovider.WeatherDataForLocation
|
||||||
|
import de.timklge.karooheadwind.weatherprovider.WeatherDataResponse
|
||||||
|
import de.timklge.karooheadwind.weatherprovider.WeatherInterpretation
|
||||||
import io.hammerhead.karooext.KarooSystemService
|
import io.hammerhead.karooext.KarooSystemService
|
||||||
import io.hammerhead.karooext.extension.DataTypeImpl
|
import io.hammerhead.karooext.extension.DataTypeImpl
|
||||||
import io.hammerhead.karooext.internal.ViewEmitter
|
import io.hammerhead.karooext.internal.ViewEmitter
|
||||||
@ -78,7 +78,8 @@ abstract class ForecastDataType(private val karooSystem: KarooSystemService, typ
|
|||||||
timeLabel: String,
|
timeLabel: String,
|
||||||
dateLabel: String?,
|
dateLabel: String?,
|
||||||
distance: Double?,
|
distance: Double?,
|
||||||
isImperial: Boolean)
|
isImperial: Boolean,
|
||||||
|
isNight: Boolean)
|
||||||
|
|
||||||
@OptIn(ExperimentalGlanceRemoteViewsApi::class)
|
@OptIn(ExperimentalGlanceRemoteViewsApi::class)
|
||||||
private val glance = GlanceRemoteViews()
|
private val glance = GlanceRemoteViews()
|
||||||
@ -123,7 +124,8 @@ abstract class ForecastDataType(private val karooSystem: KarooSystemService, typ
|
|||||||
windDirection = forecastWindDirection,
|
windDirection = forecastWindDirection,
|
||||||
windGusts = forecastWindGusts,
|
windGusts = forecastWindGusts,
|
||||||
weatherCode = forecastWeatherCode,
|
weatherCode = forecastWeatherCode,
|
||||||
isForecast = true
|
isForecast = true,
|
||||||
|
isNight = it < 2
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -144,7 +146,8 @@ abstract class ForecastDataType(private val karooSystem: KarooSystemService, typ
|
|||||||
windDirection = 180.0,
|
windDirection = 180.0,
|
||||||
windGusts = 10.0,
|
windGusts = 10.0,
|
||||||
weatherCode = WeatherInterpretation.getKnownWeatherCodes().random(),
|
weatherCode = WeatherInterpretation.getKnownWeatherCodes().random(),
|
||||||
isForecast = false
|
isForecast = false,
|
||||||
|
isNight = false
|
||||||
),
|
),
|
||||||
coords = GpsCoordinates(0.0, 0.0, distanceAlongRoute = index * distancePerHour),
|
coords = GpsCoordinates(0.0, 0.0, distanceAlongRoute = index * distancePerHour),
|
||||||
timezone = "UTC",
|
timezone = "UTC",
|
||||||
@ -305,7 +308,8 @@ abstract class ForecastDataType(private val karooSystem: KarooSystemService, typ
|
|||||||
timeLabel = formattedTime,
|
timeLabel = formattedTime,
|
||||||
dateLabel = if (hasNewDate) formattedDate else null,
|
dateLabel = if (hasNewDate) formattedDate else null,
|
||||||
distance = null,
|
distance = null,
|
||||||
isImperial = settingsAndProfile.isImperial
|
isImperial = settingsAndProfile.isImperial,
|
||||||
|
isNight = data.current.isNight
|
||||||
)
|
)
|
||||||
|
|
||||||
previousDate = formattedDate
|
previousDate = formattedDate
|
||||||
@ -330,7 +334,8 @@ abstract class ForecastDataType(private val karooSystem: KarooSystemService, typ
|
|||||||
timeLabel = formattedTime,
|
timeLabel = formattedTime,
|
||||||
dateLabel = if (hasNewDate) formattedDate else null,
|
dateLabel = if (hasNewDate) formattedDate else null,
|
||||||
distance = if (settingsAndProfile.settings.showDistanceInForecast) distanceFromCurrent else null,
|
distance = if (settingsAndProfile.settings.showDistanceInForecast) distanceFromCurrent else null,
|
||||||
isImperial = settingsAndProfile.isImperial
|
isImperial = settingsAndProfile.isImperial,
|
||||||
|
isNight = weatherData?.isNight == true
|
||||||
)
|
)
|
||||||
|
|
||||||
previousDate = formattedDate
|
previousDate = formattedDate
|
||||||
|
|||||||
@ -34,13 +34,14 @@ fun GraphicalForecast(
|
|||||||
distance: Double? = null,
|
distance: Double? = null,
|
||||||
timeLabel: String? = null,
|
timeLabel: String? = null,
|
||||||
rowAlignment: Alignment.Horizontal = Alignment.Horizontal.CenterHorizontally,
|
rowAlignment: Alignment.Horizontal = Alignment.Horizontal.CenterHorizontally,
|
||||||
isImperial: Boolean?
|
isImperial: Boolean?,
|
||||||
|
isNight: Boolean,
|
||||||
) {
|
) {
|
||||||
Column(modifier = GlanceModifier.fillMaxHeight().padding(1.dp).width(86.dp), horizontalAlignment = rowAlignment) {
|
Column(modifier = GlanceModifier.fillMaxHeight().padding(1.dp).width(86.dp), horizontalAlignment = rowAlignment) {
|
||||||
Row(modifier = GlanceModifier.defaultWeight().wrapContentWidth(), horizontalAlignment = rowAlignment, verticalAlignment = Alignment.CenterVertically) {
|
Row(modifier = GlanceModifier.defaultWeight().wrapContentWidth(), horizontalAlignment = rowAlignment, verticalAlignment = Alignment.CenterVertically) {
|
||||||
Image(
|
Image(
|
||||||
modifier = GlanceModifier.defaultWeight().wrapContentWidth().padding(1.dp),
|
modifier = GlanceModifier.defaultWeight().wrapContentWidth().padding(1.dp),
|
||||||
provider = ImageProvider(getWeatherIcon(current)),
|
provider = ImageProvider(getWeatherIcon(current, isNight)),
|
||||||
contentDescription = "Current weather information",
|
contentDescription = "Current weather information",
|
||||||
contentScale = ContentScale.Fit,
|
contentScale = ContentScale.Fit,
|
||||||
colorFilter = ColorFilter.tint(ColorProvider(Color.Black, Color.White))
|
colorFilter = ColorFilter.tint(ColorProvider(Color.Black, Color.White))
|
||||||
@ -96,13 +97,15 @@ class GraphicalForecastDataType(karooSystem: KarooSystemService) : ForecastDataT
|
|||||||
timeLabel: String,
|
timeLabel: String,
|
||||||
dateLabel: String?,
|
dateLabel: String?,
|
||||||
distance: Double?,
|
distance: Double?,
|
||||||
isImperial: Boolean
|
isImperial: Boolean,
|
||||||
|
isNight: Boolean,
|
||||||
) {
|
) {
|
||||||
GraphicalForecast(
|
GraphicalForecast(
|
||||||
current = current,
|
current = current,
|
||||||
distance = distance,
|
distance = distance,
|
||||||
timeLabel = timeLabel,
|
timeLabel = timeLabel,
|
||||||
isImperial = isImperial
|
isImperial = isImperial,
|
||||||
|
isNight = isNight
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -25,7 +25,6 @@ import de.timklge.karooheadwind.weatherprovider.WeatherInterpretation
|
|||||||
import io.hammerhead.karooext.KarooSystemService
|
import io.hammerhead.karooext.KarooSystemService
|
||||||
import kotlin.math.absoluteValue
|
import kotlin.math.absoluteValue
|
||||||
import kotlin.math.ceil
|
import kotlin.math.ceil
|
||||||
import kotlin.math.roundToInt
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun PrecipitationForecast(
|
fun PrecipitationForecast(
|
||||||
@ -34,7 +33,7 @@ fun PrecipitationForecast(
|
|||||||
distance: Double? = null,
|
distance: Double? = null,
|
||||||
timeLabel: String? = null,
|
timeLabel: String? = null,
|
||||||
rowAlignment: Alignment.Horizontal = Alignment.Horizontal.CenterHorizontally,
|
rowAlignment: Alignment.Horizontal = Alignment.Horizontal.CenterHorizontally,
|
||||||
isImperial: Boolean?
|
isImperial: Boolean?,
|
||||||
) {
|
) {
|
||||||
Column(modifier = GlanceModifier.fillMaxHeight().padding(1.dp).width(86.dp), horizontalAlignment = rowAlignment) {
|
Column(modifier = GlanceModifier.fillMaxHeight().padding(1.dp).width(86.dp), horizontalAlignment = rowAlignment) {
|
||||||
Row(modifier = GlanceModifier.defaultWeight().fillMaxWidth(), horizontalAlignment = rowAlignment, verticalAlignment = Alignment.CenterVertically) {
|
Row(modifier = GlanceModifier.defaultWeight().fillMaxWidth(), horizontalAlignment = rowAlignment, verticalAlignment = Alignment.CenterVertically) {
|
||||||
@ -95,14 +94,15 @@ class PrecipitationForecastDataType(karooSystem: KarooSystemService) : ForecastD
|
|||||||
timeLabel: String,
|
timeLabel: String,
|
||||||
dateLabel: String?,
|
dateLabel: String?,
|
||||||
distance: Double?,
|
distance: Double?,
|
||||||
isImperial: Boolean
|
isImperial: Boolean,
|
||||||
|
isNight: Boolean,
|
||||||
) {
|
) {
|
||||||
PrecipitationForecast(
|
PrecipitationForecast(
|
||||||
precipitation = ceil(precipitation).toInt(),
|
precipitation = ceil(precipitation).toInt(),
|
||||||
precipitationProbability = precipitationProbability,
|
precipitationProbability = precipitationProbability,
|
||||||
distance = distance,
|
distance = distance,
|
||||||
timeLabel = timeLabel,
|
timeLabel = timeLabel,
|
||||||
isImperial = isImperial
|
isImperial = isImperial,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -91,14 +91,15 @@ class TemperatureForecastDataType(karooSystem: KarooSystemService) : ForecastDat
|
|||||||
timeLabel: String,
|
timeLabel: String,
|
||||||
dateLabel: String?,
|
dateLabel: String?,
|
||||||
distance: Double?,
|
distance: Double?,
|
||||||
isImperial: Boolean
|
isImperial: Boolean,
|
||||||
|
isNight: Boolean
|
||||||
) {
|
) {
|
||||||
TemperatureForecast(
|
TemperatureForecast(
|
||||||
temperature = temperature,
|
temperature = temperature,
|
||||||
temperatureUnit = temperatureUnit,
|
temperatureUnit = temperatureUnit,
|
||||||
distance = distance,
|
distance = distance,
|
||||||
timeLabel = timeLabel,
|
timeLabel = timeLabel,
|
||||||
isImperial = isImperial
|
isImperial = isImperial,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,6 +16,7 @@ import de.timklge.karooheadwind.HeadingResponse
|
|||||||
import de.timklge.karooheadwind.HeadwindSettings
|
import de.timklge.karooheadwind.HeadwindSettings
|
||||||
import de.timklge.karooheadwind.KarooHeadwindExtension
|
import de.timklge.karooheadwind.KarooHeadwindExtension
|
||||||
import de.timklge.karooheadwind.MainActivity
|
import de.timklge.karooheadwind.MainActivity
|
||||||
|
import de.timklge.karooheadwind.R
|
||||||
import de.timklge.karooheadwind.TemperatureUnit
|
import de.timklge.karooheadwind.TemperatureUnit
|
||||||
import de.timklge.karooheadwind.getHeadingFlow
|
import de.timklge.karooheadwind.getHeadingFlow
|
||||||
import de.timklge.karooheadwind.streamCurrentWeatherData
|
import de.timklge.karooheadwind.streamCurrentWeatherData
|
||||||
@ -79,9 +80,12 @@ class WeatherDataType(
|
|||||||
private fun previewFlow(): Flow<StreamData> = flow {
|
private fun previewFlow(): Flow<StreamData> = flow {
|
||||||
while (true){
|
while (true){
|
||||||
emit(StreamData(
|
emit(StreamData(
|
||||||
WeatherData(Instant.now().epochSecond, 0.0,
|
WeatherData(
|
||||||
|
Instant.now().epochSecond, 0.0,
|
||||||
20.0, 50.0, 3.0, 0.0, 1013.25, 980.0, 15.0, 30.0, 30.0,
|
20.0, 50.0, 3.0, 0.0, 1013.25, 980.0, 15.0, 30.0, 30.0,
|
||||||
WeatherInterpretation.getKnownWeatherCodes().random(), isForecast = false), HeadwindSettings()))
|
WeatherInterpretation.getKnownWeatherCodes().random(), isForecast = false,
|
||||||
|
isNight = listOf(true, false).random()
|
||||||
|
), HeadwindSettings()))
|
||||||
|
|
||||||
delay(5_000)
|
delay(5_000)
|
||||||
}
|
}
|
||||||
@ -96,7 +100,7 @@ class WeatherDataType(
|
|||||||
|
|
||||||
val baseBitmap = BitmapFactory.decodeResource(
|
val baseBitmap = BitmapFactory.decodeResource(
|
||||||
context.resources,
|
context.resources,
|
||||||
de.timklge.karooheadwind.R.drawable.arrow_0
|
R.drawable.arrow_0
|
||||||
)
|
)
|
||||||
|
|
||||||
val dataFlow = if (config.preview){
|
val dataFlow = if (config.preview){
|
||||||
@ -148,7 +152,8 @@ class WeatherDataType(
|
|||||||
},
|
},
|
||||||
dateLabel = formattedDate,
|
dateLabel = formattedDate,
|
||||||
singleDisplay = true,
|
singleDisplay = true,
|
||||||
isImperial = userProfile?.preferredUnit?.distance == UserProfile.PreferredUnit.UnitType.IMPERIAL
|
isImperial = userProfile?.preferredUnit?.distance == UserProfile.PreferredUnit.UnitType.IMPERIAL,
|
||||||
|
isNight = data.isNight,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -21,7 +21,8 @@ class WeatherForecastDataType(karooSystem: KarooSystemService) : ForecastDataTyp
|
|||||||
timeLabel: String,
|
timeLabel: String,
|
||||||
dateLabel: String?,
|
dateLabel: String?,
|
||||||
distance: Double?,
|
distance: Double?,
|
||||||
isImperial: Boolean
|
isImperial: Boolean,
|
||||||
|
isNight: Boolean,
|
||||||
) {
|
) {
|
||||||
Weather(
|
Weather(
|
||||||
arrowBitmap = arrowBitmap,
|
arrowBitmap = arrowBitmap,
|
||||||
@ -36,7 +37,8 @@ class WeatherForecastDataType(karooSystem: KarooSystemService) : ForecastDataTyp
|
|||||||
timeLabel = timeLabel,
|
timeLabel = timeLabel,
|
||||||
dateLabel = dateLabel,
|
dateLabel = dateLabel,
|
||||||
distance = distance,
|
distance = distance,
|
||||||
isImperial = isImperial
|
isImperial = isImperial,
|
||||||
|
isNight = isNight,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -45,9 +45,9 @@ fun getShortDateFormatter(): DateTimeFormatter = DateTimeFormatter.ofPattern(
|
|||||||
}
|
}
|
||||||
).withZone(ZoneId.systemDefault())
|
).withZone(ZoneId.systemDefault())
|
||||||
|
|
||||||
fun getWeatherIcon(interpretation: WeatherInterpretation): Int {
|
fun getWeatherIcon(interpretation: WeatherInterpretation, isNight: Boolean): Int {
|
||||||
return when (interpretation){
|
return when (interpretation){
|
||||||
WeatherInterpretation.CLEAR -> R.drawable.bx_clear
|
WeatherInterpretation.CLEAR -> if (isNight) R.drawable.moon else R.drawable.bx_clear
|
||||||
WeatherInterpretation.CLOUDY -> R.drawable.bx_cloud
|
WeatherInterpretation.CLOUDY -> R.drawable.bx_cloud
|
||||||
WeatherInterpretation.RAINY -> R.drawable.bx_cloud_rain
|
WeatherInterpretation.RAINY -> R.drawable.bx_cloud_rain
|
||||||
WeatherInterpretation.SNOWY -> R.drawable.bx_cloud_snow
|
WeatherInterpretation.SNOWY -> R.drawable.bx_cloud_snow
|
||||||
@ -74,7 +74,8 @@ fun Weather(
|
|||||||
rowAlignment: Alignment.Horizontal = Alignment.Horizontal.CenterHorizontally,
|
rowAlignment: Alignment.Horizontal = Alignment.Horizontal.CenterHorizontally,
|
||||||
dateLabel: String? = null,
|
dateLabel: String? = null,
|
||||||
singleDisplay: Boolean = false,
|
singleDisplay: Boolean = false,
|
||||||
isImperial: Boolean?
|
isImperial: Boolean?,
|
||||||
|
isNight: Boolean
|
||||||
) {
|
) {
|
||||||
|
|
||||||
val fontSize = if (singleDisplay) 19f else 14f
|
val fontSize = if (singleDisplay) 19f else 14f
|
||||||
@ -83,7 +84,7 @@ fun Weather(
|
|||||||
Row(modifier = GlanceModifier.defaultWeight().wrapContentWidth(), horizontalAlignment = rowAlignment, verticalAlignment = Alignment.CenterVertically) {
|
Row(modifier = GlanceModifier.defaultWeight().wrapContentWidth(), horizontalAlignment = rowAlignment, verticalAlignment = Alignment.CenterVertically) {
|
||||||
Image(
|
Image(
|
||||||
modifier = GlanceModifier.defaultWeight().wrapContentWidth().padding(1.dp),
|
modifier = GlanceModifier.defaultWeight().wrapContentWidth().padding(1.dp),
|
||||||
provider = ImageProvider(getWeatherIcon(current)),
|
provider = ImageProvider(getWeatherIcon(current, isNight)),
|
||||||
contentDescription = "Current weather information",
|
contentDescription = "Current weather information",
|
||||||
contentScale = ContentScale.Fit,
|
contentScale = ContentScale.Fit,
|
||||||
colorFilter = ColorFilter.tint(ColorProvider(Color.Black, Color.White))
|
colorFilter = ColorFilter.tint(ColorProvider(Color.Black, Color.White))
|
||||||
|
|||||||
@ -103,7 +103,8 @@ class WindForecastDataType(karooSystem: KarooSystemService) : ForecastDataType(k
|
|||||||
timeLabel: String,
|
timeLabel: String,
|
||||||
dateLabel: String?,
|
dateLabel: String?,
|
||||||
distance: Double?,
|
distance: Double?,
|
||||||
isImperial: Boolean
|
isImperial: Boolean,
|
||||||
|
isNight: Boolean
|
||||||
) {
|
) {
|
||||||
WindForecast(
|
WindForecast(
|
||||||
arrowBitmap = arrowBitmap,
|
arrowBitmap = arrowBitmap,
|
||||||
@ -112,7 +113,7 @@ class WindForecastDataType(karooSystem: KarooSystemService) : ForecastDataType(k
|
|||||||
gustSpeed = windGusts,
|
gustSpeed = windGusts,
|
||||||
distance = distance,
|
distance = distance,
|
||||||
timeLabel = timeLabel,
|
timeLabel = timeLabel,
|
||||||
isImperial = isImperial
|
isImperial = isImperial,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -120,6 +120,7 @@ fun WeatherScreen(onFinish: () -> Unit) {
|
|||||||
distance = requestedWeatherPosition?.let { l -> location?.distanceTo(l)?.times(1000) },
|
distance = requestedWeatherPosition?.let { l -> location?.distanceTo(l)?.times(1000) },
|
||||||
includeDistanceLabel = false,
|
includeDistanceLabel = false,
|
||||||
isImperial = profile?.preferredUnit?.distance == UserProfile.PreferredUnit.UnitType.IMPERIAL,
|
isImperial = profile?.preferredUnit?.distance == UserProfile.PreferredUnit.UnitType.IMPERIAL,
|
||||||
|
isNight = currentWeatherData?.isNight == true
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -239,7 +240,8 @@ fun WeatherScreen(onFinish: () -> Unit) {
|
|||||||
distance = distanceFromCurrent,
|
distance = distanceFromCurrent,
|
||||||
includeDistanceLabel = true,
|
includeDistanceLabel = true,
|
||||||
precipitationProbability = weatherData?.precipitationProbability?.toInt() ?: 0,
|
precipitationProbability = weatherData?.precipitationProbability?.toInt() ?: 0,
|
||||||
isImperial = profile?.preferredUnit?.distance == UserProfile.PreferredUnit.UnitType.IMPERIAL
|
isImperial = profile?.preferredUnit?.distance == UserProfile.PreferredUnit.UnitType.IMPERIAL,
|
||||||
|
isNight = weatherData?.isNight == true,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -46,7 +46,8 @@ fun WeatherWidget(
|
|||||||
distance: Double? = null,
|
distance: Double? = null,
|
||||||
includeDistanceLabel: Boolean = false,
|
includeDistanceLabel: Boolean = false,
|
||||||
precipitationProbability: Int? = null,
|
precipitationProbability: Int? = null,
|
||||||
isImperial: Boolean
|
isImperial: Boolean,
|
||||||
|
isNight: Boolean
|
||||||
) {
|
) {
|
||||||
val fontSize = 20.sp
|
val fontSize = 20.sp
|
||||||
|
|
||||||
@ -99,7 +100,7 @@ fun WeatherWidget(
|
|||||||
|
|
||||||
// Weather icon (larger)
|
// Weather icon (larger)
|
||||||
Icon(
|
Icon(
|
||||||
painter = painterResource(id = getWeatherIcon(current)),
|
painter = painterResource(id = getWeatherIcon(current, isNight)),
|
||||||
contentDescription = "Current weather",
|
contentDescription = "Current weather",
|
||||||
modifier = Modifier.size(72.dp)
|
modifier = Modifier.size(72.dp)
|
||||||
)
|
)
|
||||||
|
|||||||
@ -16,6 +16,7 @@ data class WeatherData(
|
|||||||
val windDirection: Double,
|
val windDirection: Double,
|
||||||
val windGusts: Double,
|
val windGusts: Double,
|
||||||
val weatherCode: Int,
|
val weatherCode: Int,
|
||||||
val isForecast: Boolean
|
val isForecast: Boolean,
|
||||||
|
val isNight: Boolean
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@ -17,6 +17,7 @@ data class OpenMeteoWeatherData(
|
|||||||
@SerialName("wind_direction_10m") val windDirection: Double,
|
@SerialName("wind_direction_10m") val windDirection: Double,
|
||||||
@SerialName("wind_gusts_10m") val windGusts: Double,
|
@SerialName("wind_gusts_10m") val windGusts: Double,
|
||||||
@SerialName("weather_code") val weatherCode: Int,
|
@SerialName("weather_code") val weatherCode: Int,
|
||||||
|
@SerialName("is_day") val isDay: Int,
|
||||||
) {
|
) {
|
||||||
fun toWeatherData(): WeatherData = WeatherData(
|
fun toWeatherData(): WeatherData = WeatherData(
|
||||||
temperature = temperature,
|
temperature = temperature,
|
||||||
@ -31,6 +32,7 @@ data class OpenMeteoWeatherData(
|
|||||||
weatherCode = weatherCode,
|
weatherCode = weatherCode,
|
||||||
time = time,
|
time = time,
|
||||||
isForecast = false,
|
isForecast = false,
|
||||||
|
isNight = isDay == 0
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -14,6 +14,7 @@ data class OpenMeteoWeatherForecastData(
|
|||||||
@SerialName("wind_speed_10m") val windSpeed: List<Double>,
|
@SerialName("wind_speed_10m") val windSpeed: List<Double>,
|
||||||
@SerialName("wind_direction_10m") val windDirection: List<Double>,
|
@SerialName("wind_direction_10m") val windDirection: List<Double>,
|
||||||
@SerialName("wind_gusts_10m") val windGusts: List<Double>,
|
@SerialName("wind_gusts_10m") val windGusts: List<Double>,
|
||||||
|
@SerialName("is_day") val isDay: List<Int>,
|
||||||
) {
|
) {
|
||||||
fun toWeatherData(): List<WeatherData> {
|
fun toWeatherData(): List<WeatherData> {
|
||||||
return time.mapIndexed { index, t ->
|
return time.mapIndexed { index, t ->
|
||||||
@ -25,6 +26,7 @@ data class OpenMeteoWeatherForecastData(
|
|||||||
windDirection = windDirection[index],
|
windDirection = windDirection[index],
|
||||||
windGusts = windGusts[index],
|
windGusts = windGusts[index],
|
||||||
weatherCode = weatherCode[index],
|
weatherCode = weatherCode[index],
|
||||||
|
isNight = isDay[index] == 0,
|
||||||
time = t,
|
time = t,
|
||||||
isForecast = true,
|
isForecast = true,
|
||||||
)
|
)
|
||||||
|
|||||||
@ -34,10 +34,10 @@ class OpenMeteoWeatherProvider : WeatherProvider {
|
|||||||
val windUnit = if (profile?.preferredUnit?.distance != UserProfile.PreferredUnit.UnitType.IMPERIAL) WindUnit.KILOMETERS_PER_HOUR else WindUnit.MILES_PER_HOUR
|
val windUnit = if (profile?.preferredUnit?.distance != UserProfile.PreferredUnit.UnitType.IMPERIAL) WindUnit.KILOMETERS_PER_HOUR else WindUnit.MILES_PER_HOUR
|
||||||
|
|
||||||
val response = callbackFlow {
|
val response = callbackFlow {
|
||||||
// https://api.open-meteo.com/v1/forecast?latitude=52.52&longitude=13.41¤t=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
|
// 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 lats = gpsCoordinates.joinToString(",") { String.format(Locale.US, "%.6f", it.lat) }
|
||||||
val lons = gpsCoordinates.joinToString(",") { String.format(Locale.US, "%.6f", it.lon) }
|
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=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=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=${windUnit.id}&precipitation_unit=${precipitationUnit.id}&temperature_unit=${temperatureUnit.id}"
|
||||||
|
|
||||||
Log.d(KarooHeadwindExtension.TAG, "Http request to ${url}...")
|
Log.d(KarooHeadwindExtension.TAG, "Http request to ${url}...")
|
||||||
|
|
||||||
|
|||||||
@ -2,6 +2,8 @@ package de.timklge.karooheadwind.weatherprovider.openweathermap
|
|||||||
|
|
||||||
import de.timklge.karooheadwind.weatherprovider.WeatherData
|
import de.timklge.karooheadwind.weatherprovider.WeatherData
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
import java.time.Instant
|
||||||
|
import java.time.ZoneOffset
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class OpenWeatherMapForecastData(
|
data class OpenWeatherMapForecastData(
|
||||||
@ -20,7 +22,16 @@ data class OpenWeatherMapForecastData(
|
|||||||
val snow: Snow? = null,
|
val snow: Snow? = null,
|
||||||
val weather: List<Weather>
|
val weather: List<Weather>
|
||||||
) {
|
) {
|
||||||
fun toWeatherData(): WeatherData = WeatherData(
|
fun toWeatherData(currentWeatherData: OpenWeatherMapWeatherData): WeatherData {
|
||||||
|
val dtInstant = Instant.ofEpochSecond(dt)
|
||||||
|
val sunriseInstant = Instant.ofEpochSecond(currentWeatherData.sunrise)
|
||||||
|
val sunsetInstant = Instant.ofEpochSecond(currentWeatherData.sunset)
|
||||||
|
|
||||||
|
val dtTime = dtInstant.atZone(ZoneOffset.UTC).toLocalTime()
|
||||||
|
val sunriseTime = sunriseInstant.atZone(ZoneOffset.UTC).toLocalTime()
|
||||||
|
val sunsetTime = sunsetInstant.atZone(ZoneOffset.UTC).toLocalTime()
|
||||||
|
|
||||||
|
return WeatherData(
|
||||||
temperature = temp,
|
temperature = temp,
|
||||||
relativeHumidity = humidity.toDouble(),
|
relativeHumidity = humidity.toDouble(),
|
||||||
precipitation = rain?.h1 ?: 0.0,
|
precipitation = rain?.h1 ?: 0.0,
|
||||||
@ -34,6 +45,8 @@ data class OpenWeatherMapForecastData(
|
|||||||
weather.firstOrNull()?.id ?: 800
|
weather.firstOrNull()?.id ?: 800
|
||||||
),
|
),
|
||||||
time = dt,
|
time = dt,
|
||||||
isForecast = true
|
isForecast = true,
|
||||||
|
isNight = dtTime.isBefore(sunriseTime) || dtTime.isAfter(sunsetTime)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -35,6 +35,9 @@ data class OpenWeatherMapWeatherData(
|
|||||||
weather.firstOrNull()?.id ?: 800
|
weather.firstOrNull()?.id ?: 800
|
||||||
),
|
),
|
||||||
time = dt,
|
time = dt,
|
||||||
|
isNight = let {
|
||||||
|
dt !in sunrise..<sunset
|
||||||
|
},
|
||||||
isForecast = false
|
isForecast = false
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -14,10 +14,17 @@ data class OpenWeatherMapWeatherDataForLocation(
|
|||||||
val current: OpenWeatherMapWeatherData,
|
val current: OpenWeatherMapWeatherData,
|
||||||
val hourly: List<OpenWeatherMapForecastData>
|
val hourly: List<OpenWeatherMapForecastData>
|
||||||
){
|
){
|
||||||
fun toWeatherDataForLocation(distanceAlongRoute: Double?): WeatherDataForLocation = WeatherDataForLocation(
|
fun toWeatherDataForLocation(distanceAlongRoute: Double?): WeatherDataForLocation {
|
||||||
|
return WeatherDataForLocation(
|
||||||
current = current.toWeatherData(),
|
current = current.toWeatherData(),
|
||||||
coords = GpsCoordinates(lat, lon, bearing = null, distanceAlongRoute = distanceAlongRoute),
|
coords = GpsCoordinates(
|
||||||
|
lat,
|
||||||
|
lon,
|
||||||
|
bearing = null,
|
||||||
|
distanceAlongRoute = distanceAlongRoute
|
||||||
|
),
|
||||||
timezone = timezone,
|
timezone = timezone,
|
||||||
forecasts = hourly.map { it.toWeatherData() }
|
forecasts = hourly.map { it.toWeatherData(current) }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
BIN
app/src/main/res/drawable/moon.png
Normal file
BIN
app/src/main/res/drawable/moon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.6 KiB |
Loading…
x
Reference in New Issue
Block a user