Fuel, Snap initial location
This commit is contained in:
@@ -273,6 +273,10 @@ class NavigationSession : CarSession(), NavigationListener, NavigationObserverCa
|
||||
routeModel = RouteCarModel()
|
||||
|
||||
CarConnection(carContext).type.observe(this, ::onConnectionStateUpdated)
|
||||
|
||||
navigationViewModel.initialSnapLocation.observe(this, Observer {
|
||||
surfaceRenderer.updateLocation(it, "")
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -315,6 +319,7 @@ class NavigationSession : CarSession(), NavigationListener, NavigationObserverCa
|
||||
shouldUseCarLocationFlow = carSensorManager.shouldUseCarLocation(),
|
||||
onLocationUpdate = ::updateLocation,
|
||||
onInitialLocation = { location ->
|
||||
navigationViewModel.loadCurrentLocation(location)
|
||||
navigationViewModel.loadRecentPlaces(
|
||||
carContext,
|
||||
location,
|
||||
@@ -753,12 +758,6 @@ class NavigationSession : CarSession(), NavigationListener, NavigationObserverCa
|
||||
lastTrafficDate = current
|
||||
navigationViewModel.loadTraffic(carContext, location, surfaceRenderer.carOrientation)
|
||||
}
|
||||
if (updateLocationIndex % 4 == 0) {
|
||||
// navigationViewModel.updateTrafficMessages(
|
||||
// surfaceRenderer.lastLocation,
|
||||
// surfaceRenderer.trafficData.value!!
|
||||
// )
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.kouros.navigation.data.fuel
|
||||
|
||||
data class FuelPrice(
|
||||
val `data`: String,
|
||||
val license: String,
|
||||
val ok: Boolean,
|
||||
val stations: List<Station>,
|
||||
val status: String
|
||||
)
|
||||
@@ -0,0 +1,53 @@
|
||||
package com.kouros.navigation.data.fuel
|
||||
|
||||
import android.content.Context
|
||||
import android.location.Location
|
||||
import android.util.Log
|
||||
import com.google.gson.GsonBuilder
|
||||
import com.kouros.navigation.data.NavigationRepository
|
||||
import com.kouros.navigation.data.SearchFilter
|
||||
import com.kouros.navigation.data.overpass.Amenity
|
||||
import java.io.OutputStreamWriter
|
||||
import java.net.Authenticator
|
||||
import java.net.HttpURLConnection
|
||||
import java.net.PasswordAuthentication
|
||||
import java.net.URL
|
||||
|
||||
const val tankerKoenigUrl = "https://creativecommons.tankerkoenig.de/json/list.php?"
|
||||
|
||||
private val gson = GsonBuilder().serializeNulls().create()
|
||||
|
||||
const val sort = "&sort=dist&type=all"
|
||||
|
||||
const val apiKey = "&apikey=fc9900c9-8f02-4b28-990d-dc6067228c59"
|
||||
class FuelPrices : NavigationRepository() {
|
||||
|
||||
fun getFuelPrices(location: Location, radius: Int) : List<Station> {
|
||||
|
||||
val url = "${tankerKoenigUrl}lat=${location.latitude}&lng=${location.longitude}&rad=${radius}$sort$apiKey"
|
||||
|
||||
val prices = fetchUrl(
|
||||
url,
|
||||
false
|
||||
)
|
||||
return gson.fromJson(prices, FuelPrice::class.java).stations
|
||||
}
|
||||
|
||||
override fun getRoute(
|
||||
context: Context,
|
||||
currentLocation: Location,
|
||||
location: List<Location>,
|
||||
carOrientation: Float,
|
||||
searchFilter: SearchFilter
|
||||
): String {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun getTraffic(
|
||||
context: Context,
|
||||
location: Location,
|
||||
carOrientation: Float
|
||||
): String {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.kouros.navigation.data.fuel
|
||||
|
||||
data class Station(
|
||||
val brand: String,
|
||||
val diesel: Double,
|
||||
val dist: Double,
|
||||
val e10: Double,
|
||||
val e5: Double,
|
||||
val houseNumber: String,
|
||||
val id: String,
|
||||
val isOpen: Boolean,
|
||||
val lat: Double,
|
||||
val lng: Double,
|
||||
val name: String,
|
||||
val place: String,
|
||||
val postCode: Int,
|
||||
val street: String
|
||||
)
|
||||
@@ -4,7 +4,6 @@ import android.location.Location
|
||||
import android.util.Log
|
||||
import com.google.gson.GsonBuilder
|
||||
import com.kouros.data.BuildConfig
|
||||
import com.kouros.navigation.data.ApplicationConfig
|
||||
import com.kouros.navigation.utils.GeoUtils.getBoundingBox
|
||||
import java.io.OutputStreamWriter
|
||||
import java.net.Authenticator
|
||||
@@ -69,6 +68,28 @@ class Overpass {
|
||||
}
|
||||
|
||||
|
||||
fun getStreet(location: Location): List<Elements> {
|
||||
|
||||
val lineString = "${location.latitude},${location.longitude}"
|
||||
val searchLocation ="way[\"highway\"~\"^(primary|secondary|tertiary|residential|motorway)$\"][name](around:50, $lineString)";
|
||||
|
||||
val searchQuery = """
|
||||
|[out:json];
|
||||
|(
|
||||
| ${searchLocation};
|
||||
|);
|
||||
|out body geom;
|
||||
""".trimMargin()
|
||||
|
||||
val connection = (URL(overpassUrl).openConnection() as HttpURLConnection).apply {
|
||||
requestMethod = "POST"
|
||||
setRequestProperty("Accept", "application/json")
|
||||
doOutput = true
|
||||
}
|
||||
|
||||
return overpassApi(connection, searchQuery)
|
||||
|
||||
}
|
||||
fun getAmenities(
|
||||
type: String,
|
||||
category: String,
|
||||
|
||||
@@ -10,7 +10,6 @@ import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.GsonBuilder
|
||||
import com.kouros.navigation.data.ApplicationConfig
|
||||
import com.kouros.navigation.data.Constants
|
||||
import com.kouros.navigation.data.Constants.SPEED_BEARING_DEVIATION
|
||||
import com.kouros.navigation.data.Constants.SPEED_UPDATE_DISTANCE
|
||||
@@ -19,11 +18,13 @@ import com.kouros.navigation.data.NavigationRepository
|
||||
import com.kouros.navigation.data.Place
|
||||
import com.kouros.navigation.data.Places
|
||||
import com.kouros.navigation.data.SearchFilter
|
||||
import com.kouros.navigation.data.fuel.FuelPrices
|
||||
import com.kouros.navigation.data.nominatim.Search
|
||||
import com.kouros.navigation.data.nominatim.SearchResult
|
||||
import com.kouros.navigation.data.overpass.ElementSearch
|
||||
import com.kouros.navigation.data.overpass.Elements
|
||||
import com.kouros.navigation.data.overpass.Overpass
|
||||
import com.kouros.navigation.utils.GeoUtils.snapLocation
|
||||
import com.kouros.navigation.utils.bearingPositive
|
||||
import com.kouros.navigation.utils.countryCodeSpeedLimit
|
||||
import com.kouros.navigation.utils.getSettingsRepository
|
||||
@@ -37,7 +38,7 @@ import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.maplibre.geojson.FeatureCollection
|
||||
import org.maplibre.geojson.LineString
|
||||
import org.maplibre.geojson.Point
|
||||
import java.time.LocalDateTime
|
||||
import java.time.ZoneOffset
|
||||
import kotlin.collections.first
|
||||
@@ -125,6 +126,10 @@ class NavigationViewModel(private val repository: NavigationRepository) : ViewMo
|
||||
MutableLiveData()
|
||||
}
|
||||
|
||||
val initialSnapLocation: MutableLiveData<Location> by lazy {
|
||||
MutableLiveData()
|
||||
}
|
||||
|
||||
val gson: Gson = GsonBuilder().create()
|
||||
|
||||
/**
|
||||
@@ -528,6 +533,21 @@ class NavigationViewModel(private val repository: NavigationRepository) : ViewMo
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Queries Tankerkoenig API for fuel prices on current road.
|
||||
*
|
||||
*/
|
||||
fun updateFuelPrices(
|
||||
location: Location,
|
||||
) {
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
synchronized(this) {
|
||||
val stations =
|
||||
FuelPrices().getFuelPrices(location, 3)
|
||||
Log.d(TAG, "FuelPrices $stations")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves a place as a favorite in Preferences.
|
||||
@@ -652,4 +672,31 @@ class NavigationViewModel(private val repository: NavigationRepository) : ViewMo
|
||||
}
|
||||
return pl.toMutableStateList()
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads current location nearest street
|
||||
* and snap to location to street
|
||||
*/
|
||||
fun loadCurrentLocation(location: Location) {
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
synchronized(this) {
|
||||
val elements = Overpass().getStreet(location)
|
||||
if (elements.isNotEmpty()) {
|
||||
val points = mutableListOf<Point>()
|
||||
elements.first().geometry.forEach {
|
||||
points.add(Point.fromLngLat(it.lon, it.lat))
|
||||
}
|
||||
val snappedLocation = snapLocation(location, points)
|
||||
if (points.size > 1) {
|
||||
val bearing = location(
|
||||
points.first().longitude(),
|
||||
points.first().latitude()
|
||||
).bearingPositive(location(points[1].longitude(), points[1].latitude()))
|
||||
snappedLocation.bearing = bearing
|
||||
}
|
||||
initialSnapLocation.postValue(snappedLocation)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,7 +151,8 @@ fun duration(
|
||||
lastLocationUpdate: LocalDateTime
|
||||
): Duration {
|
||||
if (viewStyle == ViewStyle.PREVIEW ||
|
||||
viewStyle == ViewStyle.PAN_VIEW) {
|
||||
viewStyle == ViewStyle.PAN_VIEW ||
|
||||
viewStyle == ViewStyle.AMENITY_VIEW) {
|
||||
return 100.milliseconds
|
||||
}
|
||||
val cameraDuration = if ((lastBearing - bearing).absoluteValue > 20.0) {
|
||||
|
||||
@@ -8,12 +8,12 @@ koinAndroid = "4.2.1"
|
||||
koinAndroidxCompose = "4.2.1"
|
||||
koinComposeViewmodel = "4.2.1"
|
||||
koinCore = "4.2.1"
|
||||
kotlin = "2.3.20"
|
||||
kotlin = "2.3.21"
|
||||
coreKtx = "1.18.0"
|
||||
junit = "4.13.2"
|
||||
junitVersion = "1.3.0"
|
||||
espressoCore = "3.7.0"
|
||||
kotlinxSerializationJson = "1.10.0"
|
||||
kotlinxSerializationJson = "1.11.0"
|
||||
lifecycleRuntimeKtx = "2.10.0"
|
||||
composeBom = "2026.04.01"
|
||||
appcompat = "1.7.1"
|
||||
|
||||
Reference in New Issue
Block a user