diff --git a/app/build.gradle b/app/build.gradle index 56924524..5f31b435 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -94,6 +94,7 @@ dependencies { implementation 'com.facebook.stetho:stetho:1.5.1' implementation 'com.facebook.stetho:stetho-okhttp3:1.5.1' testImplementation 'junit:junit:4.12' + testImplementation "com.squareup.okhttp3:mockwebserver:3.14.7" //noinspection GradleDependency testImplementation 'org.json:json:20080701' androidTestImplementation 'androidx.test.ext:junit:1.1.1' 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 358c9a4e..4496ebdc 100644 --- a/app/src/main/java/com/johan/evmap/api/Utils.kt +++ b/app/src/main/java/com/johan/evmap/api/Utils.kt @@ -1,6 +1,5 @@ package com.johan.evmap.api -import android.location.Location import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.suspendCancellableCoroutine import okhttp3.Call @@ -37,11 +36,22 @@ suspend fun Call.await(): Response { } } +const val earthRadiusKm: Double = 6372.8 + 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] +): Double { + // see https://rosettacode.org/wiki/Haversine_formula#Java + val dLat = Math.toRadians(endLatitude - startLatitude); + val dLon = Math.toRadians(endLongitude - endLongitude); + val originLat = Math.toRadians(startLatitude); + val destinationLat = Math.toRadians(endLatitude); + + val a = Math.pow(Math.sin(dLat / 2), 2.toDouble()) + Math.pow( + Math.sin(dLon / 2), + 2.toDouble() + ) * Math.cos(originLat) * Math.cos(destinationLat); + val c = 2 * Math.asin(Math.sqrt(a)); + return earthRadiusKm * c * 1000; } \ 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 index a7ad4d5e..babb98eb 100644 --- a/app/src/main/java/com/johan/evmap/api/availability/AvailabilityDetector.kt +++ b/app/src/main/java/com/johan/evmap/api/availability/AvailabilityDetector.kt @@ -45,6 +45,37 @@ abstract class BaseAvailabilityDetector(private val client: OkHttpClient) : Avai } return filter.getOrNull(0) } + + + protected fun matchChargepoints( + connectors: Map>, + chargepoints: List + ): Map> { + // iterate over each connector type + val types = connectors.map { it.value.second }.distinct().toSet() + val geTypes = chargepoints.map { it.type }.distinct().toSet() + if (types != geTypes) throw AvailabilityDetectorException("chargepoints do not match") + return types.flatMap { type -> + // find connectors of this type + val connsOfType = connectors.filter { it.value.second == type } + // find powers this connector is available as + val powers = connsOfType.map { it.value.first }.distinct().sorted() + // find corresponding powers in GE data + val gePowers = + chargepoints.filter { it.type == type }.map { it.power }.distinct().sorted() + + // if the distinct number of powers is the same, try to match. + if (powers.size == gePowers.size) { + gePowers.zip(powers).map { (gePower, power) -> + val chargepoint = chargepoints.find { it.type == type && it.power == gePower }!! + val ids = connsOfType.filter { it.value.first == power }.keys + chargepoint to ids + } + } else { + throw AvailabilityDetectorException("chargepoints do not match") + } + }.toMap() + } } data class ChargeLocationStatus( 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 index dc279d0c..b69b9217 100644 --- a/app/src/main/java/com/johan/evmap/api/availability/NewMotionAvailabilityDetector.kt +++ b/app/src/main/java/com/johan/evmap/api/availability/NewMotionAvailabilityDetector.kt @@ -44,6 +44,7 @@ interface NewMotionApi { @JsonClass(generateAdapter = true) data class NMConnector( + val uid: Long, val connectorType: String, val electricalProperties: NMElectricalProperties ) @@ -72,9 +73,9 @@ interface NewMotionApi { } companion object { - fun create(client: OkHttpClient): NewMotionApi { + fun create(client: OkHttpClient, baseUrl: String? = null): NewMotionApi { val retrofit = Retrofit.Builder() - .baseUrl("https://my.newmotion.com/api/map/v2/") + .baseUrl(baseUrl ?: "https://my.newmotion.com/api/map/v2/") .addConverterFactory(MoshiConverterFactory.create()) .client(client) .build() @@ -83,8 +84,9 @@ interface NewMotionApi { } } -class NewMotionAvailabilityDetector(client: OkHttpClient) : BaseAvailabilityDetector(client) { - val api = NewMotionApi.create(client) +class NewMotionAvailabilityDetector(client: OkHttpClient, baseUrl: String? = null) : + BaseAvailabilityDetector(client) { + val api = NewMotionApi.create(client, baseUrl) override suspend fun getAvailability(location: ChargeLocation): ChargeLocationStatus { val lat = location.coordinates.lat @@ -121,8 +123,10 @@ class NewMotionAvailabilityDetector(client: OkHttpClient) : BaseAvailabilityDete } } - val chargepointStatus = mutableMapOf>() + val nmConnectors = mutableMapOf>() + val nmStatus = mutableMapOf() connectorStatus.forEach { (connector, statusStr) -> + val id = connector.uid val power = connector.electricalProperties.getPower() val type = when (connector.connectorType) { "Type2" -> Chargepoint.TYPE_2 @@ -138,47 +142,18 @@ class NewMotionAvailabilityDetector(client: OkHttpClient) : BaseAvailabilityDete "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 + nmConnectors.put(id, power to type) + nmStatus.put(id, status) } - if (chargepointStatus.keys == location.chargepoints.toSet()) { - return ChargeLocationStatus( - chargepointStatus, - "NewMotion" - ) - } else { - throw AvailabilityDetectorException( - "Chargepoints from NewMotion API and goingelectric do not match." - ) + val match = matchChargepoints(nmConnectors, location.chargepoints) + val chargepointStatus = match.mapValues { entry -> + entry.value.map { nmStatus[it]!! } } + return ChargeLocationStatus( + chargepointStatus, + "NewMotion" + ) } } \ No newline at end of file diff --git a/app/src/main/java/com/johan/evmap/api/goingelectric/GoingElectricApi.kt b/app/src/main/java/com/johan/evmap/api/goingelectric/GoingElectricApi.kt index d24e6a6d..ebc64704 100644 --- a/app/src/main/java/com/johan/evmap/api/goingelectric/GoingElectricApi.kt +++ b/app/src/main/java/com/johan/evmap/api/goingelectric/GoingElectricApi.kt @@ -10,7 +10,7 @@ import retrofit2.http.GET import retrofit2.http.Query interface GoingElectricApi { - @GET("/chargepoints/") + @GET("chargepoints/") fun getChargepoints( @Query("sw_lat") swlat: Double, @Query("sw_lng") sw_lng: Double, @Query("ne_lat") ne_lat: Double, @Query("ne_lng") ne_lng: Double, @@ -19,11 +19,14 @@ interface GoingElectricApi { @Query("cluster_distance") clusterDistance: Int ): Call - @GET("/chargepoints/") + @GET("chargepoints/") fun getChargepointDetail(@Query("ge_id") id: Long): Call companion object { - fun create(apikey: String): GoingElectricApi { + fun create( + apikey: String, + baseurl: String = "https://api.goingelectric.de" + ): GoingElectricApi { val client = OkHttpClient.Builder() .addInterceptor { chain -> // add API key to every request @@ -42,7 +45,7 @@ interface GoingElectricApi { .build() val retrofit = Retrofit.Builder() - .baseUrl("https://api.goingelectric.de") + .baseUrl(baseurl) .addConverterFactory(MoshiConverterFactory.create(moshi)) .client(client) .build() diff --git a/app/src/test/java/com/johan/evmap/ApiTests.kt b/app/src/test/java/com/johan/evmap/ApiTests.kt deleted file mode 100644 index 0be410fd..00000000 --- a/app/src/test/java/com/johan/evmap/ApiTests.kt +++ /dev/null @@ -1,32 +0,0 @@ -package com.johan.evmap - -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 - -class ApiTests { - val api: GoingElectricApi - - init { - val apikey = System.getenv("GOINGELECTRIC_API_KEY") - ?: throw IllegalArgumentException("please provide a GoingElectric.de API key in the GOINGELECTRIC_API_KEY environment variable.") - api = GoingElectricApi.create(apikey) - } - - @ExperimentalCoroutinesApi - @Test - fun apiTest() { - val charger = api.getChargepointDetail(2105) - .execute().body()!! - .chargelocations[0] as ChargeLocation - print(charger) - - runBlocking { - val result = availabilityDetectors[0].getAvailability(charger) - print(result) - } - } -} diff --git a/app/src/test/java/com/johan/evmap/NewMotionAvailabilityDetectorTest.kt b/app/src/test/java/com/johan/evmap/NewMotionAvailabilityDetectorTest.kt new file mode 100644 index 00000000..ad9d1933 --- /dev/null +++ b/app/src/test/java/com/johan/evmap/NewMotionAvailabilityDetectorTest.kt @@ -0,0 +1,87 @@ +package com.johan.evmap + +import com.johan.evmap.api.availability.NewMotionAvailabilityDetector +import com.johan.evmap.api.goingelectric.ChargeLocation +import com.johan.evmap.api.goingelectric.GoingElectricApi +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.runBlocking +import okhttp3.OkHttpClient +import okhttp3.mockwebserver.Dispatcher +import okhttp3.mockwebserver.MockResponse +import okhttp3.mockwebserver.MockWebServer +import okhttp3.mockwebserver.RecordedRequest +import org.junit.Test +import java.net.HttpURLConnection + +class NewMotionAvailabilityDetectorTest { + val api: GoingElectricApi + val webServer = MockWebServer() + val newMotion: NewMotionAvailabilityDetector + + init { + webServer.start() + + val apikey = "" + val baseurl = webServer.url("/ge/").toString() + api = GoingElectricApi.create(apikey, baseurl) + newMotion = NewMotionAvailabilityDetector( + OkHttpClient.Builder().build(), + webServer.url("/nm/").toString() + ) + + webServer.dispatcher = object : Dispatcher() { + val notFoundResponse = MockResponse().setResponseCode(HttpURLConnection.HTTP_NOT_FOUND) + + override fun dispatch(request: RecordedRequest): MockResponse { + val segments = request.requestUrl.pathSegments() + val urlHead = segments.subList(0, 2).joinToString("/") + when (urlHead) { + "ge/chargepoints" -> { + val id = request.requestUrl.queryParameter("ge_id") + val body = readResource("/chargers/$id.json") ?: return notFoundResponse + return MockResponse().setResponseCode(HttpURLConnection.HTTP_OK) + .setBody(body) + } + "nm/markers" -> { + val urlTail = segments.subList(2, segments.size).joinToString("/") + val id = when (urlTail) { + "9.47108/9.67108/54.4116/54.6116" -> 2105 + "9.444284/9.644283999999999/54.376699/54.576699000000005" -> 18284 + else -> -1 + } + val body = + readResource("/newmotion/$id/markers.json") ?: return notFoundResponse + return MockResponse().setResponseCode(HttpURLConnection.HTTP_OK) + .setBody(body) + } + "nm/locations" -> { + val id = segments.last() + val body = readResource("/newmotion/$id.json") ?: return notFoundResponse + return MockResponse().setResponseCode(HttpURLConnection.HTTP_OK) + .setBody(body) + } + else -> return notFoundResponse + } + } + } + } + + private fun readResource(s: String) = + NewMotionAvailabilityDetectorTest::class.java.getResource(s)?.readText() + + @ExperimentalCoroutinesApi + @Test + fun apiTest() { + for (chargepoint in listOf(2105L, 18284L)) { + val charger = api.getChargepointDetail(chargepoint) + .execute().body()!! + .chargelocations[0] as ChargeLocation + println(charger) + + runBlocking { + val result = newMotion.getAvailability(charger) + println(result) + } + } + } +} diff --git a/app/src/test/resources/chargers/18284.json b/app/src/test/resources/chargers/18284.json new file mode 100644 index 00000000..7e2bac51 --- /dev/null +++ b/app/src/test/resources/chargers/18284.json @@ -0,0 +1,438 @@ +{ + "status": "ok", + "chargelocations": [ + { + "ge_id": 18284, + "name": "Autohof Wikingerland", + "address": { + "city": "Busdorf", + "country": "Deutschland", + "postcode": "24866", + "street": "Wittgenstein 2" + }, + "coordinates": { + "lat": 54.476699, + "lng": 9.544284 + }, + "chargepoints": [ + { + "type": "CCS", + "power": 320, + "count": 2 + }, + { + "type": "CCS", + "power": 160, + "count": 1 + }, + { + "type": "CHAdeMO", + "power": 50, + "count": 2 + }, + { + "type": "CCS", + "power": 50, + "count": 1 + }, + { + "type": "Typ2", + "power": 43, + "count": 1 + } + ], + "network": "allego", + "operator": "Allego GmbH", + "cost": { + "freecharging": false, + "freeparking": true, + "description_short": false, + "description_long": false + }, + "fault_report": { + "created": 1582412400, + "description": "Ausfall Ladesäule #16853, Ladesäule #36103, Ladepunkt #108227 - combo_typ2, Ladepunkt #108228 - chademo\n" + }, + "verified": true, + "barrierfree": false, + "openinghours": { + "24/7": true, + "description": false + }, + "url": "//www.goingelectric.de/stromtankstellen/Deutschland/Busdorf/Autohof-Wikingerland-Wittgenstein-2/18284/", + "ladeweile": false, + "location_description": "Hinter der Tankstelle.", + "general_information": false, + "photos": [ + { + "id": 83288 + }, + { + "id": 87397 + }, + { + "id": 48854 + }, + { + "id": 36436 + }, + { + "id": 65830 + } + ], + "chargecards": [ + { + "id": 274 + }, + { + "id": 11 + }, + { + "id": 30 + }, + { + "id": 7 + }, + { + "id": 335 + }, + { + "id": 349 + }, + { + "id": 9 + }, + { + "id": 75 + }, + { + "id": 114 + }, + { + "id": 319 + }, + { + "id": 8 + }, + { + "id": 57 + }, + { + "id": 36 + }, + { + "id": 229 + }, + { + "id": 368 + }, + { + "id": 230 + }, + { + "id": 207 + }, + { + "id": 211 + }, + { + "id": 124 + }, + { + "id": 261 + }, + { + "id": 43 + }, + { + "id": 155 + }, + { + "id": 56 + }, + { + "id": 169 + }, + { + "id": 186 + }, + { + "id": 119 + }, + { + "id": 251 + }, + { + "id": 222 + }, + { + "id": 142 + }, + { + "id": 200 + }, + { + "id": 224 + }, + { + "id": 13 + }, + { + "id": 203 + }, + { + "id": 44 + }, + { + "id": 177 + }, + { + "id": 350 + }, + { + "id": 82 + }, + { + "id": 201 + }, + { + "id": 242 + }, + { + "id": 226 + }, + { + "id": 170 + }, + { + "id": 322 + }, + { + "id": 96 + }, + { + "id": 277 + }, + { + "id": 97 + }, + { + "id": 332 + }, + { + "id": 187 + }, + { + "id": 167 + }, + { + "id": 338 + }, + { + "id": 216 + }, + { + "id": 303 + }, + { + "id": 132 + }, + { + "id": 352 + }, + { + "id": 102 + }, + { + "id": 312 + }, + { + "id": 125 + }, + { + "id": 248 + }, + { + "id": 291 + }, + { + "id": 402 + }, + { + "id": 139 + }, + { + "id": 376 + }, + { + "id": 249 + }, + { + "id": 111 + }, + { + "id": 112 + }, + { + "id": 236 + }, + { + "id": 28 + }, + { + "id": 120 + }, + { + "id": 91 + }, + { + "id": 326 + }, + { + "id": 107 + }, + { + "id": 246 + }, + { + "id": 171 + }, + { + "id": 204 + }, + { + "id": 288 + }, + { + "id": 304 + }, + { + "id": 263 + }, + { + "id": 301 + }, + { + "id": 318 + }, + { + "id": 336 + }, + { + "id": 254 + }, + { + "id": 275 + }, + { + "id": 192 + }, + { + "id": 302 + }, + { + "id": 225 + }, + { + "id": 297 + }, + { + "id": 333 + }, + { + "id": 358 + }, + { + "id": 356 + }, + { + "id": 257 + }, + { + "id": 351 + }, + { + "id": 282 + }, + { + "id": 103 + }, + { + "id": 394 + }, + { + "id": 243 + }, + { + "id": 343 + }, + { + "id": 334 + }, + { + "id": 190 + }, + { + "id": 316 + }, + { + "id": 346 + }, + { + "id": 256 + }, + { + "id": 386 + }, + { + "id": 311 + }, + { + "id": 238 + }, + { + "id": 408 + }, + { + "id": 290 + }, + { + "id": 392 + }, + { + "id": 340 + }, + { + "id": 337 + }, + { + "id": 285 + }, + { + "id": 347 + }, + { + "id": 330 + }, + { + "id": 281 + }, + { + "id": 369 + }, + { + "id": 366 + }, + { + "id": 342 + }, + { + "id": 317 + }, + { + "id": 412 + } + ] + } + ] +} \ No newline at end of file diff --git a/app/src/test/resources/chargers/2105.json b/app/src/test/resources/chargers/2105.json new file mode 100644 index 00000000..4ea582de --- /dev/null +++ b/app/src/test/resources/chargers/2105.json @@ -0,0 +1,219 @@ +{ + "status": "ok", + "chargelocations": [ + { + "ge_id": 2105, + "name": "Hafen", + "address": { + "city": "Schleswig", + "country": "Deutschland", + "postcode": "24837", + "street": "Am Hafen 5" + }, + "coordinates": { + "lat": 54.5116, + "lng": 9.57108 + }, + "chargepoints": [ + { + "type": "Typ2", + "power": 22, + "count": 2 + }, + { + "type": "Schuko", + "power": 2.3, + "count": 2 + } + ], + "network": "be.energised", + "operator": "Schleswiger Stadtwerke GmbH", + "cost": { + "freecharging": false, + "freeparking": true, + "description_short": false, + "description_long": "Mit Kundenkarte der Stadtwerke kostenlos, sonst abhängig vom Abrechnungspartner\r\nhttps://www.schleswiger-stadtwerke.de/content/unternehmen/emobilitaet/" + }, + "fault_report": false, + "verified": true, + "barrierfree": true, + "openinghours": { + "24/7": true, + "description": false + }, + "url": "//www.goingelectric.de/stromtankstellen/Deutschland/Schleswig/Hafen-Am-Hafen-5/2105/", + "ladeweile": "Schleswiger Stadthafen mit Fischbistro, Restaurant und Eisdiele. Schleswiger Dom und Fußgängerzone in fußläufiger Entfernung.", + "location_description": false, + "general_information": false, + "photos": [ + { + "id": 3552 + }, + { + "id": 10268 + }, + { + "id": 3553 + } + ], + "chargecards": [ + { + "id": 274 + }, + { + "id": 11 + }, + { + "id": 7 + }, + { + "id": 335 + }, + { + "id": 349 + }, + { + "id": 9 + }, + { + "id": 75 + }, + { + "id": 319 + }, + { + "id": 8 + }, + { + "id": 36 + }, + { + "id": 229 + }, + { + "id": 368 + }, + { + "id": 207 + }, + { + "id": 124 + }, + { + "id": 43 + }, + { + "id": 251 + }, + { + "id": 200 + }, + { + "id": 13 + }, + { + "id": 44 + }, + { + "id": 242 + }, + { + "id": 322 + }, + { + "id": 96 + }, + { + "id": 338 + }, + { + "id": 216 + }, + { + "id": 132 + }, + { + "id": 312 + }, + { + "id": 248 + }, + { + "id": 139 + }, + { + "id": 402 + }, + { + "id": 249 + }, + { + "id": 120 + }, + { + "id": 223 + }, + { + "id": 326 + }, + { + "id": 288 + }, + { + "id": 355 + }, + { + "id": 336 + }, + { + "id": 195 + }, + { + "id": 333 + }, + { + "id": 356 + }, + { + "id": 351 + }, + { + "id": 343 + }, + { + "id": 103 + }, + { + "id": 346 + }, + { + "id": 375 + }, + { + "id": 256 + }, + { + "id": 386 + }, + { + "id": 408 + }, + { + "id": 392 + }, + { + "id": 347 + }, + { + "id": 330 + }, + { + "id": 342 + }, + { + "id": 366 + } + ] + } + ] +} \ No newline at end of file diff --git a/app/src/test/resources/newmotion/18284/markers.json b/app/src/test/resources/newmotion/18284/markers.json new file mode 100644 index 00000000..e2d55173 --- /dev/null +++ b/app/src/test/resources/newmotion/18284/markers.json @@ -0,0 +1,84 @@ +[ + { + "markerType": "SingleLocation", + "uniqueKey": "2469352_1", + "status": "Available", + "coordinates": { + "latitude": 54.489211, + "longitude": 9.55383 + }, + "evseCount": 2, + "geoHash": "u1wvcrky", + "locationUid": 2469352, + "authorizationMethods": [ + "NewMotionApp", + "RFIDToken" + ], + "operatorId": "AT-HTB" + }, + { + "markerType": "SingleLocation", + "uniqueKey": "2469608_1", + "status": "Available", + "coordinates": { + "latitude": 54.490386, + "longitude": 9.551067 + }, + "evseCount": 2, + "geoHash": "u1wvcrdv", + "locationUid": 2469608, + "authorizationMethods": [ + "NewMotionApp", + "RFIDToken" + ], + "operatorId": "AT-HTB" + }, + { + "markerType": "SingleLocation", + "uniqueKey": "2459405_1", + "status": "Unknown", + "coordinates": { + "latitude": 54.476667, + "longitude": 9.544566 + }, + "evseCount": 3, + "geoHash": "u1wvcjnj", + "locationUid": 2459405, + "authorizationMethods": [ + "RFIDToken" + ], + "operatorId": "DE-ALL" + }, + { + "markerType": "SingleLocation", + "uniqueKey": "2738212_1", + "status": "Unavailable", + "coordinates": { + "latitude": 54.476691, + "longitude": 9.544368 + }, + "evseCount": 2, + "geoHash": "u1wvcjjv", + "locationUid": 2738212, + "authorizationMethods": [ + "RFIDToken" + ], + "operatorId": "DE-ALL" + }, + { + "markerType": "SingleLocation", + "uniqueKey": "2722151_1", + "status": "Available", + "coordinates": { + "latitude": 54.476673, + "longitude": 9.544472 + }, + "evseCount": 2, + "geoHash": "u1wvcjnj", + "locationUid": 2722151, + "authorizationMethods": [ + "RFIDToken" + ], + "operatorId": "DE-ALL" + } +] \ No newline at end of file diff --git a/app/src/test/resources/newmotion/2105/markers.json b/app/src/test/resources/newmotion/2105/markers.json new file mode 100644 index 00000000..b41ca400 --- /dev/null +++ b/app/src/test/resources/newmotion/2105/markers.json @@ -0,0 +1,70 @@ +[ + { + "markerType": "SingleLocation", + "uniqueKey": "2469498_1", + "status": "Available", + "coordinates": { + "latitude": 54.513826, + "longitude": 9.545038 + }, + "evseCount": 2, + "geoHash": "u1wy15yq", + "locationUid": 2469498, + "authorizationMethods": [ + "NewMotionApp", + "RFIDToken" + ], + "operatorId": "AT-HTB" + }, + { + "markerType": "SingleLocation", + "uniqueKey": "2802993_1", + "status": "Occupied", + "coordinates": { + "latitude": 54.514816, + "longitude": 9.566383 + }, + "evseCount": 2, + "geoHash": "u1wy1sn5", + "locationUid": 2802993, + "authorizationMethods": [ + "NewMotionApp", + "RFIDToken" + ], + "operatorId": "AT-HTB" + }, + { + "markerType": "SingleLocation", + "uniqueKey": "2469318_1", + "status": "Available", + "coordinates": { + "latitude": 54.514135, + "longitude": 9.571629 + }, + "evseCount": 2, + "geoHash": "u1wy1gcz", + "locationUid": 2469318, + "authorizationMethods": [ + "NewMotionApp", + "RFIDToken" + ], + "operatorId": "AT-HTB" + }, + { + "markerType": "SingleLocation", + "uniqueKey": "2469255_1", + "status": "Available", + "coordinates": { + "latitude": 54.511612, + "longitude": 9.571052 + }, + "evseCount": 4, + "geoHash": "u1wy1g93", + "locationUid": 2469255, + "authorizationMethods": [ + "NewMotionApp", + "RFIDToken" + ], + "operatorId": "AT-HTB" + } +] \ No newline at end of file diff --git a/app/src/test/resources/newmotion/2459405.json b/app/src/test/resources/newmotion/2459405.json new file mode 100644 index 00000000..39a63d5f --- /dev/null +++ b/app/src/test/resources/newmotion/2459405.json @@ -0,0 +1,156 @@ +{ + "uid": 2459405, + "externalId": "DEALLEGO000826", + "coordinates": { + "latitude": 54.476667, + "longitude": 9.544566 + }, + "operatorName": "Allego", + "operatorId": "DE-ALL", + "address": { + "streetAndNumber": "Wittgenstein 2", + "postalCode": "24866", + "city": "Schleswig-Busdorf", + "country": "DEU" + }, + "accessibility": { + "status": "Unspecified", + "remark": "" + }, + "evses": [ + { + "uid": 742093, + "externalId": "DEALLEGO0008261", + "evseId": "DE*ALL*EGO0008261", + "status": "Unknown", + "connectors": [ + { + "uid": 625943, + "externalId": "1", + "connectorType": "Type2Combo", + "electricalProperties": { + "powerType": "DC", + "voltage": 400, + "amperage": 125 + }, + "fixedCable": true, + "tariff": { + "perKWh": 0.59, + "currency": "EUR", + "updated": "2020-04-13T09:57:18Z", + "updatedBy": "Default", + "structure": "Default" + }, + "updated": "2018-06-13T13:28:06Z", + "updatedBy": "Feed" + } + ], + "authorizationMethods": [ + "RFIDToken" + ], + "updated": "2020-04-08T23:33:18Z" + }, + { + "uid": 742094, + "externalId": "DEALLEGO0008262", + "evseId": "DE*ALL*EGO0008262", + "status": "Unknown", + "connectors": [ + { + "uid": 625944, + "externalId": "1", + "connectorType": "TepcoCHAdeMO", + "electricalProperties": { + "powerType": "DC", + "voltage": 400, + "amperage": 125 + }, + "fixedCable": true, + "tariff": { + "perKWh": 0.59, + "currency": "EUR", + "updated": "2020-04-13T09:57:18Z", + "updatedBy": "Default", + "structure": "Default" + }, + "updated": "2018-06-13T13:28:06Z", + "updatedBy": "Feed" + } + ], + "authorizationMethods": [ + "RFIDToken" + ], + "updated": "2020-04-08T23:33:18Z" + }, + { + "uid": 742095, + "externalId": "DEALLEGO0008263", + "evseId": "DE*ALL*EGO0008263", + "status": "Unknown", + "connectors": [ + { + "uid": 625945, + "externalId": "1", + "connectorType": "Type2", + "electricalProperties": { + "powerType": "AC3Phase", + "voltage": 230, + "amperage": 63 + }, + "fixedCable": true, + "tariff": { + "perKWh": 0.59, + "currency": "EUR", + "updated": "2020-04-13T09:57:18Z", + "updatedBy": "Default", + "structure": "Default" + }, + "updated": "2017-11-21T14:38:49Z", + "updatedBy": "Feed" + } + ], + "authorizationMethods": [ + "RFIDToken" + ], + "updated": "2020-04-08T23:33:18Z" + } + ], + "openingHours": [ + { + "weekDay": "Sun", + "startTime": "00:00", + "endTime": "23:59" + }, + { + "weekDay": "Mon", + "startTime": "00:00", + "endTime": "23:59" + }, + { + "weekDay": "Tue", + "startTime": "00:00", + "endTime": "23:59" + }, + { + "weekDay": "Wed", + "startTime": "00:00", + "endTime": "23:59" + }, + { + "weekDay": "Thu", + "startTime": "00:00", + "endTime": "23:59" + }, + { + "weekDay": "Fri", + "startTime": "00:00", + "endTime": "23:59" + }, + { + "weekDay": "Sat", + "startTime": "00:00", + "endTime": "23:59" + } + ], + "updated": "2020-01-29T08:44:31Z" +} \ No newline at end of file diff --git a/app/src/test/resources/newmotion/2469255.json b/app/src/test/resources/newmotion/2469255.json new file mode 100644 index 00000000..184cc6e7 --- /dev/null +++ b/app/src/test/resources/newmotion/2469255.json @@ -0,0 +1,192 @@ +{ + "uid": 2469255, + "externalId": "5e21f3af-d179-11e4-a755-005056b332c9", + "coordinates": { + "latitude": 54.511612, + "longitude": 9.571052 + }, + "operatorName": "has.to.be", + "operatorId": "AT-HTB", + "address": { + "streetAndNumber": "Am Hafen 1", + "postalCode": "24837", + "city": "Schleswig", + "country": "DEU" + }, + "accessibility": { + "status": "FreePublic" + }, + "evses": [ + { + "uid": 761531, + "externalId": "DE*SSW*E1000001", + "evseId": "DE*SSW*E1000001", + "status": "Available", + "connectors": [ + { + "uid": 647702, + "externalId": "0", + "connectorType": "Domestic", + "electricalProperties": { + "powerType": "AC1Phase", + "voltage": 240, + "amperage": 16 + }, + "fixedCable": false, + "tariff": { + "perMinute": 0.1309, + "currency": "EUR", + "updated": "2020-04-13T09:54:33Z", + "updatedBy": "Default", + "structure": "Default" + }, + "updated": "2020-01-29T15:32:02Z", + "updatedBy": "Feed" + } + ], + "authorizationMethods": [ + "NewMotionApp", + "RFIDToken" + ], + "updated": "2020-04-12T14:11:18Z" + }, + { + "uid": 761532, + "externalId": "DE*SSW*E1000002", + "evseId": "DE*SSW*E1000002", + "status": "Available", + "connectors": [ + { + "uid": 647703, + "externalId": "0", + "connectorType": "Type2", + "electricalProperties": { + "powerType": "AC3Phase", + "voltage": 277, + "amperage": 32 + }, + "fixedCable": false, + "tariff": { + "perMinute": 0.1309, + "currency": "EUR", + "updated": "2020-04-13T09:54:33Z", + "updatedBy": "Default", + "structure": "Default" + }, + "updated": "2020-01-29T15:32:02Z", + "updatedBy": "Feed" + } + ], + "authorizationMethods": [ + "NewMotionApp", + "RFIDToken" + ], + "updated": "2020-04-12T14:11:18Z" + }, + { + "uid": 761533, + "externalId": "DE*SSW*E1000003", + "evseId": "DE*SSW*E1000003", + "status": "Occupied", + "connectors": [ + { + "uid": 647704, + "externalId": "0", + "connectorType": "Domestic", + "electricalProperties": { + "powerType": "AC1Phase", + "voltage": 240, + "amperage": 16 + }, + "fixedCable": false, + "tariff": { + "perMinute": 0.1309, + "currency": "EUR", + "updated": "2020-04-13T09:54:33Z", + "updatedBy": "Default", + "structure": "Default" + }, + "updated": "2020-01-29T15:32:02Z", + "updatedBy": "Feed" + } + ], + "authorizationMethods": [ + "NewMotionApp", + "RFIDToken" + ], + "updated": "2020-04-13T07:03:52Z" + }, + { + "uid": 761534, + "externalId": "DE*SSW*E1000004", + "evseId": "DE*SSW*E1000004", + "status": "Occupied", + "connectors": [ + { + "uid": 647705, + "externalId": "0", + "connectorType": "Type2", + "electricalProperties": { + "powerType": "AC3Phase", + "voltage": 277, + "amperage": 32 + }, + "fixedCable": false, + "tariff": { + "perMinute": 0.1309, + "currency": "EUR", + "updated": "2020-04-13T09:54:33Z", + "updatedBy": "Default", + "structure": "Default" + }, + "updated": "2020-01-29T15:32:02Z", + "updatedBy": "Feed" + } + ], + "authorizationMethods": [ + "NewMotionApp", + "RFIDToken" + ], + "updated": "2020-04-13T07:03:52Z" + } + ], + "openingHours": [ + { + "weekDay": "Sun", + "startTime": "00:00", + "endTime": "23:59" + }, + { + "weekDay": "Mon", + "startTime": "00:00", + "endTime": "23:59" + }, + { + "weekDay": "Tue", + "startTime": "00:00", + "endTime": "23:59" + }, + { + "weekDay": "Wed", + "startTime": "00:00", + "endTime": "23:59" + }, + { + "weekDay": "Thu", + "startTime": "00:00", + "endTime": "23:59" + }, + { + "weekDay": "Fri", + "startTime": "00:00", + "endTime": "23:59" + }, + { + "weekDay": "Sat", + "startTime": "00:00", + "endTime": "23:59" + } + ], + "updated": "2020-01-29T15:32:02Z", + "operatorComment": "Please note that prices have increased.\nBitte beachten Sie, dass die Preise gestiegen sind.\nSi prega di notare che i prezzi sono aumentati.\nHoud er rekening mee dat de prijzen zijn gestegen." +} \ No newline at end of file diff --git a/app/src/test/resources/newmotion/2722151.json b/app/src/test/resources/newmotion/2722151.json new file mode 100644 index 00000000..834dca50 --- /dev/null +++ b/app/src/test/resources/newmotion/2722151.json @@ -0,0 +1,124 @@ +{ + "uid": 2722151, + "externalId": "DEALLEGO020014", + "coordinates": { + "latitude": 54.476673, + "longitude": 9.544472 + }, + "operatorName": "Allego", + "operatorId": "DE-ALL", + "address": { + "streetAndNumber": "Wittgenstein 2", + "postalCode": "24866", + "city": "Schleswig-Busdorf", + "country": "DEU" + }, + "accessibility": { + "status": "Unspecified", + "remark": "" + }, + "evses": [ + { + "uid": 1358404, + "externalId": "DEALLEGO0200141", + "evseId": "DE*ALL*EGO0200141", + "status": "Available", + "connectors": [ + { + "uid": 1293518, + "externalId": "1", + "connectorType": "Type2Combo", + "electricalProperties": { + "powerType": "DC", + "voltage": 400, + "amperage": 200 + }, + "fixedCable": true, + "tariff": { + "perKWh": 0.59, + "currency": "EUR", + "updated": "2020-04-13T09:57:01Z", + "updatedBy": "Default", + "structure": "Default" + }, + "updated": "2020-03-19T15:22:03Z", + "updatedBy": "Feed" + } + ], + "authorizationMethods": [ + "RFIDToken" + ], + "updated": "2020-04-12T13:44:41Z" + }, + { + "uid": 1357390, + "externalId": "DEALLEGO0200142", + "evseId": "DE*ALL*EGO0200142", + "status": "Available", + "connectors": [ + { + "uid": 1292446, + "externalId": "1", + "connectorType": "Type2Combo", + "electricalProperties": { + "powerType": "DC", + "voltage": 400, + "amperage": 500 + }, + "fixedCable": true, + "tariff": { + "perKWh": 0.59, + "currency": "EUR", + "updated": "2020-04-13T09:57:01Z", + "updatedBy": "Default", + "structure": "Default" + }, + "updated": "2020-03-19T15:22:03Z", + "updatedBy": "Feed" + } + ], + "authorizationMethods": [ + "RFIDToken" + ], + "updated": "2020-04-12T13:44:41Z" + } + ], + "openingHours": [ + { + "weekDay": "Sun", + "startTime": "00:00", + "endTime": "23:59" + }, + { + "weekDay": "Mon", + "startTime": "00:00", + "endTime": "23:59" + }, + { + "weekDay": "Tue", + "startTime": "00:00", + "endTime": "23:59" + }, + { + "weekDay": "Wed", + "startTime": "00:00", + "endTime": "23:59" + }, + { + "weekDay": "Thu", + "startTime": "00:00", + "endTime": "23:59" + }, + { + "weekDay": "Fri", + "startTime": "00:00", + "endTime": "23:59" + }, + { + "weekDay": "Sat", + "startTime": "00:00", + "endTime": "23:59" + } + ], + "updated": "2020-03-28T07:43:29Z" +} \ No newline at end of file diff --git a/app/src/test/resources/newmotion/2738212.json b/app/src/test/resources/newmotion/2738212.json new file mode 100644 index 00000000..6e3acbc2 --- /dev/null +++ b/app/src/test/resources/newmotion/2738212.json @@ -0,0 +1,124 @@ +{ + "uid": 2738212, + "externalId": "DEALLEGO020013", + "coordinates": { + "latitude": 54.476691, + "longitude": 9.544368 + }, + "operatorName": "Allego", + "operatorId": "DE-ALL", + "address": { + "streetAndNumber": "Wittgenstein 2", + "postalCode": "24866", + "city": "Schleswig-Busdorf", + "country": "DEU" + }, + "accessibility": { + "status": "Unspecified", + "remark": "" + }, + "evses": [ + { + "uid": 1353671, + "externalId": "DEALLEGO0200131", + "evseId": "DE*ALL*EGO0200131", + "status": "Unavailable", + "connectors": [ + { + "uid": 1288548, + "externalId": "1", + "connectorType": "TepcoCHAdeMO", + "electricalProperties": { + "powerType": "DC", + "voltage": 400, + "amperage": 125 + }, + "fixedCable": true, + "tariff": { + "perKWh": 0.59, + "currency": "EUR", + "updated": "2020-04-13T09:56:41Z", + "updatedBy": "Default", + "structure": "Default" + }, + "updated": "2019-10-05T15:08:20Z", + "updatedBy": "Feed" + } + ], + "authorizationMethods": [ + "RFIDToken" + ], + "updated": "2020-03-26T10:52:16Z" + }, + { + "uid": 1345434, + "externalId": "DEALLEGO0200132", + "evseId": "DE*ALL*EGO0200132", + "status": "Unavailable", + "connectors": [ + { + "uid": 1279689, + "externalId": "1", + "connectorType": "Type2Combo", + "electricalProperties": { + "powerType": "DC", + "voltage": 400, + "amperage": 500 + }, + "fixedCable": true, + "tariff": { + "perKWh": 0.59, + "currency": "EUR", + "updated": "2020-04-13T09:56:41Z", + "updatedBy": "Default", + "structure": "Default" + }, + "updated": "2020-03-19T15:22:03Z", + "updatedBy": "Feed" + } + ], + "authorizationMethods": [ + "RFIDToken" + ], + "updated": "2020-03-26T10:52:16Z" + } + ], + "openingHours": [ + { + "weekDay": "Sun", + "startTime": "00:00", + "endTime": "23:59" + }, + { + "weekDay": "Mon", + "startTime": "00:00", + "endTime": "23:59" + }, + { + "weekDay": "Tue", + "startTime": "00:00", + "endTime": "23:59" + }, + { + "weekDay": "Wed", + "startTime": "00:00", + "endTime": "23:59" + }, + { + "weekDay": "Thu", + "startTime": "00:00", + "endTime": "23:59" + }, + { + "weekDay": "Fri", + "startTime": "00:00", + "endTime": "23:59" + }, + { + "weekDay": "Sat", + "startTime": "00:00", + "endTime": "23:59" + } + ], + "updated": "2020-03-19T15:22:03Z" +} \ No newline at end of file