{"id":13634682,"url":"https://github.com/izivia/ocpp-toolkit","last_synced_at":"2026-01-14T01:57:40.370Z","repository":{"id":37407772,"uuid":"501708979","full_name":"IZIVIA/ocpp-toolkit","owner":"IZIVIA","description":"a Kotlin library to perform OCPP operations","archived":false,"fork":false,"pushed_at":"2024-03-28T09:50:24.000Z","size":2495,"stargazers_count":28,"open_issues_count":6,"forks_count":7,"subscribers_count":2,"default_branch":"dev","last_synced_at":"2024-03-28T10:58:07.946Z","etag":null,"topics":["charging-station","electric-vehicles","ev-charging","evse","kotlin","ocpp"],"latest_commit_sha":null,"homepage":"","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/IZIVIA.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2022-06-09T15:27:06.000Z","updated_at":"2024-04-23T11:46:31.373Z","dependencies_parsed_at":"2023-02-03T22:17:11.952Z","dependency_job_id":"79c7d883-3037-47c6-aa5b-485c8cfea1eb","html_url":"https://github.com/IZIVIA/ocpp-toolkit","commit_stats":{"total_commits":413,"total_committers":18,"mean_commits":"22.944444444444443","dds":0.7554479418886199,"last_synced_commit":"e17a6c6072bf73b1d4a2ce5a62068a11ab913572"},"previous_names":[],"tags_count":53,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/IZIVIA%2Focpp-toolkit","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/IZIVIA%2Focpp-toolkit/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/IZIVIA%2Focpp-toolkit/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/IZIVIA%2Focpp-toolkit/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/IZIVIA","download_url":"https://codeload.github.com/IZIVIA/ocpp-toolkit/tar.gz/refs/heads/dev","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249565248,"owners_count":21292427,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["charging-station","electric-vehicles","ev-charging","evse","kotlin","ocpp"],"created_at":"2024-08-02T00:00:29.895Z","updated_at":"2026-01-14T01:57:40.338Z","avatar_url":"https://github.com/IZIVIA.png","language":"Kotlin","funding_links":[],"categories":["OCPP"],"sub_categories":["OCPP Libraries"],"readme":"# OCPP Toolkit\n\n[![OCPP CI](https://github.com/IZIVIA/ocpp-toolkit/actions/workflows/ci.yml/badge.svg)](https://github.com/IZIVIA/ocpp-toolkit/actions/workflows/ci.yml)\n\nThis project aim is to provide a Kotlin library to perform OCPP operations.\nFor more information about OCPP (Open Charge Point Protocol), see https://www.openchargealliance.org/)\n\n## Goal \n\nThe aim is to support:\n- both the CSMS and the Charging Station sides\n- versions 1.5, 1.6 and 2.0.1 of OCPP\n- WS/JSON (OCPP-J - all versions) and SOAP (OCPP-S ; 1.x versions only) flavor for the transport\n\nIt can be used:\n- to simulate a charging station, eg to test a CSMS\n- to simulate a CSMS, eg to test a Charging Station\n- to implement a CSMS\n- to implement a ChargingStation controller (if the use of Kotlin fit your requirements)\n\nThe aim is to be a strict implementation of OCPP protocol, with no business logic: you use it as a library, and you own the business logic.\n\nWe also attempt to provide a generic API, trying to make switching between ocpp versions transparent. The design between versions of OCPP being sometimes very different, the generic API may not cover all aspects with high fidelity.\n\n## Status\n\nCurrently the ChargingStation side of versions 1.6 and 2.0.1 are fully supported in OCPP-J flavor - except the security requirements besides support for http basic auth. This includes all the data structures described by the specification, with json serialisation verified against the json schemas provided in the specification.\n\nSupport of CSMS side, OCPP 1.5 and SOAP flavor is planned.\n\nSupport for security requirements like SSL and mutual certificates is under discussion, as it can be achieved using a proxy like Envoy.\n\n## Usage of the API\n\nWith the API, you can establish a connection to a CSMS with OCPP 1.6 or OCPP 2.0.\nThen, you can send requests and get responses from the CSMS. Doing so, you can simulate\na whole transaction process.\n\n### OCPP 1.6 Example\n\nWith the API, you can perform instructions one after the other. In those examples, we're doing full transactions.\n\nOCPP 1.6 Charge : \n\n```kotlin \n//establish a connection to the CSMS\nval connection = Ocpp16ConnectionToCSMS(\n        chargePointId = chargPointId,\n        csmsUrl = csmsUrl,\n        transportType = transport,\n        ocppCSCallbacks = OcppCSCallbacks16()\n)\nconnection.connect()\n\n//the idTag variable is used to make unique transaction, so, we can use it to stare at who started a transaction for example\nval idTag = \"321\"\n\n//send an authorize request to the CSMS. We are retreiving the response from the CSMS throught the response variable.\nval response: AuthorizeResp16 = connection.authorize(RequestMetadata(chargPointId),AuthorizeReq16(idTag = idTag )).response\n\n//We're checking if the Authorization request has been accepted by the CSMS.\nif (response.idTagInfo.status == AuthorizationStatus16.Accepted) {\n\n    println(\"Authorization Accepted\")\n\n    //As the Authorization has been accepted, we can start a transaction, but before,\n    //we need to change the Status to Preparing\n    connection.statusNotification(\n        meta = RequestMetadata(chargPointId),\n        request = StatusNotificationReq16(\n            connectorId = 1,\n            errorCode = ChargePointErrorCode16.NoError,\n            status = ChargePointStatus16.Preparing\n        )\n    )\n\n    //We can now start a transaction by sending a StartTransaction request to the CSMS.\n    //We can identify this transaction thanks to the idTag parameter\n    //This function returns a response generated by the CSMS\n    val response: StartTransactionResp16 =\n        connection.startTransaction(\n            meta = RequestMetadata(chargPointId),\n            request = StartTransactionReq16(\n                connectorId = 4,\n                idTag = idTag,\n                meterStart = 0,\n                now()\n            )\n        ).response\n\n    //we are retrieving the transactionId from the reponse of our previous transaction request.\n    val transactionId = response.transactionId\n\n    println(\"TransactionId : $transactionId\")\n\n    // As the authorization has been accepted and that we have sent and receive a response for our startTransaction,\n    // we can now set the charge status to Charging.\n    // In order to do this, we send a statusNotification to the CSMS notifying that the status has changed to Charging\n    connection.statusNotification(\n        meta = RequestMetadata(chargPointId),\n        request = StatusNotificationReq16(\n            connectorId = 1,\n            errorCode = ChargePointErrorCode16.NoError,\n            status = ChargePointStatus16.Charging\n        )\n    )\n}\n\nconnection.close()\n```\n\nOCPP 1.6 Remote Charge :\n```kotlin \nvar remoteStartTransactionReq: RemoteStartTransactionReq16? = null\n\n//As previously said, the idTag variable is used to make unique transaction, so, we can use it to stare at who started a transaction for example\nval idTag = \"Tag2\"\n\n//define the callback for the remoteTransactionRequest\n//It returns a RemoteTransactionResponse\nval ocppCSCallbacks = object : OcppCSCallbacks16() {\n    override fun remoteStartTransaction(req: RemoteStartTransactionReq16): RemoteStartTransactionResp16 {\n        remoteStartTransactionReq = req\n        return RemoteStartTransactionResp16(status = RemoteStartStopStatus16.Accepted)\n    }\n}\n\n//establish a connection to the CSMS\nval connection = Ocpp16ConnectionToCSMS(\n        chargePointId = chargPointId,\n        csmsUrl = csmsUrl,\n        transportType = transport,\n        ocppCSCallbacks = ocppCSCallbacks\n)\nconnection.connect()\n\n//defining the timeout delay for receiving a remoteTransactionRequest\nval waitUntil = now() + 1.toDuration(DurationUnit.MINUTES)\n\n//We are waiting for the remote start request from the CSMS\nwhile (remoteStartTransactionReq == null \u0026\u0026 now() \u003c waitUntil) {\n    sleep(1000)\n}\n\n//We are checking if there was a remoteTransactionRequest sent\nif (remoteStartTransactionReq != null) {\n    println(\"${remoteStartTransactionReq?.idTag}\")\n\n    //As the Authorization has been accepted, we can start a transaction, but before,\n    //we need to change the Status to Preparing\n    connection.statusNotification(\n        meta = RequestMetadata(chargPointId),\n        request = StatusNotificationReq16(\n            connectorId = 1,\n            errorCode = ChargePointErrorCode16.NoError,\n            status = ChargePointStatus16.Preparing\n        )\n    )\n\n    //We can now start a transaction by sending a StartTransaction request to the CSMS.\n    //We can identify this transaction thanks to the idTag parameter\n    //This function returns a response generated by the CSMS\n    val response: StartTransactionResp16 =\n        connection.startTransaction(\n            meta = RequestMetadata(chargPointId),\n            StartTransactionReq16(\n                connectorId = 1,\n                idTag = idTag,\n                meterStart = 0,\n                timestamp = now()\n            )\n        ).response\n\n    //we are retrieving the transactionId from the reponse of our previous transaction request.\n    val transactionId = response.transactionId\n\n    // As the authorization has been accepted and that we have sent and receive a response for our startTransaction,\n    // we can now set the charge status to Charging.\n    // In order to do this, we send a statusNotification to the CSMS notifying that the status has changed to Charging\n    connection.statusNotification(\n        meta = RequestMetadata(chargPointId),\n        StatusNotificationReq16(\n            connectorId = 1,\n            errorCode = ChargePointErrorCode16.NoError,\n            status = ChargePointStatus16.Charging\n        )\n    )\n}\nconnection.close()\n```\n\n### OCPP 2.0 Example\n\nOCPP 2.0 Charge :\n```kotlin \nval connection = Ocpp20ConnectionToCSMS(\n        chargePointId = chargPointId,\n        csmsUrl = csmsUrl,\n        transportType = transport,\n        ocppCSCallbacks = OcppCSCallbacks()\n)\nconnection.connect()\n\nval response: AuthorizeResp = connection.authorize(RequestMetadata(chargPointId), AuthorizeReq(IdTokenType(\n        idToken = \"2233223\",\n        type = IdTokenEnumType.Central,\n))).response\n\nif (response.idTokenInfo.status == AuthorizationStatusEnumType.Accepted) {\n    connection.statusNotification(\n            meta = RequestMetadata(chargPointId),\n            request = StatusNotificationReq(\n                    connectorId = 1,\n                    connectorStatus = ConnectorStatusEnumType.Occupied,\n                    evseId = 1,\n                    timestamp = now()\n            )\n    )\n\n    val response: TransactionEventResp =\n            connection.transactionEvent(\n                    meta = RequestMetadata(chargPointId),\n                    request = TransactionEventReq(\n                            eventType = TransactionEventEnumType.Started,\n                            timestamp = now(),\n                            triggerReason = TriggerReasonEnumType.Authorized,\n                            seqNo = 1,\n                            transactionInfo = TransactionType(\n                                    \"1\",\n                                    ChargingStateEnumType.Charging\n                            )\n                    )\n            ).response\n\n    connection.statusNotification(\n        meta = RequestMetadata(chargPointId),\n        request = StatusNotificationReq(\n                connectorId = 1,\n                connectorStatus = ConnectorStatusEnumType.Occupied,\n                evseId = 1,\n                timestamp = now()\n        )\n    )\n}\nconnection.close()\n```\n\nOCPP 2.0 Remote Charge :\n```kotlin \nvar remoteStartTransactionReq: RequestStartTransactionReq? = null\nval ocppCSCallbacks = object : OcppCSCallbacks() {\n    override fun requestStartTransaction(req: RequestStartTransactionReq): RequestStartTransactionResp {\n        remoteStartTransactionReq = req\n        return RequestStartTransactionResp(RequestStartStopStatusEnumType.Accepted)\n    }\n}\n\nval connection = Ocpp20ConnectionToCSMS(\n        chargePointId = chargPointId,\n        csmsUrl = csmsUrl,\n        transportType = transport,\n        ocppCSCallbacks = ocppCSCallbacks\n)\nconnection.connect()\n\nval waitUntil = now() + 1.toDuration(DurationUnit.MINUTES)\n\nwhile (remoteStartTransactionReq == null \u0026\u0026 now() \u003c waitUntil) {\n    sleep(100)\n}\n\nif (remoteStartTransactionReq != null) {\n    println(\"${remoteStartTransactionReq?.idToken?.idToken}\")\n    connection.statusNotification(\n            meta = RequestMetadata(chargPointId),\n            request = StatusNotificationReq(\n                    connectorId = 1,\n                    connectorStatus = ConnectorStatusEnumType.Occupied,\n                    evseId = 1,\n                    timestamp = now()\n            )\n    )\n\n    val response: TransactionEventResp =\n            connection.transactionEvent(\n                    meta = RequestMetadata(chargPointId),\n                    request = TransactionEventReq(\n                            eventType = TransactionEventEnumType.Started,\n                            timestamp = now(),\n                            triggerReason = TriggerReasonEnumType.Authorized,\n                            seqNo = 1,\n                            transactionInfo = TransactionType(\n                                    \"1\",\n                                    ChargingStateEnumType.Charging\n                            )\n                    )\n            ).response\n\n    connection.statusNotification(\n            meta = RequestMetadata(chargPointId),\n            request = StatusNotificationReq(\n                    connectorId = 1,\n                    connectorStatus = ConnectorStatusEnumType.Occupied,\n                    evseId = 1,\n                    timestamp = now()\n            )\n    )\n}\nconnection.close()\n```\n\n## Code Organisation\n\nThe main entry point is in the module `toolkit`, which provides access to all the apis and all ocpp versions.\n\nFor each version of ocpp supported, you will find:\n- a `-core` module which provided all the data structures and operations declaration.\n- a `-api-adapter` module which is used as an adapter between that version of ocpp and the generic api\n\nPlus, you will find:\n- `generic-api`, which is an ocpp independent api which can be used to switch between ocpp versions without changing your code\n- `ocpp-transport`, which defines an interface for different transport of operations, with the modules `-websocket` and `-soap` for implementations\n- `operation-information`, used to described operations in whatever version of apis\n- `utils`, used to ease some common needs between apis\n- `ocpp-wamp`, a client \u0026 server implementation of the WAMP-like RPC-over-websocket system defined in the OCPP-J protcols\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fizivia%2Focpp-toolkit","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fizivia%2Focpp-toolkit","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fizivia%2Focpp-toolkit/lists"}