Fuel, Snap initial location
This commit is contained in:
@@ -273,6 +273,10 @@ class NavigationSession : CarSession(), NavigationListener, NavigationObserverCa
|
|||||||
routeModel = RouteCarModel()
|
routeModel = RouteCarModel()
|
||||||
|
|
||||||
CarConnection(carContext).type.observe(this, ::onConnectionStateUpdated)
|
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(),
|
shouldUseCarLocationFlow = carSensorManager.shouldUseCarLocation(),
|
||||||
onLocationUpdate = ::updateLocation,
|
onLocationUpdate = ::updateLocation,
|
||||||
onInitialLocation = { location ->
|
onInitialLocation = { location ->
|
||||||
|
navigationViewModel.loadCurrentLocation(location)
|
||||||
navigationViewModel.loadRecentPlaces(
|
navigationViewModel.loadRecentPlaces(
|
||||||
carContext,
|
carContext,
|
||||||
location,
|
location,
|
||||||
@@ -753,12 +758,6 @@ class NavigationSession : CarSession(), NavigationListener, NavigationObserverCa
|
|||||||
lastTrafficDate = current
|
lastTrafficDate = current
|
||||||
navigationViewModel.loadTraffic(carContext, location, surfaceRenderer.carOrientation)
|
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 android.util.Log
|
||||||
import com.google.gson.GsonBuilder
|
import com.google.gson.GsonBuilder
|
||||||
import com.kouros.data.BuildConfig
|
import com.kouros.data.BuildConfig
|
||||||
import com.kouros.navigation.data.ApplicationConfig
|
|
||||||
import com.kouros.navigation.utils.GeoUtils.getBoundingBox
|
import com.kouros.navigation.utils.GeoUtils.getBoundingBox
|
||||||
import java.io.OutputStreamWriter
|
import java.io.OutputStreamWriter
|
||||||
import java.net.Authenticator
|
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(
|
fun getAmenities(
|
||||||
type: String,
|
type: String,
|
||||||
category: String,
|
category: String,
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ import androidx.lifecycle.ViewModel
|
|||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import com.google.gson.Gson
|
import com.google.gson.Gson
|
||||||
import com.google.gson.GsonBuilder
|
import com.google.gson.GsonBuilder
|
||||||
import com.kouros.navigation.data.ApplicationConfig
|
|
||||||
import com.kouros.navigation.data.Constants
|
import com.kouros.navigation.data.Constants
|
||||||
import com.kouros.navigation.data.Constants.SPEED_BEARING_DEVIATION
|
import com.kouros.navigation.data.Constants.SPEED_BEARING_DEVIATION
|
||||||
import com.kouros.navigation.data.Constants.SPEED_UPDATE_DISTANCE
|
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.Place
|
||||||
import com.kouros.navigation.data.Places
|
import com.kouros.navigation.data.Places
|
||||||
import com.kouros.navigation.data.SearchFilter
|
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.Search
|
||||||
import com.kouros.navigation.data.nominatim.SearchResult
|
import com.kouros.navigation.data.nominatim.SearchResult
|
||||||
import com.kouros.navigation.data.overpass.ElementSearch
|
import com.kouros.navigation.data.overpass.ElementSearch
|
||||||
import com.kouros.navigation.data.overpass.Elements
|
import com.kouros.navigation.data.overpass.Elements
|
||||||
import com.kouros.navigation.data.overpass.Overpass
|
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.bearingPositive
|
||||||
import com.kouros.navigation.utils.countryCodeSpeedLimit
|
import com.kouros.navigation.utils.countryCodeSpeedLimit
|
||||||
import com.kouros.navigation.utils.getSettingsRepository
|
import com.kouros.navigation.utils.getSettingsRepository
|
||||||
@@ -37,7 +38,7 @@ import kotlinx.coroutines.flow.first
|
|||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
import org.maplibre.geojson.FeatureCollection
|
import org.maplibre.geojson.FeatureCollection
|
||||||
import org.maplibre.geojson.LineString
|
import org.maplibre.geojson.Point
|
||||||
import java.time.LocalDateTime
|
import java.time.LocalDateTime
|
||||||
import java.time.ZoneOffset
|
import java.time.ZoneOffset
|
||||||
import kotlin.collections.first
|
import kotlin.collections.first
|
||||||
@@ -125,6 +126,10 @@ class NavigationViewModel(private val repository: NavigationRepository) : ViewMo
|
|||||||
MutableLiveData()
|
MutableLiveData()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val initialSnapLocation: MutableLiveData<Location> by lazy {
|
||||||
|
MutableLiveData()
|
||||||
|
}
|
||||||
|
|
||||||
val gson: Gson = GsonBuilder().create()
|
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.
|
* Saves a place as a favorite in Preferences.
|
||||||
@@ -652,4 +672,31 @@ class NavigationViewModel(private val repository: NavigationRepository) : ViewMo
|
|||||||
}
|
}
|
||||||
return pl.toMutableStateList()
|
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
|
lastLocationUpdate: LocalDateTime
|
||||||
): Duration {
|
): Duration {
|
||||||
if (viewStyle == ViewStyle.PREVIEW ||
|
if (viewStyle == ViewStyle.PREVIEW ||
|
||||||
viewStyle == ViewStyle.PAN_VIEW) {
|
viewStyle == ViewStyle.PAN_VIEW ||
|
||||||
|
viewStyle == ViewStyle.AMENITY_VIEW) {
|
||||||
return 100.milliseconds
|
return 100.milliseconds
|
||||||
}
|
}
|
||||||
val cameraDuration = if ((lastBearing - bearing).absoluteValue > 20.0) {
|
val cameraDuration = if ((lastBearing - bearing).absoluteValue > 20.0) {
|
||||||
|
|||||||
@@ -8,12 +8,12 @@ koinAndroid = "4.2.1"
|
|||||||
koinAndroidxCompose = "4.2.1"
|
koinAndroidxCompose = "4.2.1"
|
||||||
koinComposeViewmodel = "4.2.1"
|
koinComposeViewmodel = "4.2.1"
|
||||||
koinCore = "4.2.1"
|
koinCore = "4.2.1"
|
||||||
kotlin = "2.3.20"
|
kotlin = "2.3.21"
|
||||||
coreKtx = "1.18.0"
|
coreKtx = "1.18.0"
|
||||||
junit = "4.13.2"
|
junit = "4.13.2"
|
||||||
junitVersion = "1.3.0"
|
junitVersion = "1.3.0"
|
||||||
espressoCore = "3.7.0"
|
espressoCore = "3.7.0"
|
||||||
kotlinxSerializationJson = "1.10.0"
|
kotlinxSerializationJson = "1.11.0"
|
||||||
lifecycleRuntimeKtx = "2.10.0"
|
lifecycleRuntimeKtx = "2.10.0"
|
||||||
composeBom = "2026.04.01"
|
composeBom = "2026.04.01"
|
||||||
appcompat = "1.7.1"
|
appcompat = "1.7.1"
|
||||||
|
|||||||
Reference in New Issue
Block a user