Fix gps flow reset
This commit is contained in:
parent
d3109e459c
commit
e6ee80e60e
@ -7,5 +7,5 @@
|
||||
"latestVersionCode": 7,
|
||||
"developer": "timklge",
|
||||
"description": "Provides headwind direction, wind speed and other weather data fields",
|
||||
"releaseNotes": "Add hourly forecast and temperature datafields. Show error message in fields if no weather data or gps is available."
|
||||
"releaseNotes": "Adds hourly forecast. Shows error message in fields if weather data or gps are unavailable and remembers last known gps position."
|
||||
}
|
||||
@ -39,13 +39,13 @@ import kotlinx.coroutines.FlowPreview
|
||||
import kotlinx.coroutines.TimeoutCancellationException
|
||||
import kotlinx.coroutines.channels.awaitClose
|
||||
import kotlinx.coroutines.channels.trySendBlocking
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.callbackFlow
|
||||
import kotlinx.coroutines.flow.catch
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.flow.filter
|
||||
import kotlinx.coroutines.flow.filterNot
|
||||
import kotlinx.coroutines.flow.emitAll
|
||||
import kotlinx.coroutines.flow.filterNotNull
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.flow.flow
|
||||
@ -124,10 +124,8 @@ suspend fun getErrorWidget(glance: GlanceRemoteViews, context: Context, settings
|
||||
"Headwind app not set up"
|
||||
} else if (headingResponse is HeadingResponse.NoGps){
|
||||
"No GPS signal"
|
||||
} else if (headingResponse is HeadingResponse.NoWeatherData) {
|
||||
"No weather data"
|
||||
} else {
|
||||
"Unknown error"
|
||||
"Weather data download failed"
|
||||
}
|
||||
|
||||
Log.d(KarooHeadwindExtension.TAG, "Error widget: $errorMessage")
|
||||
@ -334,47 +332,61 @@ fun KarooSystemService.getHeadingFlow(context: Context): Flow<HeadingResponse> {
|
||||
if (newAcc.size > 3) newAcc.drop(1) else newAcc
|
||||
}
|
||||
.map { data ->
|
||||
if (data.isEmpty()) return@map HeadingResponse.NoGps
|
||||
Log.i(KarooHeadwindExtension.TAG, "Heading value: $data")
|
||||
|
||||
if (data.isEmpty()) return@map HeadingResponse.NoGps
|
||||
if (data.firstOrNull() !is HeadingResponse.Value) return@map data.first()
|
||||
|
||||
val avgValues = data.mapNotNull { (it as? HeadingResponse.Value)?.diff }
|
||||
|
||||
if (avgValues.isEmpty()) return@map HeadingResponse.NoGps
|
||||
|
||||
val avg = avgValues.average()
|
||||
|
||||
if (data.all { it is HeadingResponse.Value }) {
|
||||
val avg = data.mapNotNull { (it as? HeadingResponse.Value)?.diff }.average()
|
||||
HeadingResponse.Value(avg)
|
||||
} else {
|
||||
data.first()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun <T> concatenate(vararg flows: Flow<T>) = flow {
|
||||
var hadNullValue = false
|
||||
|
||||
for (flow in flows) {
|
||||
flow.collect { value ->
|
||||
if (!hadNullValue) {
|
||||
emitAll(flow)
|
||||
}
|
||||
}
|
||||
|
||||
fun<T> Flow<T>.dropNullsIfNullEncountered(): Flow<T?> = flow {
|
||||
var hadValue = false
|
||||
|
||||
collect { value ->
|
||||
if (!hadValue) {
|
||||
emit(value)
|
||||
if (value == null) hadNullValue = true
|
||||
if (value != null) hadValue = true
|
||||
} else {
|
||||
if (value != null) emit(value)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(FlowPreview::class)
|
||||
suspend fun KarooSystemService.updateLastKnownGps(context: Context) {
|
||||
while (true) {
|
||||
getGpsCoordinateFlow(context)
|
||||
.filterNotNull()
|
||||
.throttle(60 * 1_000) // Only update last known gps position once every minute
|
||||
.collect { gps ->
|
||||
saveLastKnownPosition(context, gps)
|
||||
}
|
||||
delay(1_000)
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(FlowPreview::class)
|
||||
fun KarooSystemService.getGpsCoordinateFlow(context: Context): Flow<GpsCoordinates?> {
|
||||
// return flowOf(GpsCoordinates(52.5164069,13.3784))
|
||||
|
||||
val initialFlow = flow<GpsCoordinates> { context.getLastKnownPosition() }
|
||||
val initialFlow = flow {
|
||||
val lastKnownPosition = context.getLastKnownPosition()
|
||||
if (lastKnownPosition != null) emit(lastKnownPosition)
|
||||
}
|
||||
|
||||
val gpsFlow = streamDataFlow(DataType.Type.LOCATION)
|
||||
.map { (it as? StreamState.Streaming)?.dataPoint?.values }
|
||||
@ -384,10 +396,10 @@ fun KarooSystemService.getGpsCoordinateFlow(context: Context): Flow<GpsCoordinat
|
||||
val bearing = values?.get(DataType.Field.LOC_BEARING)
|
||||
|
||||
if (lat != null && lon != null){
|
||||
Log.d(KarooHeadwindExtension.TAG, "Updated gps coordinates: $lat $lon")
|
||||
// Log.d(KarooHeadwindExtension.TAG, "Updated gps coordinates: $lat $lon")
|
||||
GpsCoordinates(lat, lon, bearing)
|
||||
} else {
|
||||
Log.w(KarooHeadwindExtension.TAG, "Gps unavailable: $values")
|
||||
// Log.w(KarooHeadwindExtension.TAG, "Gps unavailable: $values")
|
||||
null
|
||||
}
|
||||
}
|
||||
@ -397,16 +409,7 @@ fun KarooSystemService.getGpsCoordinateFlow(context: Context): Flow<GpsCoordinat
|
||||
return concatenatedFlow
|
||||
.combine(context.streamSettings(this)) { gps, settings -> gps to settings }
|
||||
.map { (gps, settings) ->
|
||||
val rounded = gps?.round(settings.roundLocationTo.km.toDouble())
|
||||
if (rounded != null) Log.d(KarooHeadwindExtension.TAG, "Round location to ${settings.roundLocationTo.km} - $rounded")
|
||||
rounded
|
||||
gps?.round(settings.roundLocationTo.km.toDouble())
|
||||
}
|
||||
.distinctUntilChanged { old, new ->
|
||||
if (old != null && new != null) {
|
||||
old.distanceTo(new).absoluteValue < 0.001
|
||||
} else {
|
||||
old == new
|
||||
}
|
||||
}
|
||||
.debounce(Duration.ofSeconds(10))
|
||||
.dropNullsIfNullEncountered()
|
||||
}
|
||||
@ -23,15 +23,20 @@ import io.hammerhead.karooext.models.UserProfile
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.FlowPreview
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.flow.filter
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.retry
|
||||
import kotlinx.coroutines.flow.transformLatest
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.time.debounce
|
||||
import java.time.Duration
|
||||
import kotlin.math.absoluteValue
|
||||
import kotlin.time.Duration.Companion.hours
|
||||
import kotlin.time.Duration.Companion.minutes
|
||||
|
||||
@ -67,7 +72,7 @@ class KarooHeadwindExtension : KarooExtension("karoo-headwind", "1.1.3") {
|
||||
data class StreamData(val settings: HeadwindSettings, val gps: GpsCoordinates?,
|
||||
val profile: UserProfile? = null)
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
@OptIn(ExperimentalCoroutinesApi::class, FlowPreview::class)
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
|
||||
@ -86,6 +91,14 @@ class KarooHeadwindExtension : KarooExtension("karoo-headwind", "1.1.3") {
|
||||
|
||||
val gpsFlow = karooSystem
|
||||
.getGpsCoordinateFlow(this@KarooHeadwindExtension)
|
||||
.distinctUntilChanged { old, new ->
|
||||
if (old != null && new != null) {
|
||||
old.distanceTo(new).absoluteValue < 0.001
|
||||
} else {
|
||||
old == new
|
||||
}
|
||||
}
|
||||
.debounce(Duration.ofSeconds(5))
|
||||
.transformLatest { value: GpsCoordinates? ->
|
||||
while(true){
|
||||
emit(value)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user