Loading cardinal-android/app/src/main/java/earth/maps/cardinal/data/LocationRepository.kt +5 −1 Original line number Diff line number Diff line Loading @@ -54,7 +54,7 @@ class LocationRepository @Inject constructor( private companion object { private const val LOCATION_REQUEST_INTERVAL_MS = 15000L // 15 seconds private const val LOCATION_REQUEST_TIMEOUT_MS = 5000L // 5 seconds private const val CONTINUOUS_LOCATION_UPDATE_INTERVAL_MS = 5000L // 5 seconds private const val CONTINUOUS_LOCATION_UPDATE_INTERVAL_MS = 1000L // 1 second private const val CONTINUOUS_LOCATION_UPDATE_DISTANCE_M = 5f // 5 meters private const val GPS_PROVIDER_TIMEOUT_MS = 10_000L // 10 seconds - discard fused locations if fused has updated within this timeout Loading Loading @@ -130,6 +130,10 @@ class LocationRepository @Inject constructor( } } fun getLastLocation(): Location? { return lastRequestedLocation } fun fromNameAndLatLng(name: String?, latLng: LatLng): Place { return Place( name = name ?: context.getString(R.string.unnamed_location), Loading cardinal-android/app/src/main/java/earth/maps/cardinal/routing/FerrostarWrapper.kt +57 −2 Original line number Diff line number Diff line Loading @@ -20,25 +20,40 @@ package earth.maps.cardinal.routing import android.content.Context import com.stadiamaps.ferrostar.composeui.notification.DefaultForegroundNotificationBuilder import com.stadiamaps.ferrostar.core.AndroidSystemLocationProvider import com.stadiamaps.ferrostar.core.AndroidTtsObserver import com.stadiamaps.ferrostar.core.FerrostarCore import com.stadiamaps.ferrostar.core.LocationProvider import com.stadiamaps.ferrostar.core.LocationUpdateListener import com.stadiamaps.ferrostar.core.http.OkHttpClientProvider import com.stadiamaps.ferrostar.core.service.FerrostarForegroundServiceManager import com.stadiamaps.ferrostar.core.service.ForegroundServiceManager import com.stadiamaps.ferrostar.core.toUserLocation import earth.maps.cardinal.data.LocationRepository import earth.maps.cardinal.data.OrientationRepository import earth.maps.cardinal.data.RoutingMode import earth.maps.cardinal.data.room.RoutingProfileRepository import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import okhttp3.OkHttpClient import uniffi.ferrostar.CourseFiltering import uniffi.ferrostar.Heading import uniffi.ferrostar.NavigationControllerConfig import uniffi.ferrostar.RouteAdapter import uniffi.ferrostar.RouteDeviationTracking import uniffi.ferrostar.UserLocation import uniffi.ferrostar.WaypointAdvanceMode import uniffi.ferrostar.stepAdvanceDistanceEntryAndExit import uniffi.ferrostar.stepAdvanceDistanceToEndOfStep import java.util.concurrent.Executor import kotlin.time.Clock import kotlin.time.ExperimentalTime import kotlin.time.toJavaInstant class FerrostarWrapper( context: Context, private val locationRepository: LocationRepository, private val orientationRepository: OrientationRepository, private val mode: RoutingMode, private val localValhallaEndpoint: String, private val androidTtsObserver: AndroidTtsObserver, Loading @@ -46,12 +61,52 @@ class FerrostarWrapper( routingOptions: RoutingOptions? = null ) { private val coroutineScope = CoroutineScope(Dispatchers.Main) private val foregroundServiceManager: ForegroundServiceManager = FerrostarForegroundServiceManager( context = context, DefaultForegroundNotificationBuilder(context) ) private val locationProvider = AndroidSystemLocationProvider(context = context) @OptIn(ExperimentalTime::class) private val locationProvider = object: LocationProvider { private val listeners = mutableListOf<LocationUpdateListener>() override val lastLocation: UserLocation? get() = locationRepository.getLastLocation()?.toUserLocation() override val lastHeading: Heading? get() { val heading = ((orientationRepository.azimuth.value.toInt() + 360) % 360).toUShort() return Heading( heading, 0u, Clock.System.now().toJavaInstant() ) } init { coroutineScope.launch { locationRepository.locationFlow.collect { location -> listeners.forEach { listener -> location?.toUserLocation()?.let { userLocation -> listener.onLocationUpdated(userLocation) } } } } } override fun addListener( listener: LocationUpdateListener, executor: Executor ) { listeners.add(listener) } override fun removeListener(listener: LocationUpdateListener) { listeners.remove(listener) } } private var previousRouteOptions: RoutingOptions? = null var core = Loading cardinal-android/app/src/main/java/earth/maps/cardinal/routing/FerrostarWrapperRepository.kt +16 −0 Original line number Diff line number Diff line Loading @@ -21,6 +21,8 @@ package earth.maps.cardinal.routing import android.content.Context import com.stadiamaps.ferrostar.core.AndroidTtsObserver import dagger.hilt.android.qualifiers.ApplicationContext import earth.maps.cardinal.data.LocationRepository import earth.maps.cardinal.data.OrientationRepository import earth.maps.cardinal.data.RoutingMode import earth.maps.cardinal.data.room.RoutingProfileRepository import javax.inject.Inject Loading @@ -30,6 +32,8 @@ import javax.inject.Singleton class FerrostarWrapperRepository @Inject constructor( @param:ApplicationContext private val context: Context, private val locationRepository: LocationRepository, private val orientationRepository: OrientationRepository, private val routingProfileRepository: RoutingProfileRepository ) { lateinit var walking: FerrostarWrapper Loading @@ -44,6 +48,8 @@ class FerrostarWrapperRepository @Inject constructor( fun setValhallaEndpoint(endpoint: String) { walking = FerrostarWrapper( context, locationRepository, orientationRepository, RoutingMode.PEDESTRIAN, endpoint, androidTtsObserver, Loading @@ -51,6 +57,8 @@ class FerrostarWrapperRepository @Inject constructor( ) cycling = FerrostarWrapper( context, locationRepository, orientationRepository, RoutingMode.BICYCLE, endpoint, androidTtsObserver, Loading @@ -58,6 +66,8 @@ class FerrostarWrapperRepository @Inject constructor( ) driving = FerrostarWrapper( context, locationRepository, orientationRepository, RoutingMode.AUTO, endpoint, androidTtsObserver, Loading @@ -65,6 +75,8 @@ class FerrostarWrapperRepository @Inject constructor( ) truck = FerrostarWrapper( context, locationRepository, orientationRepository, RoutingMode.TRUCK, endpoint, androidTtsObserver, Loading @@ -72,6 +84,8 @@ class FerrostarWrapperRepository @Inject constructor( ) motorScooter = FerrostarWrapper( context, locationRepository, orientationRepository, RoutingMode.MOTOR_SCOOTER, endpoint, androidTtsObserver, Loading @@ -79,6 +93,8 @@ class FerrostarWrapperRepository @Inject constructor( ) motorcycle = FerrostarWrapper( context, locationRepository, orientationRepository, RoutingMode.MOTORCYCLE, endpoint, androidTtsObserver, Loading Loading
cardinal-android/app/src/main/java/earth/maps/cardinal/data/LocationRepository.kt +5 −1 Original line number Diff line number Diff line Loading @@ -54,7 +54,7 @@ class LocationRepository @Inject constructor( private companion object { private const val LOCATION_REQUEST_INTERVAL_MS = 15000L // 15 seconds private const val LOCATION_REQUEST_TIMEOUT_MS = 5000L // 5 seconds private const val CONTINUOUS_LOCATION_UPDATE_INTERVAL_MS = 5000L // 5 seconds private const val CONTINUOUS_LOCATION_UPDATE_INTERVAL_MS = 1000L // 1 second private const val CONTINUOUS_LOCATION_UPDATE_DISTANCE_M = 5f // 5 meters private const val GPS_PROVIDER_TIMEOUT_MS = 10_000L // 10 seconds - discard fused locations if fused has updated within this timeout Loading Loading @@ -130,6 +130,10 @@ class LocationRepository @Inject constructor( } } fun getLastLocation(): Location? { return lastRequestedLocation } fun fromNameAndLatLng(name: String?, latLng: LatLng): Place { return Place( name = name ?: context.getString(R.string.unnamed_location), Loading
cardinal-android/app/src/main/java/earth/maps/cardinal/routing/FerrostarWrapper.kt +57 −2 Original line number Diff line number Diff line Loading @@ -20,25 +20,40 @@ package earth.maps.cardinal.routing import android.content.Context import com.stadiamaps.ferrostar.composeui.notification.DefaultForegroundNotificationBuilder import com.stadiamaps.ferrostar.core.AndroidSystemLocationProvider import com.stadiamaps.ferrostar.core.AndroidTtsObserver import com.stadiamaps.ferrostar.core.FerrostarCore import com.stadiamaps.ferrostar.core.LocationProvider import com.stadiamaps.ferrostar.core.LocationUpdateListener import com.stadiamaps.ferrostar.core.http.OkHttpClientProvider import com.stadiamaps.ferrostar.core.service.FerrostarForegroundServiceManager import com.stadiamaps.ferrostar.core.service.ForegroundServiceManager import com.stadiamaps.ferrostar.core.toUserLocation import earth.maps.cardinal.data.LocationRepository import earth.maps.cardinal.data.OrientationRepository import earth.maps.cardinal.data.RoutingMode import earth.maps.cardinal.data.room.RoutingProfileRepository import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import okhttp3.OkHttpClient import uniffi.ferrostar.CourseFiltering import uniffi.ferrostar.Heading import uniffi.ferrostar.NavigationControllerConfig import uniffi.ferrostar.RouteAdapter import uniffi.ferrostar.RouteDeviationTracking import uniffi.ferrostar.UserLocation import uniffi.ferrostar.WaypointAdvanceMode import uniffi.ferrostar.stepAdvanceDistanceEntryAndExit import uniffi.ferrostar.stepAdvanceDistanceToEndOfStep import java.util.concurrent.Executor import kotlin.time.Clock import kotlin.time.ExperimentalTime import kotlin.time.toJavaInstant class FerrostarWrapper( context: Context, private val locationRepository: LocationRepository, private val orientationRepository: OrientationRepository, private val mode: RoutingMode, private val localValhallaEndpoint: String, private val androidTtsObserver: AndroidTtsObserver, Loading @@ -46,12 +61,52 @@ class FerrostarWrapper( routingOptions: RoutingOptions? = null ) { private val coroutineScope = CoroutineScope(Dispatchers.Main) private val foregroundServiceManager: ForegroundServiceManager = FerrostarForegroundServiceManager( context = context, DefaultForegroundNotificationBuilder(context) ) private val locationProvider = AndroidSystemLocationProvider(context = context) @OptIn(ExperimentalTime::class) private val locationProvider = object: LocationProvider { private val listeners = mutableListOf<LocationUpdateListener>() override val lastLocation: UserLocation? get() = locationRepository.getLastLocation()?.toUserLocation() override val lastHeading: Heading? get() { val heading = ((orientationRepository.azimuth.value.toInt() + 360) % 360).toUShort() return Heading( heading, 0u, Clock.System.now().toJavaInstant() ) } init { coroutineScope.launch { locationRepository.locationFlow.collect { location -> listeners.forEach { listener -> location?.toUserLocation()?.let { userLocation -> listener.onLocationUpdated(userLocation) } } } } } override fun addListener( listener: LocationUpdateListener, executor: Executor ) { listeners.add(listener) } override fun removeListener(listener: LocationUpdateListener) { listeners.remove(listener) } } private var previousRouteOptions: RoutingOptions? = null var core = Loading
cardinal-android/app/src/main/java/earth/maps/cardinal/routing/FerrostarWrapperRepository.kt +16 −0 Original line number Diff line number Diff line Loading @@ -21,6 +21,8 @@ package earth.maps.cardinal.routing import android.content.Context import com.stadiamaps.ferrostar.core.AndroidTtsObserver import dagger.hilt.android.qualifiers.ApplicationContext import earth.maps.cardinal.data.LocationRepository import earth.maps.cardinal.data.OrientationRepository import earth.maps.cardinal.data.RoutingMode import earth.maps.cardinal.data.room.RoutingProfileRepository import javax.inject.Inject Loading @@ -30,6 +32,8 @@ import javax.inject.Singleton class FerrostarWrapperRepository @Inject constructor( @param:ApplicationContext private val context: Context, private val locationRepository: LocationRepository, private val orientationRepository: OrientationRepository, private val routingProfileRepository: RoutingProfileRepository ) { lateinit var walking: FerrostarWrapper Loading @@ -44,6 +48,8 @@ class FerrostarWrapperRepository @Inject constructor( fun setValhallaEndpoint(endpoint: String) { walking = FerrostarWrapper( context, locationRepository, orientationRepository, RoutingMode.PEDESTRIAN, endpoint, androidTtsObserver, Loading @@ -51,6 +57,8 @@ class FerrostarWrapperRepository @Inject constructor( ) cycling = FerrostarWrapper( context, locationRepository, orientationRepository, RoutingMode.BICYCLE, endpoint, androidTtsObserver, Loading @@ -58,6 +66,8 @@ class FerrostarWrapperRepository @Inject constructor( ) driving = FerrostarWrapper( context, locationRepository, orientationRepository, RoutingMode.AUTO, endpoint, androidTtsObserver, Loading @@ -65,6 +75,8 @@ class FerrostarWrapperRepository @Inject constructor( ) truck = FerrostarWrapper( context, locationRepository, orientationRepository, RoutingMode.TRUCK, endpoint, androidTtsObserver, Loading @@ -72,6 +84,8 @@ class FerrostarWrapperRepository @Inject constructor( ) motorScooter = FerrostarWrapper( context, locationRepository, orientationRepository, RoutingMode.MOTOR_SCOOTER, endpoint, androidTtsObserver, Loading @@ -79,6 +93,8 @@ class FerrostarWrapperRepository @Inject constructor( ) motorcycle = FerrostarWrapper( context, locationRepository, orientationRepository, RoutingMode.MOTORCYCLE, endpoint, androidTtsObserver, Loading