From 80edbe66ce6926ef4b69dd59cb5edb95d2cbcfa2 Mon Sep 17 00:00:00 2001 From: Johan von Forstner Date: Sun, 12 Apr 2020 23:54:33 +0200 Subject: [PATCH] implement availability detector with NewMotion API --- .../main/java/com/johan/evmap/MapsActivity.kt | 2 +- .../evmap/adapter/DataBindingAdapters.kt | 6 +- .../com/johan/evmap/adapter/GalleryAdapter.kt | 2 +- .../main/java/com/johan/evmap/api/Utils.kt | 11 +- .../api/availability/AvailabilityDetector.kt | 76 ++++++++ .../ChargecloudAvailabilityDetector.kt} | 99 ++++------ .../NewMotionAvailabilityDetector.kt | 184 ++++++++++++++++++ .../GoingElectricAdapters.kt | 22 ++- .../{ => goingelectric}/GoingElectricApi.kt | 2 +- .../{ => goingelectric}/GoingElectricModel.kt | 2 +- .../com/johan/evmap/fragment/MapFragment.kt | 8 +- .../com/johan/evmap/ui/BindingAdapters.kt | 2 +- .../java/com/johan/evmap/ui/MarkerUtils.kt | 2 +- .../com/johan/evmap/viewmodel/MapViewModel.kt | 8 +- app/src/main/res/layout/activity_gallery.xml | 2 +- app/src/main/res/layout/detail_view.xml | 6 +- app/src/test/java/com/johan/evmap/ApiTests.kt | 4 +- 17 files changed, 347 insertions(+), 91 deletions(-) create mode 100644 app/src/main/java/com/johan/evmap/api/availability/AvailabilityDetector.kt rename app/src/main/java/com/johan/evmap/api/{AvailabilityDetector.kt => availability/ChargecloudAvailabilityDetector.kt} (54%) create mode 100644 app/src/main/java/com/johan/evmap/api/availability/NewMotionAvailabilityDetector.kt rename app/src/main/java/com/johan/evmap/api/{ => goingelectric}/GoingElectricAdapters.kt (88%) rename app/src/main/java/com/johan/evmap/api/{ => goingelectric}/GoingElectricApi.kt (97%) rename app/src/main/java/com/johan/evmap/api/{ => goingelectric}/GoingElectricModel.kt (99%) diff --git a/app/src/main/java/com/johan/evmap/MapsActivity.kt b/app/src/main/java/com/johan/evmap/MapsActivity.kt index 9aece720..56e08b64 100644 --- a/app/src/main/java/com/johan/evmap/MapsActivity.kt +++ b/app/src/main/java/com/johan/evmap/MapsActivity.kt @@ -12,7 +12,7 @@ import androidx.navigation.ui.AppBarConfiguration import androidx.navigation.ui.setupWithNavController import com.google.android.material.navigation.NavigationView import com.google.android.material.snackbar.Snackbar -import com.johan.evmap.api.ChargeLocation +import com.johan.evmap.api.goingelectric.ChargeLocation const val REQUEST_LOCATION_PERMISSION = 1 diff --git a/app/src/main/java/com/johan/evmap/adapter/DataBindingAdapters.kt b/app/src/main/java/com/johan/evmap/adapter/DataBindingAdapters.kt index 7b417616..df8394ab 100644 --- a/app/src/main/java/com/johan/evmap/adapter/DataBindingAdapters.kt +++ b/app/src/main/java/com/johan/evmap/adapter/DataBindingAdapters.kt @@ -10,9 +10,9 @@ import androidx.recyclerview.widget.ListAdapter import androidx.recyclerview.widget.RecyclerView import com.johan.evmap.BR import com.johan.evmap.R -import com.johan.evmap.api.ChargeLocation -import com.johan.evmap.api.Chargepoint -import com.johan.evmap.api.ChargepointStatus +import com.johan.evmap.api.availability.ChargepointStatus +import com.johan.evmap.api.goingelectric.ChargeLocation +import com.johan.evmap.api.goingelectric.Chargepoint interface Equatable { override fun equals(other: Any?): Boolean; diff --git a/app/src/main/java/com/johan/evmap/adapter/GalleryAdapter.kt b/app/src/main/java/com/johan/evmap/adapter/GalleryAdapter.kt index 04f555d7..059b23b2 100644 --- a/app/src/main/java/com/johan/evmap/adapter/GalleryAdapter.kt +++ b/app/src/main/java/com/johan/evmap/adapter/GalleryAdapter.kt @@ -8,7 +8,7 @@ import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.ListAdapter import androidx.recyclerview.widget.RecyclerView import com.johan.evmap.R -import com.johan.evmap.api.ChargerPhoto +import com.johan.evmap.api.goingelectric.ChargerPhoto import com.ortiz.touchview.TouchImageView import com.squareup.picasso.Callback import com.squareup.picasso.Picasso diff --git a/app/src/main/java/com/johan/evmap/api/Utils.kt b/app/src/main/java/com/johan/evmap/api/Utils.kt index 315aa201..358c9a4e 100644 --- a/app/src/main/java/com/johan/evmap/api/Utils.kt +++ b/app/src/main/java/com/johan/evmap/api/Utils.kt @@ -1,12 +1,12 @@ package com.johan.evmap.api +import android.location.Location import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.suspendCancellableCoroutine import okhttp3.Call import okhttp3.Callback import okhttp3.Response import org.json.JSONArray -import org.json.JSONObject import java.io.IOException import kotlin.coroutines.resumeWithException @@ -35,4 +35,13 @@ suspend fun Call.await(): Response { } } } +} + +fun distanceBetween( + startLatitude: Double, startLongitude: Double, + endLatitude: Double, endLongitude: Double +): Float { + val distance = floatArrayOf(0f) + Location.distanceBetween(startLatitude, startLongitude, endLatitude, endLongitude, distance) + return distance[0] } \ No newline at end of file diff --git a/app/src/main/java/com/johan/evmap/api/availability/AvailabilityDetector.kt b/app/src/main/java/com/johan/evmap/api/availability/AvailabilityDetector.kt new file mode 100644 index 00000000..a7ad4d5e --- /dev/null +++ b/app/src/main/java/com/johan/evmap/api/availability/AvailabilityDetector.kt @@ -0,0 +1,76 @@ +package com.johan.evmap.api.availability + +import com.facebook.stetho.okhttp3.StethoInterceptor +import com.johan.evmap.api.await +import com.johan.evmap.api.goingelectric.ChargeLocation +import com.johan.evmap.api.goingelectric.Chargepoint +import okhttp3.OkHttpClient +import okhttp3.Request +import java.io.IOException +import java.util.concurrent.TimeUnit + +interface AvailabilityDetector { + suspend fun getAvailability(location: ChargeLocation): ChargeLocationStatus +} + +abstract class BaseAvailabilityDetector(private val client: OkHttpClient) : AvailabilityDetector { + protected suspend fun httpGet(url: String): String { + val request = Request.Builder().url(url).build() + val response = client.newCall(request).await() + + if (!response.isSuccessful) throw IOException(response.message()) + + val str = response.body()!!.string() + return str + } + + protected fun getCorrespondingChargepoint( + cps: Iterable, type: String, power: Double + ): Chargepoint? { + var filter = cps.filter { + it.type == type + } + if (filter.size > 1) { + filter = filter.filter { + if (power > 0) { + it.power == power + } else true + } + // TODO: handle not matching powers + /*if (filter.isEmpty()) { + filter = listOfNotNull(cps.minBy { + abs(it.power - power) + }) + }*/ + } + return filter.getOrNull(0) + } +} + +data class ChargeLocationStatus( + val status: Map>, + val source: String +) + +enum class ChargepointStatus { + AVAILABLE, UNKNOWN, CHARGING, OCCUPIED, FAULTED +} + +class AvailabilityDetectorException(message: String) : Exception(message) + +private val okhttp = OkHttpClient.Builder() + .addNetworkInterceptor(StethoInterceptor()) + .readTimeout(10, TimeUnit.SECONDS) + .connectTimeout(10, TimeUnit.SECONDS) + .build() +val availabilityDetectors = listOf( + NewMotionAvailabilityDetector(okhttp) + /*ChargecloudAvailabilityDetector( + okhttp, + "606a0da0dfdd338ee4134605653d4fd8" + ), // Maingau + ChargecloudAvailabilityDetector( + okhttp, + "6336fe713f2eb7fa04b97ff6651b76f8" + ) // SW Kiel*/ +) \ No newline at end of file diff --git a/app/src/main/java/com/johan/evmap/api/AvailabilityDetector.kt b/app/src/main/java/com/johan/evmap/api/availability/ChargecloudAvailabilityDetector.kt similarity index 54% rename from app/src/main/java/com/johan/evmap/api/AvailabilityDetector.kt rename to app/src/main/java/com/johan/evmap/api/availability/ChargecloudAvailabilityDetector.kt index 75468f2f..48df3432 100644 --- a/app/src/main/java/com/johan/evmap/api/AvailabilityDetector.kt +++ b/app/src/main/java/com/johan/evmap/api/availability/ChargecloudAvailabilityDetector.kt @@ -1,51 +1,35 @@ -package com.johan.evmap.api +package com.johan.evmap.api.availability -import com.facebook.stetho.okhttp3.StethoInterceptor +import com.johan.evmap.api.goingelectric.ChargeLocation +import com.johan.evmap.api.goingelectric.Chargepoint +import com.johan.evmap.api.iterator import kotlinx.coroutines.ExperimentalCoroutinesApi import okhttp3.OkHttpClient -import okhttp3.Request import org.json.JSONObject import java.io.IOException -import java.util.concurrent.TimeUnit private const val radius = 200 // max radius in meters -interface AvailabilityDetector { - suspend fun getAvailability(location: ChargeLocation): ChargeLocationStatus -} - -data class ChargeLocationStatus( - val status: Map>, - val source: String -) - -enum class ChargepointStatus { - AVAILABLE, UNKNOWN, CHARGING, OCCUPIED, FAULTED -} - -class AvailabilityDetectorException(message: String) : Exception(message) - class ChargecloudAvailabilityDetector( - private val client: OkHttpClient, + client: OkHttpClient, private val operatorId: String -) : AvailabilityDetector { +) : BaseAvailabilityDetector(client) { @ExperimentalCoroutinesApi override suspend fun getAvailability(location: ChargeLocation): ChargeLocationStatus { val url = "https://app.chargecloud.de/emobility:ocpi/$operatorId/app/2.0/locations?latitude=${location.coordinates.lat}&longitude=${location.coordinates.lng}&radius=$radius&offset=0&limit=10" - val request = Request.Builder().url(url).build() - val response = client.newCall(request).await() - - if (!response.isSuccessful) throw IOException(response.message()) - - val json = JSONObject(response.body()!!.string()) + val json = JSONObject(httpGet(url)) val statusMessage = json.getString("status_message") if (statusMessage != "Success") throw IOException(statusMessage) val data = json.getJSONArray("data") - if (data.length() > 1) throw AvailabilityDetectorException("found multiple candidates.") - if (data.length() == 0) throw AvailabilityDetectorException("no candidates found.") + if (data.length() > 1) throw AvailabilityDetectorException( + "found multiple candidates." + ) + if (data.length() == 0) throw AvailabilityDetectorException( + "no candidates found." + ) val evses = data.getJSONObject(0).getJSONArray("evses") val chargepointStatus = mutableMapOf>() @@ -61,15 +45,25 @@ class ChargecloudAvailabilityDetector( // find corresponding chargepoint from goingelectric to get correct power val geChargepoint = getCorrespondingChargepoint(location.chargepoints, type, power) - ?: throw AvailabilityDetectorException("Chargepoints from chargecloud API and goingelectric do not match.") - chargepoint = Chargepoint(type, geChargepoint.power, 1) + ?: throw AvailabilityDetectorException( + "Chargepoints from chargecloud API and goingelectric do not match." + ) + chargepoint = Chargepoint( + type, + geChargepoint.power, + 1 + ) statusList = listOf(status) } else { val previousStatus = chargepointStatus[chargepoint]!! statusList = previousStatus + listOf(status) chargepointStatus.remove(chargepoint) chargepoint = - Chargepoint(chargepoint.type, chargepoint.power, chargepoint.count + 1) + Chargepoint( + chargepoint.type, + chargepoint.power, + chargepoint.count + 1 + ) } chargepointStatus[chargepoint] = statusList @@ -79,32 +73,17 @@ class ChargecloudAvailabilityDetector( if (chargepointStatus.keys == location.chargepoints.toSet()) { - return ChargeLocationStatus(chargepointStatus, "chargecloud.de") + return ChargeLocationStatus( + chargepointStatus, + "chargecloud.de" + ) } else { - throw AvailabilityDetectorException("Chargepoints from chargecloud API and goingelectric do not match.") + throw AvailabilityDetectorException( + "Chargepoints from chargecloud API and goingelectric do not match." + ) } } - private fun getCorrespondingChargepoint( - cps: Iterable, type: String, power: Double - ): Chargepoint? { - var filter = cps.filter { - it.type == type && - if (power > 0) { - it.power in power - 2..power + 2 - } else true - } - if (filter.size > 1) { - filter = cps.filter { - it.type == type && - if (power > 0) { - it.power == power - } else true - } - } - return filter.getOrNull(0) - } - private fun getType(string: String): String { return when (string) { "IEC_62196_T2" -> Chargepoint.TYPE_2 @@ -114,14 +93,4 @@ class ChargecloudAvailabilityDetector( else -> throw IllegalArgumentException("unrecognized type $string") } } -} - -private val okhttp = OkHttpClient.Builder() - .addNetworkInterceptor(StethoInterceptor()) - .readTimeout(10, TimeUnit.SECONDS) - .connectTimeout(10, TimeUnit.SECONDS) - .build() -val availabilityDetectors = listOf( - ChargecloudAvailabilityDetector(okhttp, "606a0da0dfdd338ee4134605653d4fd8"), // Maingau - ChargecloudAvailabilityDetector(okhttp, "6336fe713f2eb7fa04b97ff6651b76f8") // SW Kiel -) \ No newline at end of file +} \ No newline at end of file diff --git a/app/src/main/java/com/johan/evmap/api/availability/NewMotionAvailabilityDetector.kt b/app/src/main/java/com/johan/evmap/api/availability/NewMotionAvailabilityDetector.kt new file mode 100644 index 00000000..dc279d0c --- /dev/null +++ b/app/src/main/java/com/johan/evmap/api/availability/NewMotionAvailabilityDetector.kt @@ -0,0 +1,184 @@ +package com.johan.evmap.api.availability + +import com.johan.evmap.api.distanceBetween +import com.johan.evmap.api.goingelectric.ChargeLocation +import com.johan.evmap.api.goingelectric.Chargepoint +import com.squareup.moshi.JsonClass +import okhttp3.OkHttpClient +import retrofit2.Retrofit +import retrofit2.converter.moshi.MoshiConverterFactory +import retrofit2.http.GET +import retrofit2.http.Path + +private const val coordRange = 0.1 // range of latitude and longitude for loading the map +private const val maxDistance = 15 // max distance between reported positions in meters + +interface NewMotionApi { + @GET("markers/{lngMin}/{lngMax}/{latMin}/{latMax}") + suspend fun getMarkers( + @Path("lngMin") lngMin: Double, + @Path("lngMax") lngMax: Double, + @Path("latMin") latMin: Double, + @Path("latMax") latMax: Double + ): List + + @GET("locations/{id}") + suspend fun getLocation(@Path("id") id: Long): NMLocation + + @JsonClass(generateAdapter = true) + data class NMMarker(val coordinates: NMCoordinates, val locationUid: Long) + + @JsonClass(generateAdapter = true) + data class NMCoordinates(val latitude: Double, val longitude: Double) + + @JsonClass(generateAdapter = true) + data class NMLocation( + val uid: Long, + val coordinates: NMCoordinates, + val operatorName: String, + val evses: List + ) + + @JsonClass(generateAdapter = true) + data class NMEvse(val evseId: String, val status: String, val connectors: List) + + @JsonClass(generateAdapter = true) + data class NMConnector( + val connectorType: String, + val electricalProperties: NMElectricalProperties + ) + + @JsonClass(generateAdapter = true) + data class NMElectricalProperties(val powerType: String, val voltage: Int, val amperage: Int) { + fun getPower(): Double { + val phases = when (powerType) { + "AC1Phase" -> 1 + "AC3Phase" -> 3 + else -> 1 + } + val volt = when (voltage) { + 277 -> 230 + else -> voltage + } + val power = volt * amperage * phases + return when (power) { + 3680 -> 3.7 + 11040 -> 11.0 + 22080 -> 22.0 + 43470 -> 43.0 + else -> power / 1000.0 + } + } + } + + companion object { + fun create(client: OkHttpClient): NewMotionApi { + val retrofit = Retrofit.Builder() + .baseUrl("https://my.newmotion.com/api/map/v2/") + .addConverterFactory(MoshiConverterFactory.create()) + .client(client) + .build() + return retrofit.create(NewMotionApi::class.java) + } + } +} + +class NewMotionAvailabilityDetector(client: OkHttpClient) : BaseAvailabilityDetector(client) { + val api = NewMotionApi.create(client) + + override suspend fun getAvailability(location: ChargeLocation): ChargeLocationStatus { + val lat = location.coordinates.lat + val lng = location.coordinates.lng + + // find nearest station to this position + var markers = + api.getMarkers(lng - coordRange, lng + coordRange, lat - coordRange, lat + coordRange) + val nearest = markers.minBy { marker -> + distanceBetween(marker.coordinates.latitude, marker.coordinates.longitude, lat, lng) + } ?: throw AvailabilityDetectorException("no candidates found.") + + // combine related stations + markers = markers.filter { marker -> + distanceBetween( + marker.coordinates.latitude, + marker.coordinates.longitude, + nearest.coordinates.latitude, + nearest.coordinates.longitude + ) < maxDistance + } + + // load details + var details = markers.map { + api.getLocation(it.locationUid) + } + // only include stations from same operator + details = details.filter { + it.operatorName == details[0].operatorName + } + val connectorStatus = details.flatMap { it.evses }.flatMap { evse -> + evse.connectors.map { connector -> + connector to evse.status + } + } + + val chargepointStatus = mutableMapOf>() + connectorStatus.forEach { (connector, statusStr) -> + val power = connector.electricalProperties.getPower() + val type = when (connector.connectorType) { + "Type2" -> Chargepoint.TYPE_2 + "Domestic" -> Chargepoint.SCHUKO + "Type2Combo" -> Chargepoint.CCS + "TepcoCHAdeMO" -> Chargepoint.CHADEMO + else -> throw IllegalArgumentException("unrecognized type ${connector.connectorType}") + } + val status = when (statusStr) { + "Unavailable" -> ChargepointStatus.FAULTED + "Available" -> ChargepointStatus.AVAILABLE + "Occupied" -> ChargepointStatus.CHARGING + "Unspecified" -> ChargepointStatus.UNKNOWN + else -> ChargepointStatus.UNKNOWN + } + + var chargepoint = getCorrespondingChargepoint(chargepointStatus.keys, type, power) + val statusList: List + if (chargepoint == null) { + // find corresponding chargepoint from goingelectric to get correct power + val geChargepoint = + getCorrespondingChargepoint(location.chargepoints, type, power) + ?: throw AvailabilityDetectorException( + "Chargepoints from NewMotion API and goingelectric do not match." + ) + chargepoint = Chargepoint( + type, + geChargepoint.power, + 1 + ) + statusList = listOf(status) + } else { + val previousStatus = chargepointStatus[chargepoint]!! + statusList = previousStatus + listOf(status) + chargepointStatus.remove(chargepoint) + chargepoint = + Chargepoint( + chargepoint.type, + chargepoint.power, + chargepoint.count + 1 + ) + } + + chargepointStatus[chargepoint] = statusList + } + + if (chargepointStatus.keys == location.chargepoints.toSet()) { + return ChargeLocationStatus( + chargepointStatus, + "NewMotion" + ) + } else { + throw AvailabilityDetectorException( + "Chargepoints from NewMotion API and goingelectric do not match." + ) + } + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/johan/evmap/api/GoingElectricAdapters.kt b/app/src/main/java/com/johan/evmap/api/goingelectric/GoingElectricAdapters.kt similarity index 88% rename from app/src/main/java/com/johan/evmap/api/GoingElectricAdapters.kt rename to app/src/main/java/com/johan/evmap/api/goingelectric/GoingElectricAdapters.kt index 4968b39a..61982473 100644 --- a/app/src/main/java/com/johan/evmap/api/GoingElectricAdapters.kt +++ b/app/src/main/java/com/johan/evmap/api/goingelectric/GoingElectricAdapters.kt @@ -1,4 +1,4 @@ -package com.johan.evmap.api +package com.johan.evmap.api.goingelectric import com.squareup.moshi.* import java.lang.reflect.Type @@ -12,7 +12,9 @@ internal class ChargepointListItemJsonAdapterFactory : JsonAdapter.Factory { moshi: Moshi ): JsonAdapter<*>? { if (Types.getRawType(type) == ChargepointListItem::class.java) { - return ChargepointListItemJsonAdapter(moshi) + return ChargepointListItemJsonAdapter( + moshi + ) } else { return null } @@ -24,9 +26,13 @@ internal class ChargepointListItemJsonAdapterFactory : JsonAdapter.Factory { internal class ChargepointListItemJsonAdapter(val moshi: Moshi) : JsonAdapter() { private val clusterAdapter = - moshi.adapter(ChargeLocationCluster::class.java) + moshi.adapter( + ChargeLocationCluster::class.java + ) - private val locationAdapter = moshi.adapter(ChargeLocation::class.java) + private val locationAdapter = moshi.adapter( + ChargeLocation::class.java + ) @FromJson override fun fromJson(reader: JsonReader): ChargepointListItem { @@ -69,9 +75,13 @@ internal class JsonObjectOrFalseAdapter private constructor( moshi: Moshi ): JsonAdapter<*>? { val clazz = Types.getRawType(type) - return when (hasJsonObjectOrFalseAnnotation(annotations)) { + return when (hasJsonObjectOrFalseAnnotation( + annotations + )) { false -> null - true -> JsonObjectOrFalseAdapter(moshi.adapter(clazz)) + true -> JsonObjectOrFalseAdapter( + moshi.adapter(clazz) + ) } } } diff --git a/app/src/main/java/com/johan/evmap/api/GoingElectricApi.kt b/app/src/main/java/com/johan/evmap/api/goingelectric/GoingElectricApi.kt similarity index 97% rename from app/src/main/java/com/johan/evmap/api/GoingElectricApi.kt rename to app/src/main/java/com/johan/evmap/api/goingelectric/GoingElectricApi.kt index 3c96da47..d24e6a6d 100644 --- a/app/src/main/java/com/johan/evmap/api/GoingElectricApi.kt +++ b/app/src/main/java/com/johan/evmap/api/goingelectric/GoingElectricApi.kt @@ -1,4 +1,4 @@ -package com.johan.evmap.api +package com.johan.evmap.api.goingelectric import com.facebook.stetho.okhttp3.StethoInterceptor import com.squareup.moshi.Moshi diff --git a/app/src/main/java/com/johan/evmap/api/GoingElectricModel.kt b/app/src/main/java/com/johan/evmap/api/goingelectric/GoingElectricModel.kt similarity index 99% rename from app/src/main/java/com/johan/evmap/api/GoingElectricModel.kt rename to app/src/main/java/com/johan/evmap/api/goingelectric/GoingElectricModel.kt index df9d894f..1ed1f38a 100644 --- a/app/src/main/java/com/johan/evmap/api/GoingElectricModel.kt +++ b/app/src/main/java/com/johan/evmap/api/goingelectric/GoingElectricModel.kt @@ -1,4 +1,4 @@ -package com.johan.evmap.api +package com.johan.evmap.api.goingelectric import android.content.Context import android.os.Parcelable diff --git a/app/src/main/java/com/johan/evmap/fragment/MapFragment.kt b/app/src/main/java/com/johan/evmap/fragment/MapFragment.kt index 9562925c..0371e21a 100644 --- a/app/src/main/java/com/johan/evmap/fragment/MapFragment.kt +++ b/app/src/main/java/com/johan/evmap/fragment/MapFragment.kt @@ -37,10 +37,10 @@ import com.johan.evmap.REQUEST_LOCATION_PERMISSION import com.johan.evmap.adapter.ConnectorAdapter import com.johan.evmap.adapter.DetailAdapter import com.johan.evmap.adapter.GalleryAdapter -import com.johan.evmap.api.ChargeLocation -import com.johan.evmap.api.ChargeLocationCluster -import com.johan.evmap.api.ChargepointListItem -import com.johan.evmap.api.ChargerPhoto +import com.johan.evmap.api.goingelectric.ChargeLocation +import com.johan.evmap.api.goingelectric.ChargeLocationCluster +import com.johan.evmap.api.goingelectric.ChargepointListItem +import com.johan.evmap.api.goingelectric.ChargerPhoto import com.johan.evmap.databinding.FragmentMapBinding import com.johan.evmap.ui.* import com.johan.evmap.viewmodel.MapPosition diff --git a/app/src/main/java/com/johan/evmap/ui/BindingAdapters.kt b/app/src/main/java/com/johan/evmap/ui/BindingAdapters.kt index becc912e..a1a220a2 100644 --- a/app/src/main/java/com/johan/evmap/ui/BindingAdapters.kt +++ b/app/src/main/java/com/johan/evmap/ui/BindingAdapters.kt @@ -12,7 +12,7 @@ import androidx.recyclerview.widget.RecyclerView import androidx.viewpager2.widget.ViewPager2 import com.google.android.material.floatingactionbutton.FloatingActionButton import com.johan.evmap.R -import com.johan.evmap.api.Chargepoint +import com.johan.evmap.api.goingelectric.Chargepoint @BindingAdapter("goneUnless") diff --git a/app/src/main/java/com/johan/evmap/ui/MarkerUtils.kt b/app/src/main/java/com/johan/evmap/ui/MarkerUtils.kt index b2a4e51c..a8088098 100644 --- a/app/src/main/java/com/johan/evmap/ui/MarkerUtils.kt +++ b/app/src/main/java/com/johan/evmap/ui/MarkerUtils.kt @@ -6,7 +6,7 @@ import androidx.interpolator.view.animation.FastOutLinearInInterpolator import androidx.interpolator.view.animation.LinearOutSlowInInterpolator import com.google.android.gms.maps.model.Marker import com.johan.evmap.R -import com.johan.evmap.api.ChargeLocation +import com.johan.evmap.api.goingelectric.ChargeLocation fun getMarkerTint(charger: ChargeLocation): Int = when { charger.maxPower >= 100 -> R.color.charger_100kw diff --git a/app/src/main/java/com/johan/evmap/viewmodel/MapViewModel.kt b/app/src/main/java/com/johan/evmap/viewmodel/MapViewModel.kt index 5550260f..f371c835 100644 --- a/app/src/main/java/com/johan/evmap/viewmodel/MapViewModel.kt +++ b/app/src/main/java/com/johan/evmap/viewmodel/MapViewModel.kt @@ -5,7 +5,13 @@ import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.google.android.gms.maps.model.LatLngBounds -import com.johan.evmap.api.* +import com.johan.evmap.api.availability.AvailabilityDetectorException +import com.johan.evmap.api.availability.ChargeLocationStatus +import com.johan.evmap.api.availability.availabilityDetectors +import com.johan.evmap.api.goingelectric.ChargeLocation +import com.johan.evmap.api.goingelectric.ChargepointList +import com.johan.evmap.api.goingelectric.ChargepointListItem +import com.johan.evmap.api.goingelectric.GoingElectricApi import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext diff --git a/app/src/main/res/layout/activity_gallery.xml b/app/src/main/res/layout/activity_gallery.xml index 28d30364..cdc02252 100644 --- a/app/src/main/res/layout/activity_gallery.xml +++ b/app/src/main/res/layout/activity_gallery.xml @@ -4,7 +4,7 @@ - + diff --git a/app/src/main/res/layout/detail_view.xml b/app/src/main/res/layout/detail_view.xml index 333cd6c0..ac5a77b7 100644 --- a/app/src/main/res/layout/detail_view.xml +++ b/app/src/main/res/layout/detail_view.xml @@ -5,11 +5,11 @@ - + - + - + diff --git a/app/src/test/java/com/johan/evmap/ApiTests.kt b/app/src/test/java/com/johan/evmap/ApiTests.kt index c858f273..0be410fd 100644 --- a/app/src/test/java/com/johan/evmap/ApiTests.kt +++ b/app/src/test/java/com/johan/evmap/ApiTests.kt @@ -1,6 +1,8 @@ package com.johan.evmap -import com.johan.evmap.api.* +import com.johan.evmap.api.availability.availabilityDetectors +import com.johan.evmap.api.goingelectric.ChargeLocation +import com.johan.evmap.api.goingelectric.GoingElectricApi import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.runBlocking import org.junit.Test