Add jitpack to your repositories section in your gradle or maven build file
repositories {
    maven("https://jitpack.io")
}OCPP V16
dependencies {
    implementation("com.monta.library.ocpp:core:<version>")
    implementation("com.monta.library.ocpp:v16:<version>")
}OCPP V201
dependencies {
    implementation("com.monta.library.ocpp:core:<version>")
    implementation("com.monta.library.ocpp:v201:<version>")
}The OCPP protocol is an RPC framework with a request-response protocol
The synchronicity of the protocol is well described in OCPP-J-1.6 in chapter 4.1.1 Synchronicity
In summary this describes that there can always only be one message in flight, in either direction.
The library should be seen as a library. I.e. it is a passive component.
- if any thread pools should be used, they should be passed in from the outside when creating an instance of the library.
 - if any logging framework should be used it should also be passed in from the outside.
 
Chapter 4 of the OCPP-1.6 specification
The library should be usable both in a blocking and an asynchronous way for messages initiated by the charge point.
/**
 * A blocking core profile implementation. Today such an interface is found
 * in `com.monta.ocpp.profiles.core.CoreProfileListener`
 */
CoreProfileListenerSync {
    /**
     * @throws OCPPCallErrorException on unable to handle authorize
     */
    override fun authorize(
        request: AuthorizeRequest
    ): AuthorizeConfirmation
}
/**
 * An callback based core profile implementation
 */
CoreProfileListenerASync {
    override fun authorize(
        request: AuthorizeRequest,
        onError: (CallError) -> Unit,
        onSuccess: (AuthorizeConfirmation) -> Unit
    )
}For both scenarios we need to figure out how to handle timeouts in our own code.
The implementation in the library should be relatively straight forward
- Parse the incoming message into a Kotlin type
 - Find the profile that should handle it - if not supported, send a CallError to the charge point
 - Call the profile and let it handle e.g. the 
Authorize - When the library gets the 
AuthorizeConfirmationformat it to a json string and send it back on the same WS connection it was received on 
Chapter 5 of the OCPP-1.6 specification
The library should be usable both in a blocking and an asynchronous way for messages initiated by the OCPP server.
/**
 * A blocking core profile implementation. Today such an implementation is found
 * in `com.monta.ocpp.service.ChargePointConnection`
 */
CoreProfileSync {
    /**
     * @throws OCPPCallErrorException on unable to handle reset
     */
    override fun reset(
        request: ResetRequest
    ): Future<ResetConfirmation>
}
/**
 * A callback core profile implementation. Maybe this can be implemented in a generic way
 * using `java.util.concurrent.CompletionStage`?
 */
CoreProfileASync {
    /**
     * `onSuccess` will be called by the OCPP library when a response is received from the
     * charge point.
     * `onError` will be called by the OCPP library if an error or no response is received
     * from the charge point
     */
    override fun reset(
        request: ResetRequest,
        onSuccess: (ResetConfirmation) -> Unit,
        onError: (CallError) -> Unit
    )
}Messages initiated by us and sent to the charge point is a little bit more difficult.
- The message should be send to an object that contains the WS session
 - Format the message to a OCPP json string
 - Send it over the WS connection
 - Synchronize so that when we receive the response object, we can parse it and either unblock the waiting thread or call the callback objects
 
A rough blocking implementation of this is today in com.monta.ocpp.service.ChargePointConnection which implements
CoreProfile