mirror of
https://github.com/ev-map/EVMap.git
synced 2026-04-23 23:57:08 -04:00
OSM: implement ReferenceData and network filter
This commit is contained in:
@@ -130,6 +130,16 @@ data class ChargepointList(val items: List<ChargepointListItem>, val isComplete:
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Result returned from fullDownload() function.
|
||||
*
|
||||
* Note that [chargers] is implemented as a [Sequence] so that downloaded chargers can be saved
|
||||
* while they are being parsed instead of having to keep all of them in RAM at once.
|
||||
*
|
||||
* [progress] is updated regularly to indicate the current download progress.
|
||||
* [referenceData] will typically only be available once the download is completed, i.e. you have
|
||||
* iterated over the whole sequence of [chargers].
|
||||
*/
|
||||
interface FullDownloadResult<out T : ReferenceData> {
|
||||
val chargers: Sequence<ChargeLocation>
|
||||
val progress: Float
|
||||
|
||||
@@ -12,6 +12,7 @@ import net.vonforst.evmap.api.ChargepointList
|
||||
import net.vonforst.evmap.api.FiltersSQLQuery
|
||||
import net.vonforst.evmap.api.FullDownloadResult
|
||||
import net.vonforst.evmap.api.StringProvider
|
||||
import net.vonforst.evmap.api.goingelectric.GEReferenceData
|
||||
import net.vonforst.evmap.api.mapPower
|
||||
import net.vonforst.evmap.api.mapPowerInverse
|
||||
import net.vonforst.evmap.api.nameForPlugType
|
||||
@@ -128,6 +129,9 @@ class OpenStreetMapApiWrapper(baseurl: String = "https://evmap-dev.vonforst.net"
|
||||
nameForPlugType(sp, plug)
|
||||
}
|
||||
|
||||
val refData = referenceData as OSMReferenceData
|
||||
val networkMap = refData.networks.associateWith { it }
|
||||
|
||||
return listOf(
|
||||
BooleanFilter(sp.getString(R.string.filter_free), "freecharging"),
|
||||
BooleanFilter(sp.getString(R.string.filter_free_parking), "freeparking"),
|
||||
@@ -152,6 +156,10 @@ class OpenStreetMapApiWrapper(baseurl: String = "https://evmap-dev.vonforst.net"
|
||||
),
|
||||
manyChoices = true
|
||||
),
|
||||
MultipleChoiceFilter(
|
||||
sp.getString(R.string.filter_networks), "networks",
|
||||
networkMap, manyChoices = true
|
||||
),
|
||||
SliderFilter(
|
||||
sp.getString(R.string.filter_min_connectors),
|
||||
"min_connectors",
|
||||
@@ -204,6 +212,16 @@ class OpenStreetMapApiWrapper(baseurl: String = "https://evmap-dev.vonforst.net"
|
||||
requiresChargepointQuery = true
|
||||
}
|
||||
|
||||
val networks = filters.getMultipleChoiceValue("networks")
|
||||
if (networks != null && !networks.all) {
|
||||
val networksList = if (networks.values.size == 0) {
|
||||
""
|
||||
} else {
|
||||
networks.values.joinToString(",") { DatabaseUtils.sqlEscapeString(it) }
|
||||
}
|
||||
result.append(" AND network IN (${networksList})")
|
||||
}
|
||||
|
||||
return FiltersSQLQuery(result.toString(), requiresChargepointQuery, false)
|
||||
}
|
||||
|
||||
@@ -222,23 +240,31 @@ class OpenStreetMapApiWrapper(baseurl: String = "https://evmap-dev.vonforst.net"
|
||||
}
|
||||
}
|
||||
|
||||
data class OSMReferenceData(val test: String) : ReferenceData()
|
||||
data class OSMReferenceData(val networks: List<String>) : ReferenceData()
|
||||
|
||||
class OSMFullDownloadResult(private val body: OSMDocument) : FullDownloadResult<OSMReferenceData> {
|
||||
private var downloadProgress = 0f
|
||||
private var refData: OSMReferenceData? = null
|
||||
|
||||
override val chargers: Sequence<ChargeLocation>
|
||||
get() {
|
||||
val time = body.timestamp
|
||||
val networks = mutableListOf<String>()
|
||||
|
||||
return sequence {
|
||||
body.elements.forEachIndexed { i, it ->
|
||||
yield(it.convert(time))
|
||||
val charger = it.convert(time)
|
||||
yield(charger)
|
||||
downloadProgress = i.toFloat() / body.count
|
||||
charger.network?.let { networks.add(it) }
|
||||
}
|
||||
refData = OSMReferenceData(networks)
|
||||
}
|
||||
}
|
||||
override val progress: Float
|
||||
get() = downloadProgress
|
||||
override val referenceData: OSMReferenceData
|
||||
get() = TODO("Not yet implemented")
|
||||
get() = refData
|
||||
?: throw UnsupportedOperationException("referenceData is only available once download is complete")
|
||||
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ import net.vonforst.evmap.api.goingelectric.GEReferenceData
|
||||
import net.vonforst.evmap.api.goingelectric.GoingElectricApiWrapper
|
||||
import net.vonforst.evmap.api.openchargemap.OCMReferenceData
|
||||
import net.vonforst.evmap.api.openchargemap.OpenChargeMapApiWrapper
|
||||
import net.vonforst.evmap.api.openstreetmap.OSMReferenceData
|
||||
import net.vonforst.evmap.api.openstreetmap.OpenStreetMapApiWrapper
|
||||
import net.vonforst.evmap.model.*
|
||||
import net.vonforst.evmap.ui.cluster
|
||||
@@ -144,15 +145,7 @@ class ChargeLocationsRepository(
|
||||
}
|
||||
|
||||
is OpenStreetMapApiWrapper -> {
|
||||
liveData<OCMReferenceData> {
|
||||
emit(
|
||||
OCMReferenceData(
|
||||
emptyList(),
|
||||
emptyList(),
|
||||
emptyList()
|
||||
)
|
||||
)
|
||||
} // TODO: add OSM reference data
|
||||
OSMReferenceDataRepository(db.osmReferenceDataDao()).getReferenceData()
|
||||
}
|
||||
|
||||
else -> {
|
||||
@@ -552,6 +545,14 @@ class ChargeLocationsRepository(
|
||||
true
|
||||
)
|
||||
)
|
||||
|
||||
when (api) {
|
||||
is OpenStreetMapApiWrapper -> {
|
||||
val refData = result.referenceData
|
||||
OSMReferenceDataRepository(db.osmReferenceDataDao()).updateReferenceData(refData as OSMReferenceData)
|
||||
}
|
||||
}
|
||||
|
||||
} finally {
|
||||
fullDownloadProgress.value = null
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@ import net.vonforst.evmap.model.*
|
||||
OCMConnectionType::class,
|
||||
OCMCountry::class,
|
||||
OCMOperator::class,
|
||||
OSMNetwork::class,
|
||||
SavedRegion::class
|
||||
], version = 23
|
||||
)
|
||||
@@ -51,6 +52,9 @@ abstract class AppDatabase : RoomDatabase() {
|
||||
// OpenChargeMap API specific
|
||||
abstract fun ocmReferenceDataDao(): OCMReferenceDataDao
|
||||
|
||||
// OpenStreetMap API specific
|
||||
abstract fun osmReferenceDataDao(): OSMReferenceDataDao
|
||||
|
||||
companion object {
|
||||
private lateinit var context: Context
|
||||
private val database: AppDatabase by lazy(LazyThreadSafetyMode.SYNCHRONIZED) {
|
||||
@@ -465,6 +469,7 @@ abstract class AppDatabase : RoomDatabase() {
|
||||
override fun migrate(db: SupportSQLiteDatabase) {
|
||||
// API openstreetmap added
|
||||
db.execSQL("INSERT INTO `FilterProfile` (`dataSource`, `name`, `id`, `order`) VALUES ('openstreetmap', 'FILTERS_CUSTOM', $FILTERS_CUSTOM, 0)")
|
||||
db.execSQL("CREATE TABLE IF NOT EXISTS `OSMNetwork` (`name` TEXT NOT NULL, PRIMARY KEY(`name`))")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
package net.vonforst.evmap.storage
|
||||
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MediatorLiveData
|
||||
import androidx.room.*
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.launch
|
||||
import net.vonforst.evmap.api.openchargemap.*
|
||||
import net.vonforst.evmap.api.openstreetmap.OSMReferenceData
|
||||
import net.vonforst.evmap.viewmodel.Status
|
||||
import java.time.Duration
|
||||
import java.time.Instant
|
||||
|
||||
@Entity
|
||||
data class OSMNetwork(@PrimaryKey val name: String)
|
||||
|
||||
@Dao
|
||||
abstract class OSMReferenceDataDao {
|
||||
// NETWORKS
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
abstract suspend fun insert(vararg networks: OSMNetwork)
|
||||
|
||||
@Query("DELETE FROM osmnetwork")
|
||||
abstract fun deleteAllNetworks()
|
||||
|
||||
@Transaction
|
||||
open suspend fun updateNetworks(networks: List<OSMNetwork>) {
|
||||
deleteAllNetworks()
|
||||
for (network in networks) {
|
||||
insert(network)
|
||||
}
|
||||
}
|
||||
|
||||
@Query("SELECT * FROM osmnetwork")
|
||||
abstract fun getAllNetworks(): LiveData<List<OSMNetwork>>
|
||||
}
|
||||
|
||||
class OSMReferenceDataRepository(private val dao: OSMReferenceDataDao) {
|
||||
fun getReferenceData(): LiveData<OSMReferenceData> {
|
||||
val networks = dao.getAllNetworks()
|
||||
return MediatorLiveData<OSMReferenceData>().apply {
|
||||
value = null
|
||||
addSource(networks) { _ ->
|
||||
val n = networks.value ?: return@addSource
|
||||
value = OSMReferenceData(n.map { it.name })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun updateReferenceData(refData: OSMReferenceData) {
|
||||
dao.updateNetworks(refData.networks.map { OSMNetwork(it) })
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user