Skip to content

Commit

Permalink
feat(commands) #26: Implment Commands module
Browse files Browse the repository at this point in the history
  • Loading branch information
atschabu committed Feb 21, 2024
1 parent 0112039 commit 148d07f
Show file tree
Hide file tree
Showing 16 changed files with 687 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.izivia.ocpi.toolkit.common

import com.izivia.ocpi.toolkit.transport.domain.HttpRequest

/**
* Example implementation
*
* httpAuth = { req ->
* partnerRepository.getPartnerUrlByCredentialsServerToken(req.parseAuthorizationHeader())!!
* }
*/
fun interface HttpAuthInterface {
suspend fun partnerUrlFromRequest(req: HttpRequest): String
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.izivia.ocpi.toolkit.modules.commands

import com.izivia.ocpi.toolkit.common.*
import com.izivia.ocpi.toolkit.modules.commands.domain.CommandResult
import com.izivia.ocpi.toolkit.modules.credentials.repositories.PartnerRepository
import com.izivia.ocpi.toolkit.transport.TransportClientBuilder
import com.izivia.ocpi.toolkit.transport.domain.HttpMethod
import com.izivia.ocpi.toolkit.transport.domain.HttpRequest

class CommandCpoClient(
private val transportClientBuilder: TransportClientBuilder,
private val partnerRepository: PartnerRepository,
) {
suspend fun postCommandCallback(
commandResult: CommandResult,
partnerUrl: String,
responseUrl: String,
): OcpiResponseBody<Any> =
transportClientBuilder
.build("")
.send(
HttpRequest(
method = HttpMethod.POST,
path = responseUrl,
body = mapper.writeValueAsString(commandResult)
)
.withRequiredHeaders(
requestId = generateUUIDv4Token(),
correlationId = generateUUIDv4Token()
)
.authenticate(partnerRepository = partnerRepository, partnerUrl = partnerUrl)
).parseBody()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.izivia.ocpi.toolkit.modules.commands

import com.izivia.ocpi.toolkit.common.OcpiResponseBody
import com.izivia.ocpi.toolkit.modules.commands.domain.*

interface CommandCpoInterface {
suspend fun postStartSession(
partnerUrl: String,
startSession: StartSession,
): OcpiResponseBody<CommandResponse>

suspend fun postStopSession(
partnerUrl: String,
stopSession: StopSession,
): OcpiResponseBody<CommandResponse>

suspend fun postReserveNow(
partnerUrl: String,
reserveNow: ReserveNow,
): OcpiResponseBody<CommandResponse>

suspend fun postCancelReservation(
partnerUrl: String,
cancelReservation: CancelReservation,
): OcpiResponseBody<CommandResponse>

suspend fun postUnlockConnector(
partnerUrl: String,
unlockConnector: UnlockConnector,
): OcpiResponseBody<CommandResponse>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package com.izivia.ocpi.toolkit.modules.commands

import com.izivia.ocpi.toolkit.common.HttpAuthInterface
import com.izivia.ocpi.toolkit.common.OcpiSelfRegisteringModuleServer
import com.izivia.ocpi.toolkit.common.httpResponse
import com.izivia.ocpi.toolkit.common.mapper
import com.izivia.ocpi.toolkit.modules.commands.domain.*
import com.izivia.ocpi.toolkit.modules.versions.domain.InterfaceRole
import com.izivia.ocpi.toolkit.modules.versions.domain.ModuleID
import com.izivia.ocpi.toolkit.modules.versions.domain.VersionNumber
import com.izivia.ocpi.toolkit.modules.versions.repositories.MutableVersionsRepository
import com.izivia.ocpi.toolkit.transport.TransportServer
import com.izivia.ocpi.toolkit.transport.domain.FixedPathSegment
import com.izivia.ocpi.toolkit.transport.domain.HttpMethod

class CommandCpoServer(
private val httpAuth: HttpAuthInterface,
private val service: CommandCpoInterface,
versionsRepository: MutableVersionsRepository? = null,
basePathOverride: String? = null,
) : OcpiSelfRegisteringModuleServer(
ocpiVersion = VersionNumber.V2_2_1,
moduleID = ModuleID.commands,
interfaceRole = InterfaceRole.RECEIVER,
versionsRepository = versionsRepository,
basePathOverride = basePathOverride
) {

override suspend fun doRegisterOn(transportServer: TransportServer) {
transportServer.handle(
method = HttpMethod.POST,
path = basePathSegments + FixedPathSegment("START_SESSION"),
) { req ->
val senderPlatformUrl = httpAuth.partnerUrlFromRequest(req)
val startSession = mapper.readValue(req.body, StartSession::class.java)

req.httpResponse {
service.postStartSession(senderPlatformUrl, startSession)
}
}

transportServer.handle(
method = HttpMethod.POST,
path = basePathSegments + FixedPathSegment("STOP_SESSION"),
) { req ->
val senderPlatformUrl = httpAuth.partnerUrlFromRequest(req)
val stopSession = mapper.readValue(req.body, StopSession::class.java)

req.httpResponse {
service.postStopSession(senderPlatformUrl, stopSession = stopSession)
}
}

transportServer.handle(
method = HttpMethod.POST,
path = basePathSegments + FixedPathSegment("RESERVE_NOW"),
) { req ->
val senderPlatformUrl = httpAuth.partnerUrlFromRequest(req)
val reserveNow = mapper.readValue(req.body, ReserveNow::class.java)

req.httpResponse {
service.postReserveNow(senderPlatformUrl, reserveNow)
}
}

transportServer.handle(
method = HttpMethod.POST,
path = basePathSegments + FixedPathSegment("CANCEL_RESERVATION"),
) { req ->
val senderPlatformUrl = httpAuth.partnerUrlFromRequest(req)
val cancelReservation = mapper.readValue(req.body, CancelReservation::class.java)

req.httpResponse {
service.postCancelReservation(senderPlatformUrl, cancelReservation)
}
}

transportServer.handle(
method = HttpMethod.POST,
path = basePathSegments + FixedPathSegment("UNLOCK_CONNECTOR"),
) { req ->
val senderPlatformUrl = httpAuth.partnerUrlFromRequest(req)
val unlockConnector = mapper.readValue(req.body, UnlockConnector::class.java)

req.httpResponse {
service.postUnlockConnector(senderPlatformUrl, unlockConnector)
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
package com.izivia.ocpi.toolkit.modules.commands

import com.izivia.ocpi.toolkit.common.*
import com.izivia.ocpi.toolkit.modules.commands.domain.*
import com.izivia.ocpi.toolkit.modules.credentials.repositories.PartnerRepository
import com.izivia.ocpi.toolkit.modules.tokens.domain.Token
import com.izivia.ocpi.toolkit.modules.versions.domain.ModuleID
import com.izivia.ocpi.toolkit.transport.TransportClient
import com.izivia.ocpi.toolkit.transport.TransportClientBuilder
import com.izivia.ocpi.toolkit.transport.domain.HttpMethod
import com.izivia.ocpi.toolkit.transport.domain.HttpRequest
import java.time.Instant

class CommandEmspClient(
private val transportClientBuilder: TransportClientBuilder,
private val serverVersionsEndpointUrl: String,
private val partnerRepository: PartnerRepository,
private val callbackBaseUrl: String,
) {

private suspend fun buildTransport(): TransportClient = transportClientBuilder
.buildFor(
module = ModuleID.commands,
partnerUrl = serverVersionsEndpointUrl,
partnerRepository = partnerRepository
)

suspend fun postStartSession(
token: Token,
locationId: CiString,
evseId: CiString?,
connectorId: CiString?,
authorizationReference: CiString,
): OcpiResponseBody<CommandResponse> =
with(buildTransport()) {
send(
HttpRequest(
method = HttpMethod.POST,
path = "/START_SESSION",
body = mapper.writeValueAsString(
StartSession(
responseUrl = "${callbackBaseUrl}/START_SESSION/callback/${authorizationReference}",
token = token,
locationId = locationId,
evseUid = evseId,
connectorId = connectorId,
authorizationReference = authorizationReference,
)
)
)
.withRequiredHeaders(
requestId = generateUUIDv4Token(),
correlationId = generateUUIDv4Token()
)
.authenticate(partnerRepository = partnerRepository, partnerUrl = serverVersionsEndpointUrl)
)
.parseBody()
}

suspend fun postStopSession(sessionId: String): OcpiResponseBody<CommandResponse> =
with(buildTransport()) {
send(
HttpRequest(
method = HttpMethod.POST,
path = "/STOP_SESSION",
body = mapper.writeValueAsString(
StopSession(
responseUrl = "${callbackBaseUrl}/STOP_SESSION/callback/${sessionId}",
sessionId = sessionId,
)
)
)
.withRequiredHeaders(
requestId = generateUUIDv4Token(),
correlationId = generateUUIDv4Token()
)
.authenticate(partnerRepository = partnerRepository, partnerUrl = serverVersionsEndpointUrl)
)
.parseBody()
}

suspend fun postReserveNow(
token: Token,
expiryDate: Instant,
reservationId: CiString,
locationId: CiString,
evseUid: CiString?,
authorizationReference: CiString?,
): OcpiResponseBody<CommandResponse> =
with(buildTransport()) {
send(
HttpRequest(
method = HttpMethod.POST,
path = "/RESERVE_NOW",
body = mapper.writeValueAsString(
ReserveNow(
responseUrl = "${callbackBaseUrl}/RESERVE_NOW/callback/${reservationId}",
token = token,
expiryDate = expiryDate,
reservationId = reservationId,
locationId = locationId,
evseUid = evseUid,
authorizationReference = authorizationReference,
)
)
)
.withRequiredHeaders(
requestId = generateUUIDv4Token(),
correlationId = generateUUIDv4Token()
)
.authenticate(partnerRepository = partnerRepository, partnerUrl = serverVersionsEndpointUrl)
)
.parseBody()
}

suspend fun postCancelReservation(reservationId: CiString): OcpiResponseBody<CommandResponse> =
with(buildTransport()) {
send(
HttpRequest(
method = HttpMethod.POST,
path = "/CANCEL_RESERVATION",
body = mapper.writeValueAsString(
CancelReservation(
responseUrl = "${callbackBaseUrl}/CANCEL_RESERVATION/callback/${reservationId}",
reservationId = reservationId,
)
)
)
.withRequiredHeaders(
requestId = generateUUIDv4Token(),
correlationId = generateUUIDv4Token()
)
.authenticate(partnerRepository = partnerRepository, partnerUrl = serverVersionsEndpointUrl)
)
.parseBody()
}

suspend fun postUnlockConnector(
locationId: CiString,
evseUid: CiString,
connectorId: CiString,
): OcpiResponseBody<CommandResponse> =
with(buildTransport()) {
send(
HttpRequest(
method = HttpMethod.POST,
path = "/UNLOCK_CONNECTOR",
body = mapper.writeValueAsString(
UnlockConnector(
responseUrl = "${callbackBaseUrl}/UNLOCK_CONNECTOR/callback/${locationId}/${evseUid}/${connectorId}",
locationId = locationId,
evseUid = evseUid,
connectorId = connectorId,
)
)
)
.withRequiredHeaders(
requestId = generateUUIDv4Token(),
correlationId = generateUUIDv4Token()
)
.authenticate(partnerRepository = partnerRepository, partnerUrl = serverVersionsEndpointUrl)
)
.parseBody()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.izivia.ocpi.toolkit.modules.commands

import com.izivia.ocpi.toolkit.common.OcpiResponseBody
import com.izivia.ocpi.toolkit.modules.commands.domain.CommandResult

interface CommandEmspInterface {
suspend fun postCallbackStartSession(
authorizationReference: String,
result: CommandResult,
): OcpiResponseBody<String>

suspend fun postCallbackStopSession(sessionId: String, result: CommandResult): OcpiResponseBody<String>

suspend fun postCallbackReserveNow(reservationId: String, result: CommandResult): OcpiResponseBody<String>

suspend fun postCallbackCancelReservation(reservationId: String, result: CommandResult): OcpiResponseBody<String>

suspend fun postCallbackUnlockConnector(
locationId: String,
evseId: String,
connectorId: String,
result: CommandResult,
): OcpiResponseBody<String>
}
Loading

0 comments on commit 148d07f

Please sign in to comment.