Implement operators and licenses for OpenChargeMap data

This commit is contained in:
johan12345
2021-06-20 19:09:00 +02:00
parent 7f8403cfb4
commit e29d40bca2
15 changed files with 116 additions and 28 deletions

View File

@@ -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
)
),
)
}

View File

@@ -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 {

View File

@@ -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,

View File

@@ -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
)
}

View File

@@ -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,

View File

@@ -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?,
)

View File

@@ -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)

View File

@@ -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.

View File

@@ -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()
}
}
}
}
}

View File

@@ -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)

View 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>

View File

@@ -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>

View File

@@ -144,7 +144,8 @@
app:chargeCards="@{vm.chargeCardMap}"
app:filteredChargeCards="@{vm.filteredChargeCards}"
app:distance="@{vm.chargerDistance}"
app:expanded="@{vm.bottomSheetState != BottomSheetBehaviorGoogleMapsLike.STATE_COLLAPSED &amp;&amp; vm.bottomSheetState != BottomSheetBehaviorGoogleMapsLike.STATE_HIDDEN}" />
app:expanded="@{vm.bottomSheetState != BottomSheetBehaviorGoogleMapsLike.STATE_COLLAPSED &amp;&amp; vm.bottomSheetState != BottomSheetBehaviorGoogleMapsLike.STATE_HIDDEN}"
app:apiName="@{vm.apiName}" />
</androidx.core.widget.NestedScrollView>

View File

@@ -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>

View File

@@ -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>