fix #128: Remove absolute displayed wind speed, text on indicator settings, userwindSpeed datatype
All checks were successful
Build / build (push) Successful in 5m38s
All checks were successful
Build / build (push) Successful in 5m38s
This commit is contained in:
parent
a8f7f53d66
commit
abf2757d08
13
README.md
13
README.md
@ -53,10 +53,11 @@ This app uses Google Crashlytics for crash reporting to help improve stability a
|
|||||||
## Extension Developers: Headwind Data Type
|
## Extension Developers: Headwind Data Type
|
||||||
|
|
||||||
If the user has installed the headwind extension on his karoo, you can stream the headwind data type from other extensions via `karoo-ext`.
|
If the user has installed the headwind extension on his karoo, you can stream the headwind data type from other extensions via `karoo-ext`.
|
||||||
Use extension id `karoo-headwind` with datatype ids `headwind` and `userwindSpeed`.
|
Use extension id `karoo-headwind` with datatype ids `headwind`, `windDirection`, `headwindSpeed`, `windSpeed` etc.
|
||||||
|
|
||||||
- The `headwind` datatype contains a single field that either represents an error code or the wind direction. A `-1.0` indicates missing gps receiption, `-2.0` no weather data, `-3.0` that the headwind extension
|
- The `headwind` datatype contains a single field that either represents an error code or the *relative* wind direction. A `-1.0` indicates missing gps receiption, `-2.0` no weather data, `-3.0` that the headwind extension
|
||||||
has not been set up. Otherwise, the value is the wind direction in degrees; if the user has set the headwind indicator to depict the absolute wind direction, the field will contain the absolute wind direction; otherwise
|
has not been set up. Otherwise, the value is the headwind direction in degrees.
|
||||||
it will contain the headwind direction.
|
- The `windDirection` datatype contains a single field with the *absolute* wind direction in degrees (so 0 = North, 90 = East etc.)
|
||||||
- The `userwindSpeed` datatype contains a single field with the wind speed in the user's defined unit. If the user has set the headwind indicator to show the absolute wind speed,
|
- The `headwindSpeed` datatype contains a single field that contains the *relative* headwind speed in meters per second.
|
||||||
this field will contain the absolute wind speed; otherwise it will contain the headwind speed.
|
- The `windSpeed` datatype contains a single field that contains the *absolute* wind speed in meters per second.
|
||||||
|
- Other datatypes like `windGusts` etc. are also available, see [extension_info.xml](https://github.com/timklge/karoo-headwind/blob/master/app/src/main/res/xml/extension_info.xml)
|
||||||
@ -18,17 +18,6 @@ enum class PrecipitationUnit(val id: String, val label: String, val unitDisplay:
|
|||||||
INCH("inch", "Inch", "in")
|
INCH("inch", "Inch", "in")
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class WindDirectionIndicatorTextSetting(val id: String, val label: String){
|
|
||||||
HEADWIND_SPEED("headwind-speed", "Headwind speed"),
|
|
||||||
WIND_SPEED("absolute-wind-speed", "Absolute wind speed"),
|
|
||||||
NONE("none", "None")
|
|
||||||
}
|
|
||||||
|
|
||||||
enum class WindDirectionIndicatorSetting(val id: String, val label: String){
|
|
||||||
HEADWIND_DIRECTION("headwind-direction", "Headwind"),
|
|
||||||
WIND_DIRECTION("wind-direction", "Absolute wind direction"),
|
|
||||||
}
|
|
||||||
|
|
||||||
enum class TemperatureUnit(val id: String, val label: String, val unitDisplay: String){
|
enum class TemperatureUnit(val id: String, val label: String, val unitDisplay: String){
|
||||||
CELSIUS("celsius", "Celsius (°C)", "°C"),
|
CELSIUS("celsius", "Celsius (°C)", "°C"),
|
||||||
FAHRENHEIT("fahrenheit", "Fahrenheit (°F)", "°F")
|
FAHRENHEIT("fahrenheit", "Fahrenheit (°F)", "°F")
|
||||||
@ -91,8 +80,6 @@ enum class RefreshRate(val id: String, val k2Ms: Long, val k3Ms: Long) {
|
|||||||
@Serializable
|
@Serializable
|
||||||
data class HeadwindSettings(
|
data class HeadwindSettings(
|
||||||
val welcomeDialogAccepted: Boolean = false,
|
val welcomeDialogAccepted: Boolean = false,
|
||||||
val windDirectionIndicatorTextSetting: WindDirectionIndicatorTextSetting = WindDirectionIndicatorTextSetting.HEADWIND_SPEED,
|
|
||||||
val windDirectionIndicatorSetting: WindDirectionIndicatorSetting = WindDirectionIndicatorSetting.HEADWIND_DIRECTION,
|
|
||||||
val roundLocationTo: RoundLocationSetting = RoundLocationSetting.KM_3,
|
val roundLocationTo: RoundLocationSetting = RoundLocationSetting.KM_3,
|
||||||
val forecastedKmPerHour: Int = 20,
|
val forecastedKmPerHour: Int = 20,
|
||||||
val forecastedMilesPerHour: Int = 12,
|
val forecastedMilesPerHour: Int = 12,
|
||||||
|
|||||||
@ -20,7 +20,6 @@ import de.timklge.karooheadwind.datatypes.TailwindAndRideSpeedDataType
|
|||||||
import de.timklge.karooheadwind.datatypes.TailwindDataType
|
import de.timklge.karooheadwind.datatypes.TailwindDataType
|
||||||
import de.timklge.karooheadwind.datatypes.TemperatureDataType
|
import de.timklge.karooheadwind.datatypes.TemperatureDataType
|
||||||
import de.timklge.karooheadwind.datatypes.TemperatureForecastDataType
|
import de.timklge.karooheadwind.datatypes.TemperatureForecastDataType
|
||||||
import de.timklge.karooheadwind.datatypes.UserWindSpeedDataType
|
|
||||||
import de.timklge.karooheadwind.datatypes.WeatherDataType
|
import de.timklge.karooheadwind.datatypes.WeatherDataType
|
||||||
import de.timklge.karooheadwind.datatypes.WeatherForecastDataType
|
import de.timklge.karooheadwind.datatypes.WeatherForecastDataType
|
||||||
import de.timklge.karooheadwind.datatypes.WindDirectionDataType
|
import de.timklge.karooheadwind.datatypes.WindDirectionDataType
|
||||||
@ -81,7 +80,6 @@ class KarooHeadwindExtension : KarooExtension("karoo-headwind", BuildConfig.VERS
|
|||||||
PrecipitationDataType(karooSystem, applicationContext),
|
PrecipitationDataType(karooSystem, applicationContext),
|
||||||
SurfacePressureDataType(karooSystem, applicationContext),
|
SurfacePressureDataType(karooSystem, applicationContext),
|
||||||
SealevelPressureDataType(karooSystem, applicationContext),
|
SealevelPressureDataType(karooSystem, applicationContext),
|
||||||
UserWindSpeedDataType(karooSystem, applicationContext),
|
|
||||||
TemperatureForecastDataType(karooSystem),
|
TemperatureForecastDataType(karooSystem),
|
||||||
PrecipitationForecastDataType(karooSystem),
|
PrecipitationForecastDataType(karooSystem),
|
||||||
WindForecastDataType(karooSystem),
|
WindForecastDataType(karooSystem),
|
||||||
|
|||||||
@ -9,7 +9,6 @@ import androidx.glance.appwidget.GlanceRemoteViews
|
|||||||
import de.timklge.karooheadwind.HeadingResponse
|
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.WindDirectionIndicatorSetting
|
|
||||||
import de.timklge.karooheadwind.getRelativeHeadingFlow
|
import de.timklge.karooheadwind.getRelativeHeadingFlow
|
||||||
import de.timklge.karooheadwind.streamCurrentWeatherData
|
import de.timklge.karooheadwind.streamCurrentWeatherData
|
||||||
import de.timklge.karooheadwind.streamDatatypeIsVisible
|
import de.timklge.karooheadwind.streamDatatypeIsVisible
|
||||||
@ -17,6 +16,7 @@ import de.timklge.karooheadwind.streamSettings
|
|||||||
import de.timklge.karooheadwind.streamUserProfile
|
import de.timklge.karooheadwind.streamUserProfile
|
||||||
import de.timklge.karooheadwind.throttle
|
import de.timklge.karooheadwind.throttle
|
||||||
import de.timklge.karooheadwind.util.msInUserUnit
|
import de.timklge.karooheadwind.util.msInUserUnit
|
||||||
|
import de.timklge.karooheadwind.weatherprovider.WeatherData
|
||||||
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.Emitter
|
import io.hammerhead.karooext.internal.Emitter
|
||||||
@ -39,6 +39,7 @@ import kotlinx.coroutines.flow.filter
|
|||||||
import kotlinx.coroutines.flow.first
|
import kotlinx.coroutines.flow.first
|
||||||
import kotlinx.coroutines.flow.flow
|
import kotlinx.coroutines.flow.flow
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlin.math.cos
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
@OptIn(ExperimentalGlanceRemoteViewsApi::class)
|
@OptIn(ExperimentalGlanceRemoteViewsApi::class)
|
||||||
@ -84,10 +85,7 @@ class HeadwindDirectionDataType(
|
|||||||
|
|
||||||
returnValue = errorCode
|
returnValue = errorCode
|
||||||
} else {
|
} else {
|
||||||
var windDirection = when (streamData.settings.windDirectionIndicatorSetting){
|
var windDirection = value
|
||||||
WindDirectionIndicatorSetting.HEADWIND_DIRECTION -> value
|
|
||||||
WindDirectionIndicatorSetting.WIND_DIRECTION -> streamData.absoluteWindDirection + 180
|
|
||||||
}
|
|
||||||
|
|
||||||
if (windDirection < 0) windDirection += 360
|
if (windDirection < 0) windDirection += 360
|
||||||
|
|
||||||
@ -154,7 +152,7 @@ class HeadwindDirectionDataType(
|
|||||||
val directionFlow = streamValues()
|
val directionFlow = streamValues()
|
||||||
val speedFlow = flow {
|
val speedFlow = flow {
|
||||||
emit(0.0)
|
emit(0.0)
|
||||||
emitAll(UserWindSpeedDataType.streamValues(context, karooSystem))
|
emitAll(streamValues(context, karooSystem))
|
||||||
}
|
}
|
||||||
|
|
||||||
combine(directionFlow, speedFlow, karooSystem.streamDatatypeIsVisible(dataTypeId), karooSystem.streamUserProfile()) { direction, speed, isVisible, profile ->
|
combine(directionFlow, speedFlow, karooSystem.streamDatatypeIsVisible(dataTypeId), karooSystem.streamUserProfile()) { direction, speed, isVisible, profile ->
|
||||||
@ -203,6 +201,26 @@ class HeadwindDirectionDataType(
|
|||||||
const val ERROR_NO_GPS = -1
|
const val ERROR_NO_GPS = -1
|
||||||
const val ERROR_NO_WEATHER_DATA = -2
|
const val ERROR_NO_WEATHER_DATA = -2
|
||||||
const val ERROR_APP_NOT_SET_UP = -3
|
const val ERROR_APP_NOT_SET_UP = -3
|
||||||
|
|
||||||
|
fun streamValues(context: Context, karooSystem: KarooSystemService): Flow<Double> = flow {
|
||||||
|
data class StreamData(
|
||||||
|
val headingResponse: HeadingResponse,
|
||||||
|
val weatherResponse: WeatherData?,
|
||||||
|
val settings: HeadwindSettings
|
||||||
|
)
|
||||||
|
|
||||||
|
combine(karooSystem.getRelativeHeadingFlow(context), context.streamCurrentWeatherData(karooSystem), context.streamSettings(karooSystem)) { headingResponse, weatherResponse, settings ->
|
||||||
|
StreamData(headingResponse, weatherResponse, settings)
|
||||||
|
}.filter { it.weatherResponse != null }
|
||||||
|
.collect { streamData ->
|
||||||
|
val windSpeed = streamData.weatherResponse?.windSpeed ?: 0.0
|
||||||
|
val windDirection = (streamData.headingResponse as? HeadingResponse.Value)?.diff ?: 0.0
|
||||||
|
|
||||||
|
val headwindSpeed = cos((windDirection + 180) * Math.PI / 180.0) * windSpeed
|
||||||
|
|
||||||
|
emit(headwindSpeed)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -15,8 +15,6 @@ 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.R
|
import de.timklge.karooheadwind.R
|
||||||
import de.timklge.karooheadwind.WindDirectionIndicatorSetting
|
|
||||||
import de.timklge.karooheadwind.WindDirectionIndicatorTextSetting
|
|
||||||
import de.timklge.karooheadwind.datatypes.TailwindDataType.StreamData
|
import de.timklge.karooheadwind.datatypes.TailwindDataType.StreamData
|
||||||
import de.timklge.karooheadwind.getRelativeHeadingFlow
|
import de.timklge.karooheadwind.getRelativeHeadingFlow
|
||||||
import de.timklge.karooheadwind.streamCurrentWeatherData
|
import de.timklge.karooheadwind.streamCurrentWeatherData
|
||||||
@ -161,10 +159,7 @@ class TailwindAndRideSpeedDataType(
|
|||||||
}
|
}
|
||||||
|
|
||||||
val windSpeed = streamData.windSpeed
|
val windSpeed = streamData.windSpeed
|
||||||
val windDirection = when (streamData.settings.windDirectionIndicatorSetting){
|
val windDirection = streamData.headingResponse.diff
|
||||||
WindDirectionIndicatorSetting.HEADWIND_DIRECTION -> streamData.headingResponse.diff
|
|
||||||
WindDirectionIndicatorSetting.WIND_DIRECTION -> streamData.absoluteWindDirection + 180
|
|
||||||
}
|
|
||||||
|
|
||||||
val rideSpeedInUserUnit = msInUserUnit(streamData.rideSpeed ?: 0.0, streamData.isImperial)
|
val rideSpeedInUserUnit = msInUserUnit(streamData.rideSpeed ?: 0.0, streamData.isImperial)
|
||||||
val text = String.format(Locale.current.platformLocale, "%.1f", rideSpeedInUserUnit)
|
val text = String.format(Locale.current.platformLocale, "%.1f", rideSpeedInUserUnit)
|
||||||
@ -181,8 +176,7 @@ class TailwindAndRideSpeedDataType(
|
|||||||
|
|
||||||
val windSpeedUserUnit = msInUserUnit(windSpeed, streamData.isImperial)
|
val windSpeedUserUnit = msInUserUnit(windSpeed, streamData.isImperial)
|
||||||
|
|
||||||
val subtextWithSign = when (streamData.settings.windDirectionIndicatorTextSetting) {
|
val subtextWithSign = let {
|
||||||
WindDirectionIndicatorTextSetting.HEADWIND_SPEED -> {
|
|
||||||
val headwindSpeed = cos( (windDirection + 180) * Math.PI / 180.0) * windSpeed
|
val headwindSpeed = cos( (windDirection + 180) * Math.PI / 180.0) * windSpeed
|
||||||
headwindSpeed.roundToInt().toString()
|
headwindSpeed.roundToInt().toString()
|
||||||
|
|
||||||
@ -194,19 +188,15 @@ class TailwindAndRideSpeedDataType(
|
|||||||
|
|
||||||
"$sign${headwindSpeedUserUnit.roundToInt().absoluteValue} ${windSpeedUserUnit.roundToInt()}${gustSpeedAddon}"
|
"$sign${headwindSpeedUserUnit.roundToInt().absoluteValue} ${windSpeedUserUnit.roundToInt()}${gustSpeedAddon}"
|
||||||
}
|
}
|
||||||
WindDirectionIndicatorTextSetting.WIND_SPEED -> "${windSpeedUserUnit.roundToInt()}${gustSpeedAddon}"
|
|
||||||
WindDirectionIndicatorTextSetting.NONE -> ""
|
|
||||||
}
|
|
||||||
|
|
||||||
var dayColor = Color(ContextCompat.getColor(context, R.color.black))
|
var dayColor = Color(ContextCompat.getColor(context, R.color.black))
|
||||||
var nightColor = Color(ContextCompat.getColor(context, R.color.white))
|
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 headwindSpeed = cos( (windDirection + 180) * Math.PI / 180.0) * windSpeed
|
||||||
val windSpeedInKmh = headwindSpeed * 3.6
|
val windSpeedInKmh = headwindSpeed * 3.6
|
||||||
dayColor = interpolateWindColor(windSpeedInKmh, false, context)
|
dayColor = interpolateWindColor(windSpeedInKmh, false, context)
|
||||||
nightColor = interpolateWindColor(windSpeedInKmh, true, context)
|
nightColor = interpolateWindColor(windSpeedInKmh, true, context)
|
||||||
}
|
|
||||||
|
|
||||||
val result = glance.compose(context, DpSize.Unspecified) {
|
val result = glance.compose(context, DpSize.Unspecified) {
|
||||||
HeadwindDirection(
|
HeadwindDirection(
|
||||||
|
|||||||
@ -12,8 +12,6 @@ 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.R
|
import de.timklge.karooheadwind.R
|
||||||
import de.timklge.karooheadwind.WindDirectionIndicatorSetting
|
|
||||||
import de.timklge.karooheadwind.WindDirectionIndicatorTextSetting
|
|
||||||
import de.timklge.karooheadwind.getRelativeHeadingFlow
|
import de.timklge.karooheadwind.getRelativeHeadingFlow
|
||||||
import de.timklge.karooheadwind.streamCurrentWeatherData
|
import de.timklge.karooheadwind.streamCurrentWeatherData
|
||||||
import de.timklge.karooheadwind.streamDataFlow
|
import de.timklge.karooheadwind.streamDataFlow
|
||||||
@ -147,13 +145,9 @@ class TailwindDataType(
|
|||||||
}
|
}
|
||||||
|
|
||||||
val windSpeed = streamData.windSpeed
|
val windSpeed = streamData.windSpeed
|
||||||
val windDirection = when (streamData.settings.windDirectionIndicatorSetting){
|
val windDirection = streamData.headingResponse.diff
|
||||||
WindDirectionIndicatorSetting.HEADWIND_DIRECTION -> streamData.headingResponse.diff
|
|
||||||
WindDirectionIndicatorSetting.WIND_DIRECTION -> streamData.absoluteWindDirection + 180
|
|
||||||
}
|
|
||||||
|
|
||||||
val mainText = when (streamData.settings.windDirectionIndicatorTextSetting) {
|
val mainText = let {
|
||||||
WindDirectionIndicatorTextSetting.HEADWIND_SPEED -> {
|
|
||||||
val headwindSpeed = cos( (windDirection + 180) * Math.PI / 180.0) * windSpeed
|
val headwindSpeed = cos( (windDirection + 180) * Math.PI / 180.0) * windSpeed
|
||||||
headwindSpeed.roundToInt().toString()
|
headwindSpeed.roundToInt().toString()
|
||||||
|
|
||||||
@ -165,9 +159,6 @@ class TailwindDataType(
|
|||||||
|
|
||||||
"$sign${headwindSpeedUserUnit.roundToInt().absoluteValue}"
|
"$sign${headwindSpeedUserUnit.roundToInt().absoluteValue}"
|
||||||
}
|
}
|
||||||
WindDirectionIndicatorTextSetting.WIND_SPEED -> msInUserUnit(windSpeed, streamData.isImperial).roundToInt().toString()
|
|
||||||
WindDirectionIndicatorTextSetting.NONE -> ""
|
|
||||||
}
|
|
||||||
|
|
||||||
val windSpeedUserUnit = msInUserUnit(windSpeed, streamData.isImperial)
|
val windSpeedUserUnit = msInUserUnit(windSpeed, streamData.isImperial)
|
||||||
val gustSpeedUserUnit = msInUserUnit(streamData.gustSpeed ?: 0.0, streamData.isImperial)
|
val gustSpeedUserUnit = msInUserUnit(streamData.gustSpeed ?: 0.0, streamData.isImperial)
|
||||||
@ -177,12 +168,10 @@ class TailwindDataType(
|
|||||||
var dayColor = Color(ContextCompat.getColor(context, R.color.black))
|
var dayColor = Color(ContextCompat.getColor(context, R.color.black))
|
||||||
var nightColor = Color(ContextCompat.getColor(context, R.color.white))
|
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 headwindSpeed = cos( (windDirection + 180) * Math.PI / 180.0) * windSpeed
|
||||||
val windSpeedInKmh = headwindSpeed * 3.6
|
val windSpeedInKmh = headwindSpeed * 3.6
|
||||||
dayColor = interpolateWindColor(windSpeedInKmh, false, context)
|
dayColor = interpolateWindColor(windSpeedInKmh, false, context)
|
||||||
nightColor = interpolateWindColor(windSpeedInKmh, true, context)
|
nightColor = interpolateWindColor(windSpeedInKmh, true, context)
|
||||||
}
|
|
||||||
|
|
||||||
val result = glance.compose(context, DpSize.Unspecified) {
|
val result = glance.compose(context, DpSize.Unspecified) {
|
||||||
HeadwindDirection(
|
HeadwindDirection(
|
||||||
|
|||||||
@ -1,75 +0,0 @@
|
|||||||
package de.timklge.karooheadwind.datatypes
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import de.timklge.karooheadwind.HeadingResponse
|
|
||||||
import de.timklge.karooheadwind.HeadwindSettings
|
|
||||||
import de.timklge.karooheadwind.weatherprovider.WeatherData
|
|
||||||
import de.timklge.karooheadwind.WindDirectionIndicatorTextSetting
|
|
||||||
import de.timklge.karooheadwind.getRelativeHeadingFlow
|
|
||||||
import de.timklge.karooheadwind.streamCurrentWeatherData
|
|
||||||
import de.timklge.karooheadwind.streamSettings
|
|
||||||
import io.hammerhead.karooext.KarooSystemService
|
|
||||||
import io.hammerhead.karooext.extension.DataTypeImpl
|
|
||||||
import io.hammerhead.karooext.internal.Emitter
|
|
||||||
import io.hammerhead.karooext.models.DataPoint
|
|
||||||
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
|
|
||||||
|
|
||||||
class UserWindSpeedDataType(
|
|
||||||
private val karooSystem: KarooSystemService,
|
|
||||||
private val context: Context
|
|
||||||
) : DataTypeImpl("karoo-headwind", "userwindSpeed"){
|
|
||||||
|
|
||||||
data class StreamData(val headingResponse: HeadingResponse, val weatherResponse: WeatherData?, val settings: HeadwindSettings)
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
fun streamValues(context: Context, karooSystem: KarooSystemService): Flow<Double> = flow {
|
|
||||||
karooSystem.getRelativeHeadingFlow(context)
|
|
||||||
.combine(context.streamCurrentWeatherData(karooSystem)) { value, data -> value to data }
|
|
||||||
.combine(context.streamSettings(karooSystem)) { (value, data), settings ->
|
|
||||||
StreamData(value, data, settings)
|
|
||||||
}
|
|
||||||
.filter { it.weatherResponse != null }
|
|
||||||
.collect { streamData ->
|
|
||||||
val windSpeed = streamData.weatherResponse?.windSpeed ?: 0.0
|
|
||||||
val windDirection = (streamData.headingResponse as? HeadingResponse.Value)?.diff ?: 0.0
|
|
||||||
|
|
||||||
if (streamData.settings.windDirectionIndicatorTextSetting == WindDirectionIndicatorTextSetting.HEADWIND_SPEED){
|
|
||||||
val headwindSpeed = cos((windDirection + 180) * Math.PI / 180.0) * windSpeed
|
|
||||||
|
|
||||||
emit(headwindSpeed)
|
|
||||||
} else {
|
|
||||||
emit(windSpeed)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun startStream(emitter: Emitter<StreamState>) {
|
|
||||||
val job = CoroutineScope(Dispatchers.IO).launch {
|
|
||||||
streamValues(context, karooSystem)
|
|
||||||
.collect { value ->
|
|
||||||
emitter.onNext(
|
|
||||||
StreamState.Streaming(
|
|
||||||
DataPoint(
|
|
||||||
dataTypeId,
|
|
||||||
mapOf(DataType.Field.SINGLE to value)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
emitter.setCancellable {
|
|
||||||
job.cancel()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -42,8 +42,6 @@ import de.timklge.karooheadwind.KarooHeadwindExtension
|
|||||||
import de.timklge.karooheadwind.RefreshRate
|
import de.timklge.karooheadwind.RefreshRate
|
||||||
import de.timklge.karooheadwind.RoundLocationSetting
|
import de.timklge.karooheadwind.RoundLocationSetting
|
||||||
import de.timklge.karooheadwind.WeatherDataProvider
|
import de.timklge.karooheadwind.WeatherDataProvider
|
||||||
import de.timklge.karooheadwind.WindDirectionIndicatorSetting
|
|
||||||
import de.timklge.karooheadwind.WindDirectionIndicatorTextSetting
|
|
||||||
import de.timklge.karooheadwind.datatypes.GpsCoordinates
|
import de.timklge.karooheadwind.datatypes.GpsCoordinates
|
||||||
import de.timklge.karooheadwind.saveSettings
|
import de.timklge.karooheadwind.saveSettings
|
||||||
import de.timklge.karooheadwind.streamSettings
|
import de.timklge.karooheadwind.streamSettings
|
||||||
@ -64,16 +62,6 @@ fun SettingsScreen(onFinish: () -> Unit) {
|
|||||||
val karooSystem = remember { KarooSystemService(ctx) }
|
val karooSystem = remember { KarooSystemService(ctx) }
|
||||||
|
|
||||||
var refreshRateSetting by remember { mutableStateOf(RefreshRate.STANDARD) }
|
var refreshRateSetting by remember { mutableStateOf(RefreshRate.STANDARD) }
|
||||||
var selectedWindDirectionIndicatorTextSetting by remember {
|
|
||||||
mutableStateOf(
|
|
||||||
WindDirectionIndicatorTextSetting.HEADWIND_SPEED
|
|
||||||
)
|
|
||||||
}
|
|
||||||
var selectedWindDirectionIndicatorSetting by remember {
|
|
||||||
mutableStateOf(
|
|
||||||
WindDirectionIndicatorSetting.HEADWIND_DIRECTION
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
var selectedRoundLocationSetting by remember { mutableStateOf(RoundLocationSetting.KM_3) }
|
var selectedRoundLocationSetting by remember { mutableStateOf(RoundLocationSetting.KM_3) }
|
||||||
var forecastKmPerHour by remember { mutableStateOf("20") }
|
var forecastKmPerHour by remember { mutableStateOf("20") }
|
||||||
@ -88,8 +76,6 @@ fun SettingsScreen(onFinish: () -> Unit) {
|
|||||||
|
|
||||||
LaunchedEffect(Unit) {
|
LaunchedEffect(Unit) {
|
||||||
ctx.streamSettings(karooSystem).collect { settings ->
|
ctx.streamSettings(karooSystem).collect { settings ->
|
||||||
selectedWindDirectionIndicatorTextSetting = settings.windDirectionIndicatorTextSetting
|
|
||||||
selectedWindDirectionIndicatorSetting = settings.windDirectionIndicatorSetting
|
|
||||||
selectedRoundLocationSetting = settings.roundLocationTo
|
selectedRoundLocationSetting = settings.roundLocationTo
|
||||||
forecastKmPerHour = settings.forecastedKmPerHour.toString()
|
forecastKmPerHour = settings.forecastedKmPerHour.toString()
|
||||||
forecastMilesPerHour = settings.forecastedMilesPerHour.toString()
|
forecastMilesPerHour = settings.forecastedMilesPerHour.toString()
|
||||||
@ -118,8 +104,6 @@ fun SettingsScreen(onFinish: () -> Unit) {
|
|||||||
|
|
||||||
val newSettings = HeadwindSettings(
|
val newSettings = HeadwindSettings(
|
||||||
welcomeDialogAccepted = true,
|
welcomeDialogAccepted = true,
|
||||||
windDirectionIndicatorSetting = selectedWindDirectionIndicatorSetting,
|
|
||||||
windDirectionIndicatorTextSetting = selectedWindDirectionIndicatorTextSetting,
|
|
||||||
roundLocationTo = selectedRoundLocationSetting,
|
roundLocationTo = selectedRoundLocationSetting,
|
||||||
forecastedMilesPerHour = forecastMilesPerHour.toIntOrNull()?.coerceIn(3, 30) ?: 12,
|
forecastedMilesPerHour = forecastMilesPerHour.toIntOrNull()?.coerceIn(3, 30) ?: 12,
|
||||||
forecastedKmPerHour = forecastKmPerHour.toIntOrNull()?.coerceIn(5, 50) ?: 20,
|
forecastedKmPerHour = forecastKmPerHour.toIntOrNull()?.coerceIn(5, 50) ?: 20,
|
||||||
@ -165,37 +149,6 @@ fun SettingsScreen(onFinish: () -> Unit) {
|
|||||||
refreshRateSetting = RefreshRate.entries.find { unit -> unit.id == selectedOption.id }!!
|
refreshRateSetting = RefreshRate.entries.find { unit -> unit.id == selectedOption.id }!!
|
||||||
}
|
}
|
||||||
|
|
||||||
val windDirectionIndicatorSettingDropdownOptions =
|
|
||||||
WindDirectionIndicatorSetting.entries.toList().map { unit -> DropdownOption(unit.id, unit.label) }
|
|
||||||
val windDirectionIndicatorSettingSelection by remember(selectedWindDirectionIndicatorSetting) {
|
|
||||||
mutableStateOf(windDirectionIndicatorSettingDropdownOptions.find { option -> option.id == selectedWindDirectionIndicatorSetting.id }!!)
|
|
||||||
}
|
|
||||||
Dropdown(
|
|
||||||
label = "Wind Direction Indicator",
|
|
||||||
options = windDirectionIndicatorSettingDropdownOptions,
|
|
||||||
selected = windDirectionIndicatorSettingSelection
|
|
||||||
) { selectedOption ->
|
|
||||||
selectedWindDirectionIndicatorSetting =
|
|
||||||
WindDirectionIndicatorSetting.entries.find { unit -> unit.id == selectedOption.id }!!
|
|
||||||
}
|
|
||||||
|
|
||||||
val windDirectionIndicatorTextSettingDropdownOptions =
|
|
||||||
WindDirectionIndicatorTextSetting.entries.toList()
|
|
||||||
.map { unit -> DropdownOption(unit.id, unit.label) }
|
|
||||||
val windDirectionIndicatorTextSettingSelection by remember(
|
|
||||||
selectedWindDirectionIndicatorTextSetting
|
|
||||||
) {
|
|
||||||
mutableStateOf(windDirectionIndicatorTextSettingDropdownOptions.find { option -> option.id == selectedWindDirectionIndicatorTextSetting.id }!!)
|
|
||||||
}
|
|
||||||
Dropdown(
|
|
||||||
label = "Text on Headwind Indicator",
|
|
||||||
options = windDirectionIndicatorTextSettingDropdownOptions,
|
|
||||||
selected = windDirectionIndicatorTextSettingSelection
|
|
||||||
) { selectedOption ->
|
|
||||||
selectedWindDirectionIndicatorTextSetting =
|
|
||||||
WindDirectionIndicatorTextSetting.entries.find { unit -> unit.id == selectedOption.id }!!
|
|
||||||
}
|
|
||||||
|
|
||||||
val roundLocationDropdownOptions = RoundLocationSetting.entries.toList()
|
val roundLocationDropdownOptions = RoundLocationSetting.entries.toList()
|
||||||
.map { unit -> DropdownOption(unit.id, unit.label) }
|
.map { unit -> DropdownOption(unit.id, unit.label) }
|
||||||
val roundLocationInitialSelection by remember(selectedRoundLocationSetting) {
|
val roundLocationInitialSelection by remember(selectedRoundLocationSetting) {
|
||||||
|
|||||||
@ -75,13 +75,6 @@
|
|||||||
icon="@drawable/wind"
|
icon="@drawable/wind"
|
||||||
typeId="headwindSpeed" />
|
typeId="headwindSpeed" />
|
||||||
|
|
||||||
<DataType
|
|
||||||
description="@string/userwind_speed_description"
|
|
||||||
displayName="@string/userwind_speed"
|
|
||||||
graphical="false"
|
|
||||||
icon="@drawable/wind"
|
|
||||||
typeId="userwindSpeed" />
|
|
||||||
|
|
||||||
<DataType
|
<DataType
|
||||||
description="@string/relativeHumidity_description"
|
description="@string/relativeHumidity_description"
|
||||||
displayName="@string/relativeHumidity"
|
displayName="@string/relativeHumidity"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user