From 85bf04504b8697256deb3ff913bef7e03d5c04ff Mon Sep 17 00:00:00 2001 From: Danilo Bargen Date: Thu, 27 Jan 2022 00:34:26 +0100 Subject: [PATCH] Make Chargepoint.power nullable Not all data sources provide power for all connectors (e.g. OpenChargeMap and OpenStreetMap don't always). Even without the power level, knowing what connectors there are is still useful. --- .../api/availability/AvailabilityDetector.kt | 4 +-- .../evmap/api/chargeprice/ChargepriceModel.kt | 8 ++--- .../api/openchargemap/OpenChargeMapModel.kt | 2 +- .../net/vonforst/evmap/model/ChargersModel.kt | 36 ++++++++++++++----- .../java/net/vonforst/evmap/ui/MarkerUtils.kt | 16 +++++---- app/src/main/res/layout/item_connector.xml | 2 +- 6 files changed, 44 insertions(+), 24 deletions(-) diff --git a/app/src/main/java/net/vonforst/evmap/api/availability/AvailabilityDetector.kt b/app/src/main/java/net/vonforst/evmap/api/availability/AvailabilityDetector.kt index 95378ddb..efb5ebe9 100644 --- a/app/src/main/java/net/vonforst/evmap/api/availability/AvailabilityDetector.kt +++ b/app/src/main/java/net/vonforst/evmap/api/availability/AvailabilityDetector.kt @@ -86,7 +86,7 @@ abstract class BaseAvailabilityDetector(private val client: OkHttpClient) : Avai // find corresponding powers in GE data val gePowers = chargepoints.filter { equivalentPlugTypes(it.type).any { it == type } } - .map { it.power }.distinct().sorted() + .mapNotNull { it.power }.distinct().sorted() // if the distinct number of powers is the same, try to match. if (powers.size == gePowers.size) { @@ -131,7 +131,7 @@ data class ChargeLocationStatus( (connectors == null || connectors.map { equivalentPlugTypes(it) }.any { equivalent -> it.type in equivalent }) - && (minPower == null || it.power > minPower) + && (minPower == null || (it.power != null && it.power > minPower)) } return this.copy(status = statusFiltered) } diff --git a/app/src/main/java/net/vonforst/evmap/api/chargeprice/ChargepriceModel.kt b/app/src/main/java/net/vonforst/evmap/api/chargeprice/ChargepriceModel.kt index 024678dd..e237d17c 100644 --- a/app/src/main/java/net/vonforst/evmap/api/chargeprice/ChargepriceModel.kt +++ b/app/src/main/java/net/vonforst/evmap/api/chargeprice/ChargepriceModel.kt @@ -48,11 +48,9 @@ data class ChargepriceStation( charger.coordinates.lat, charger.chargepriceData.country, charger.chargepriceData.network, - charger.chargepoints.zip(plugTypes).filter { - equivalentPlugTypes(it.first.type).any { it in compatibleConnectors } - }.map { - ChargepriceChargepoint(it.first.power, it.second) - } + charger.chargepoints.zip(plugTypes) + .filter { equivalentPlugTypes(it.first.type).any { it in compatibleConnectors } } + .map { ChargepriceChargepoint(it.first.power ?: 0.0, it.second) } ) } } diff --git a/app/src/main/java/net/vonforst/evmap/api/openchargemap/OpenChargeMapModel.kt b/app/src/main/java/net/vonforst/evmap/api/openchargemap/OpenChargeMapModel.kt index cc2e4206..bb4aa762 100644 --- a/app/src/main/java/net/vonforst/evmap/api/openchargemap/OpenChargeMapModel.kt +++ b/app/src/main/java/net/vonforst/evmap/api/openchargemap/OpenChargeMapModel.kt @@ -141,7 +141,7 @@ data class OCMConnection( ) { fun convert(refData: OCMReferenceData) = Chargepoint( convertConnectionTypeFromOCM(connectionTypeId, refData), - power ?: 0.0, + power, quantity ?: 1 ) diff --git a/app/src/main/java/net/vonforst/evmap/model/ChargersModel.kt b/app/src/main/java/net/vonforst/evmap/model/ChargersModel.kt index ac95723c..522e0733 100644 --- a/app/src/main/java/net/vonforst/evmap/model/ChargersModel.kt +++ b/app/src/main/java/net/vonforst/evmap/model/ChargersModel.kt @@ -64,7 +64,7 @@ data class ChargeLocation( /** * maximum power available from this charger. */ - val maxPower: Double + val maxPower: Double? get() { return maxPower() } @@ -72,17 +72,20 @@ data class ChargeLocation( /** * Gets the maximum power available from certain connectors of this charger. */ - fun maxPower(connectors: Set? = null): Double { - return chargepoints.filter { connectors?.contains(it.type) ?: true } - .map { it.power }.maxOrNull() ?: 0.0 + fun maxPower(connectors: Set? = null): Double? { + return chargepoints + .filter { connectors?.contains(it.type) ?: true } + .mapNotNull { it.power } + .maxOrNull() } fun isMulti(filteredConnectors: Set? = null): Boolean { var chargepoints = chargepointsMerged .filter { filteredConnectors?.contains(it.type) ?: true } - if (maxPower(filteredConnectors) >= 43) { + val chargepointMaxPower = maxPower(filteredConnectors) + if (chargepointMaxPower != null && chargepointMaxPower >= 43) { // fast charger -> only count fast chargers - chargepoints = chargepoints.filter { it.power >= 43 } + chargepoints = chargepoints.filter {it.power != null && it.power >= 43 } } val connectors = chargepoints.map { it.type }.distinct().toSet() @@ -306,9 +309,24 @@ data class Address( @Parcelize @JsonClass(generateAdapter = true) -data class Chargepoint(val type: String, val power: Double, val count: Int) : Equatable, - Parcelable { - fun formatPower(): String { +data class Chargepoint( + // The chargepoint type (use one of the constants in the companion object) + val type: String, + // Power in kW (or null if unknown) + val power: Double?, + // How many instances of this plug/socket are available? + val count: Int, +) : Equatable, Parcelable { + fun hasKnownPower(): Boolean = power != null + + /** + * If chargepoint power is defined, format it into a string. + * Otherwise, return null. + */ + fun formatPower(): String? { + if (power == null) { + return null + } val powerFmt = if (power - power.toInt() == 0.0) { "%.0f".format(power) } else { diff --git a/app/src/main/java/net/vonforst/evmap/ui/MarkerUtils.kt b/app/src/main/java/net/vonforst/evmap/ui/MarkerUtils.kt index 15a68661..c71d5cad 100644 --- a/app/src/main/java/net/vonforst/evmap/ui/MarkerUtils.kt +++ b/app/src/main/java/net/vonforst/evmap/ui/MarkerUtils.kt @@ -13,12 +13,16 @@ import kotlin.math.max fun getMarkerTint( charger: ChargeLocation, connectors: Set? = null -): Int = when { - charger.maxPower(connectors) >= 100 -> R.color.charger_100kw - charger.maxPower(connectors) >= 43 -> R.color.charger_43kw - charger.maxPower(connectors) >= 20 -> R.color.charger_20kw - charger.maxPower(connectors) >= 11 -> R.color.charger_11kw - else -> R.color.charger_low +): Int { + val maxPower = charger.maxPower(connectors) + return when { + maxPower == null -> R.color.charger_low + maxPower >= 100 -> R.color.charger_100kw + maxPower >= 43 -> R.color.charger_43kw + maxPower >= 20 -> R.color.charger_20kw + maxPower >= 11 -> R.color.charger_11kw + else -> R.color.charger_low + } } class MarkerAnimator(val gen: ChargerIconGenerator) { diff --git a/app/src/main/res/layout/item_connector.xml b/app/src/main/res/layout/item_connector.xml index 5f1676ab..6dc4c3a0 100644 --- a/app/src/main/res/layout/item_connector.xml +++ b/app/src/main/res/layout/item_connector.xml @@ -4,7 +4,6 @@ xmlns:tools="http://schemas.android.com/tools"> - @@ -74,6 +73,7 @@ android:layout_marginBottom="8dp" android:text="@{item.chargepoint.formatPower()}" android:textAppearance="@style/TextAppearance.Material3.BodySmall" + app:goneUnless="@{item.chargepoint.hasKnownPower()}" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent"