implement availability detector with NewMotion API

This commit is contained in:
Johan von Forstner
2020-04-13 13:10:06 +02:00
parent 80edbe66ce
commit c800cca21e
15 changed files with 1566 additions and 84 deletions

View File

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

View File

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

View File

@@ -45,6 +45,37 @@ abstract class BaseAvailabilityDetector(private val client: OkHttpClient) : Avai
}
return filter.getOrNull(0)
}
protected fun matchChargepoints(
connectors: Map<Long, Pair<Double, String>>,
chargepoints: List<Chargepoint>
): Map<Chargepoint, Set<Long>> {
// 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(

View File

@@ -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<Chargepoint, List<ChargepointStatus>>()
val nmConnectors = mutableMapOf<Long, Pair<Double, String>>()
val nmStatus = mutableMapOf<Long, ChargepointStatus>()
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<ChargepointStatus>
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"
)
}
}

View File

@@ -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<ChargepointList>
@GET("/chargepoints/")
@GET("chargepoints/")
fun getChargepointDetail(@Query("ge_id") id: Long): Call<ChargepointList>
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()

View File

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

View File

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

View File

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

View File

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

View File

@@ -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"
}
]

View File

@@ -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"
}
]

View File

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

View File

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

View File

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

View File

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