mirror of
https://github.com/ev-map/EVMap.git
synced 2026-04-30 19:14:22 -04:00
Implement operators and licenses for OpenChargeMap data
This commit is contained in:
@@ -18,7 +18,7 @@ class DetailsAdapter : DataBindingAdapter<DetailsAdapter.Detail>() {
|
||||
data class Detail(
|
||||
val icon: Int,
|
||||
val contentDescription: Int,
|
||||
val text: CharSequence,
|
||||
val text: CharSequence?,
|
||||
val detailText: CharSequence? = null,
|
||||
val links: Boolean = true,
|
||||
val clickable: Boolean = false,
|
||||
@@ -119,7 +119,7 @@ fun buildDetails(
|
||||
loc.coordinates.formatDecimal(),
|
||||
links = false,
|
||||
clickable = true
|
||||
)
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -30,6 +30,8 @@ interface ChargepointApi<out T : ReferenceData> {
|
||||
suspend fun getReferenceData(): Resource<T>
|
||||
|
||||
fun getFilters(referenceData: ReferenceData, sp: StringProvider): List<Filter<FilterValue>>
|
||||
|
||||
fun getName(): String
|
||||
}
|
||||
|
||||
interface StringProvider {
|
||||
|
||||
@@ -128,6 +128,9 @@ class GoingElectricApiWrapper(
|
||||
context: Context? = null
|
||||
) : ChargepointApi<GEReferenceData> {
|
||||
val api = GoingElectricApi.create(apikey, baseurl, context)
|
||||
|
||||
override fun getName() = "GoingElectric.de"
|
||||
|
||||
override suspend fun getChargepoints(
|
||||
referenceData: ReferenceData,
|
||||
bounds: LatLngBounds,
|
||||
|
||||
@@ -61,7 +61,8 @@ data class GEChargeLocation(
|
||||
address.convert(),
|
||||
chargepoints.map { it.convert() },
|
||||
network,
|
||||
url,
|
||||
"https:${url}",
|
||||
"https:${url}edit/",
|
||||
faultReport?.convert(),
|
||||
verified,
|
||||
barrierFree,
|
||||
@@ -72,7 +73,8 @@ data class GEChargeLocation(
|
||||
photos?.map { it.convert(apikey) },
|
||||
chargecards?.map { it.convert() },
|
||||
openinghours?.convert(),
|
||||
cost?.convert()
|
||||
cost?.convert(),
|
||||
null
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -86,6 +86,8 @@ class OpenChargeMapApiWrapper(
|
||||
) : ChargepointApi<OCMReferenceData> {
|
||||
val api = OpenChargeMapApi.create(apikey, baseurl, context)
|
||||
|
||||
override fun getName() = "OpenChargeMap.org"
|
||||
|
||||
override suspend fun getChargepoints(
|
||||
referenceData: ReferenceData,
|
||||
bounds: LatLngBounds,
|
||||
|
||||
@@ -23,7 +23,9 @@ data class OCMChargepoint(
|
||||
@Json(name = "AddressInfo") val addressInfo: OCMAddressInfo,
|
||||
@Json(name = "Connections") val connections: List<OCMConnection>,
|
||||
@Json(name = "NumberOfPoints") val numPoints: Int,
|
||||
@Json(name = "GeneralComments") val generalComments: String?
|
||||
@Json(name = "GeneralComments") val generalComments: String?,
|
||||
@Json(name = "OperatorInfo") val operatorInfo: OCMOperator?,
|
||||
@Json(name = "DataProvider") val dataProvider: OCMDataProvider?
|
||||
) {
|
||||
fun convert(refData: OCMReferenceData) = ChargeLocation(
|
||||
id,
|
||||
@@ -31,19 +33,21 @@ data class OCMChargepoint(
|
||||
Coordinate(addressInfo.latitude, addressInfo.longitude),
|
||||
addressInfo.toAddress(refData),
|
||||
connections.map { it.convert(refData) },
|
||||
null,
|
||||
operatorInfo?.title,
|
||||
"https://openchargemap.org/site/poi/details/$id",
|
||||
"https://openchargemap.org/site/poi/edit/$id",
|
||||
null,
|
||||
recentlyVerified,
|
||||
null,
|
||||
null, //TODO: OperatorInfo
|
||||
null,
|
||||
generalComments,
|
||||
null,
|
||||
addressInfo.accessComments,
|
||||
null, // TODO: MediaItems,
|
||||
null,
|
||||
null,
|
||||
cost?.let { Cost(descriptionShort = it) }
|
||||
cost?.let { Cost(descriptionShort = it) },
|
||||
dataProvider?.let { "© ${it.title}" + if (it.license != null) ". ${it.license}" else "" }
|
||||
)
|
||||
}
|
||||
|
||||
@@ -128,4 +132,22 @@ data class OCMCountry(
|
||||
@Json(name = "ISOCode") val isoCode: String,
|
||||
@Json(name = "ContinentCode") val continentCode: String?,
|
||||
@Json(name = "Title") val title: String
|
||||
)
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class OCMDataProvider(
|
||||
@Json(name = "ID") val id: Long,
|
||||
@Json(name = "WebsiteURL") val websiteUrl: String?,
|
||||
@Json(name = "Title") val title: String,
|
||||
@Json(name = "License") val license: String?
|
||||
)
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class OCMOperator(
|
||||
@Json(name = "ID") val id: Long,
|
||||
@Json(name = "WebsiteURL") val websiteUrl: String?,
|
||||
@Json(name = "Title") val title: String,
|
||||
@Json(name = "ContactEmail") val contactEmail: String?,
|
||||
@Json(name = "PhonePrimaryContact") val contactTelephone1: String?,
|
||||
@Json(name = "PhoneSecondaryContact") val contactTelephone2: String?,
|
||||
)
|
||||
@@ -66,6 +66,7 @@ import net.vonforst.evmap.*
|
||||
import net.vonforst.evmap.adapter.ConnectorAdapter
|
||||
import net.vonforst.evmap.adapter.DetailsAdapter
|
||||
import net.vonforst.evmap.adapter.GalleryAdapter
|
||||
import net.vonforst.evmap.api.goingelectric.GoingElectricApiWrapper
|
||||
import net.vonforst.evmap.autocomplete.handleAutocompleteResult
|
||||
import net.vonforst.evmap.autocomplete.launchAutocomplete
|
||||
import net.vonforst.evmap.databinding.FragmentMapBinding
|
||||
@@ -292,10 +293,10 @@ class MapFragment : Fragment(), OnMapReadyCallback, MapsActivity.FragmentCallbac
|
||||
binding.layers.btnClose.setOnClickListener {
|
||||
closeLayersMenu()
|
||||
}
|
||||
binding.detailView.goingelectricButton.setOnClickListener {
|
||||
binding.detailView.sourceButton.setOnClickListener {
|
||||
val charger = vm.charger.value?.data
|
||||
if (charger != null) {
|
||||
(activity as? MapsActivity)?.openUrl("https:${charger.url}")
|
||||
(activity as? MapsActivity)?.openUrl(charger.url)
|
||||
}
|
||||
}
|
||||
binding.detailView.btnChargeprice.setOnClickListener {
|
||||
@@ -323,19 +324,22 @@ class MapFragment : Fragment(), OnMapReadyCallback, MapsActivity.FragmentCallbac
|
||||
R.id.menu_share -> {
|
||||
val charger = vm.charger.value?.data
|
||||
if (charger != null) {
|
||||
(activity as? MapsActivity)?.shareUrl("https:${charger.url}")
|
||||
(activity as? MapsActivity)?.shareUrl(charger.url)
|
||||
}
|
||||
true
|
||||
}
|
||||
R.id.menu_edit -> {
|
||||
val charger = vm.charger.value?.data
|
||||
if (charger != null) {
|
||||
(activity as? MapsActivity)?.openUrl("https:${charger.url}edit/")
|
||||
Toast.makeText(
|
||||
requireContext(),
|
||||
R.string.edit_on_goingelectric_info,
|
||||
Toast.LENGTH_LONG
|
||||
).show()
|
||||
if (charger?.editUrl != null) {
|
||||
(activity as? MapsActivity)?.openUrl(charger.editUrl)
|
||||
if (vm.apiType == GoingElectricApiWrapper::class.java) {
|
||||
// instructions specific to GoingElectric
|
||||
Toast.makeText(
|
||||
requireContext(),
|
||||
R.string.edit_on_goingelectric_info,
|
||||
Toast.LENGTH_LONG
|
||||
).show()
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
@@ -627,7 +631,7 @@ class MapFragment : Fragment(), OnMapReadyCallback, MapsActivity.FragmentCallbac
|
||||
(activity as? MapsActivity)?.showLocation(charger)
|
||||
}
|
||||
R.drawable.ic_fault_report -> {
|
||||
(activity as? MapsActivity)?.openUrl("https:${charger.url}")
|
||||
(activity as? MapsActivity)?.openUrl(charger.url)
|
||||
}
|
||||
R.drawable.ic_payment -> {
|
||||
showPaymentMethodsDialog(charger)
|
||||
|
||||
@@ -31,6 +31,7 @@ data class ChargeLocation(
|
||||
val chargepoints: List<Chargepoint>,
|
||||
val network: String?,
|
||||
val url: String,
|
||||
val editUrl: String?,
|
||||
@Embedded(prefix = "fault_report_") val faultReport: FaultReport?,
|
||||
val verified: Boolean,
|
||||
val barrierFree: Boolean?,
|
||||
@@ -42,7 +43,8 @@ data class ChargeLocation(
|
||||
val photos: List<ChargerPhoto>?,
|
||||
val chargecards: List<ChargeCardId>?,
|
||||
@Embedded val openinghours: OpeningHours?,
|
||||
@Embedded val cost: Cost?
|
||||
@Embedded val cost: Cost?,
|
||||
val license: String?
|
||||
) : ChargepointListItem(), Equatable {
|
||||
/**
|
||||
* maximum power available from this charger.
|
||||
|
||||
@@ -20,7 +20,7 @@ import net.vonforst.evmap.model.*
|
||||
GEPlug::class,
|
||||
GENetwork::class,
|
||||
GEChargeCard::class
|
||||
], version = 11
|
||||
], version = 12
|
||||
)
|
||||
@TypeConverters(Converters::class)
|
||||
abstract class AppDatabase : RoomDatabase() {
|
||||
@@ -37,7 +37,8 @@ abstract class AppDatabase : RoomDatabase() {
|
||||
Room.databaseBuilder(context, AppDatabase::class.java, "evmap.db")
|
||||
.addMigrations(
|
||||
MIGRATION_2, MIGRATION_3, MIGRATION_4, MIGRATION_5, MIGRATION_6,
|
||||
MIGRATION_7, MIGRATION_8, MIGRATION_9, MIGRATION_10, MIGRATION_11
|
||||
MIGRATION_7, MIGRATION_8, MIGRATION_9, MIGRATION_10, MIGRATION_11,
|
||||
MIGRATION_12
|
||||
)
|
||||
.addCallback(object : Callback() {
|
||||
override fun onCreate(db: SupportSQLiteDatabase) {
|
||||
@@ -172,5 +173,18 @@ abstract class AppDatabase : RoomDatabase() {
|
||||
db.execSQL("ALTER TABLE `ChargeLocation` ADD `barrierFree` INTEGER")
|
||||
}
|
||||
}
|
||||
|
||||
private val MIGRATION_12 = object : Migration(11, 12) {
|
||||
override fun migrate(db: SupportSQLiteDatabase) {
|
||||
db.beginTransaction()
|
||||
try {
|
||||
db.execSQL("ALTER TABLE `ChargeLocation` ADD `editUrl` TEXT")
|
||||
db.execSQL("ALTER TABLE `ChargeLocation` ADD `license` TEXT")
|
||||
db.setTransactionSuccessful()
|
||||
} finally {
|
||||
db.endTransaction()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -42,6 +42,10 @@ class MapViewModel(application: Application, geApiKey: String) : AndroidViewMode
|
||||
R.string.openchargemap_key
|
||||
)
|
||||
)
|
||||
val apiType: Class<ChargepointApi<ReferenceData>>
|
||||
get() = api.javaClass
|
||||
val apiName: String
|
||||
get() = api.getName()
|
||||
|
||||
// = GoingElectricApiWrapper(geApiKey, context = application)
|
||||
private var db = AppDatabase.getInstance(application)
|
||||
|
||||
10
app/src/main/res/drawable/ic_license.xml
Normal file
10
app/src/main/res/drawable/ic_license.xml
Normal file
@@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M11.88,9.14c1.28,0.06 1.61,1.15 1.63,1.66h1.79c-0.08,-1.98 -1.49,-3.19 -3.45,-3.19C9.64,7.61 8,9 8,12.14c0,1.94 0.93,4.24 3.84,4.24c2.22,0 3.41,-1.65 3.44,-2.95h-1.79c-0.03,0.59 -0.45,1.38 -1.63,1.44C10.55,14.83 10,13.81 10,12.14C10,9.25 11.28,9.16 11.88,9.14zM12,2C6.48,2 2,6.48 2,12s4.48,10 10,10s10,-4.48 10,-10S17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8s8,3.59 8,8S16.41,20 12,20z" />
|
||||
</vector>
|
||||
@@ -53,6 +53,10 @@
|
||||
name="expanded"
|
||||
type="Boolean" />
|
||||
|
||||
<variable
|
||||
name="apiName"
|
||||
type="String" />
|
||||
|
||||
</data>
|
||||
|
||||
<androidx.cardview.widget.CardView
|
||||
@@ -270,14 +274,13 @@
|
||||
app:layout_constraintGuide_begin="16dp" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/goingelectricButton"
|
||||
android:id="@+id/sourceButton"
|
||||
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:text="@string/go_to_goingelectric"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
android:text="@{@string/source(apiName)}"
|
||||
app:layout_constraintEnd_toStartOf="@+id/guideline2"
|
||||
app:layout_constraintStart_toStartOf="@+id/guideline"
|
||||
app:layout_constraintTop_toBottomOf="@+id/textView4" />
|
||||
@@ -349,6 +352,23 @@
|
||||
app:srcCompat="@drawable/ic_map_marker_fault"
|
||||
tools:targetApi="o" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txtLicense"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:textAlignment="center"
|
||||
android:textAppearance="@style/TextAppearance.MaterialComponents.Caption"
|
||||
android:textStyle="italic"
|
||||
android:text="@{charger.data.license}"
|
||||
android:breakStrategy="balanced"
|
||||
app:goneUnless="@{charger.data.license != null}"
|
||||
app:layout_constraintEnd_toStartOf="@+id/guideline2"
|
||||
app:layout_constraintStart_toStartOf="@+id/guideline"
|
||||
app:layout_constraintTop_toBottomOf="@+id/sourceButton"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
tools:text="The data is provided under the National Oman Open Data LicensE (NOODLE), Version 3.14, and may be used for any purpose whatsoever." />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
@@ -144,7 +144,8 @@
|
||||
app:chargeCards="@{vm.chargeCardMap}"
|
||||
app:filteredChargeCards="@{vm.filteredChargeCards}"
|
||||
app:distance="@{vm.chargerDistance}"
|
||||
app:expanded="@{vm.bottomSheetState != BottomSheetBehaviorGoogleMapsLike.STATE_COLLAPSED && vm.bottomSheetState != BottomSheetBehaviorGoogleMapsLike.STATE_HIDDEN}" />
|
||||
app:expanded="@{vm.bottomSheetState != BottomSheetBehaviorGoogleMapsLike.STATE_COLLAPSED && vm.bottomSheetState != BottomSheetBehaviorGoogleMapsLike.STATE_HIDDEN}"
|
||||
app:apiName="@{vm.apiName}" />
|
||||
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
<string name="realtime_data_unavailable">Echtzeitstatus nicht verfügbar</string>
|
||||
<string name="realtime_data_loading">Prüfe Echtzeitstatus…</string>
|
||||
<string name="realtime_data_source">Quelle Echtzeitdaten (beta): %s</string>
|
||||
<string name="go_to_goingelectric">Quelle: goingelectric.de</string>
|
||||
<string name="source">Quelle: %s</string>
|
||||
<string name="search">Suche</string>
|
||||
<string name="menu_map">Karte</string>
|
||||
<string name="menu_favs">Favoriten</string>
|
||||
@@ -192,6 +192,7 @@
|
||||
<string name="pref_chargeprice_currency">Währung</string>
|
||||
<string name="pref_my_tariffs">Meine Tarife</string>
|
||||
<string name="chargeprice_all_tariffs_selected">alle Tarife ausgewählt</string>
|
||||
<string name="license">Lizenz</string>
|
||||
<string-array name="pref_chargeprice_currency_names">
|
||||
<item>Schweizer Franken (CHF)</item>
|
||||
<item>Tschechische Krone (CZK)</item>
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
<string name="realtime_data_unavailable">Real-time status unavailable</string>
|
||||
<string name="realtime_data_loading">Checking real-time status…</string>
|
||||
<string name="realtime_data_source">Real-time status source (beta): %s</string>
|
||||
<string name="go_to_goingelectric">Source: goingelectric.de</string>
|
||||
<string name="source">Source: %s</string>
|
||||
<string name="search">Search</string>
|
||||
<string name="menu_map">Map</string>
|
||||
<string name="menu_favs">Favorites</string>
|
||||
@@ -191,6 +191,7 @@
|
||||
<string name="pref_chargeprice_currency">Currency</string>
|
||||
<string name="pref_my_tariffs">My charging plans</string>
|
||||
<string name="chargeprice_all_tariffs_selected">all plans selected</string>
|
||||
<string name="license">License</string>
|
||||
<plurals name="chargeprice_some_tariffs_selected">
|
||||
<item quantity="one">%d plan selected</item>
|
||||
<item quantity="other">%d plans selected</item>
|
||||
|
||||
Reference in New Issue
Block a user