{"id":13634650,"url":"https://github.com/lorenzodonini/ocpp-go","last_synced_at":"2025-04-18T23:32:40.342Z","repository":{"id":36373810,"uuid":"182324051","full_name":"lorenzodonini/ocpp-go","owner":"lorenzodonini","description":"Open Charge Point Protocol implementation in Go","archived":false,"fork":false,"pushed_at":"2024-09-16T20:34:17.000Z","size":9733,"stargazers_count":258,"open_issues_count":64,"forks_count":120,"subscribers_count":26,"default_branch":"master","last_synced_at":"2024-09-17T01:39:05.460Z","etag":null,"topics":["charging-stations","electric-vehicles","emobility","ocpp"],"latest_commit_sha":null,"homepage":null,"language":"Go","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/lorenzodonini.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,"publiccode":null,"codemeta":null}},"created_at":"2019-04-19T20:49:36.000Z","updated_at":"2024-09-16T20:34:21.000Z","dependencies_parsed_at":"2023-09-22T18:17:14.933Z","dependency_job_id":"e38b3e31-835d-4b45-900c-a7c8d65b83f6","html_url":"https://github.com/lorenzodonini/ocpp-go","commit_stats":{"total_commits":531,"total_committers":22,"mean_commits":"24.136363636363637","dds":0.4896421845574388,"last_synced_commit":"9b4800337eaee4dddd4996396942fec6191dd8b3"},"previous_names":["lorenzodonini/go-ocpp"],"tags_count":10,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lorenzodonini%2Focpp-go","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lorenzodonini%2Focpp-go/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lorenzodonini%2Focpp-go/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lorenzodonini%2Focpp-go/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lorenzodonini","download_url":"https://codeload.github.com/lorenzodonini/ocpp-go/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":223786390,"owners_count":17202581,"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-stations","electric-vehicles","emobility","ocpp"],"created_at":"2024-08-02T00:00:28.651Z","updated_at":"2025-04-18T23:32:40.333Z","avatar_url":"https://github.com/lorenzodonini.png","language":"Go","funding_links":[],"categories":["Tools and Resources"],"sub_categories":["OCPP"],"readme":"# ocpp-go\n\n[![Build Status](https://github.com/lorenzodonini/ocpp-go/actions/workflows/test.yaml/badge.svg)](https://github.com/lorenzodonini/ocpp-go/actions/workflows/test.yaml)\n[![GoDoc](https://img.shields.io/badge/godoc-reference-5272B4)](https://godoc.org/github.com/lorenzodonini/ocpp-go)\n[![Coverage Status](https://coveralls.io/repos/github/lorenzodonini/ocpp-go/badge.svg?branch=master)](https://coveralls.io/github/lorenzodonini/ocpp-go?branch=master)\n[![Go report](https://goreportcard.com/badge/github.com/lorenzodonini/ocpp-go)](https://goreportcard.com/report/github.com/lorenzodonini/ocpp-go)\n\nOpen Charge Point Protocol implementation in Go.\n\nThe library targets modern charge points and central systems, running OCPP version 1.6+.\n\nGiven that SOAP will no longer be supported in future versions of OCPP, only OCPP-J is supported in this library.\nThere are currently no plans of supporting OCPP-S.\n\n## Status \u0026 Roadmap\n\n**Note: Releases 0.10.0 introduced breaking changes in some API, due to refactoring. The functionality remains the same,\nbut naming changed.**\n\nPlanned milestones and features:\n\n-   [x] OCPP 1.6\n-   [x] OCPP 1.6 Security extension (experimental)\n-   [x] OCPP 2.0.1 (examples working, but will need more real-world testing)\n-   [ ] Dedicated package for configuration management\n\n## OCPP 1.6 Usage\n\nGo version 1.13+ is required.\n\n```sh\ngo get github.com/lorenzodonini/ocpp-go\n```\n\nYou will also need to fetch some dependencies:\n\n```sh\ncd \u003cpath-to-ocpp-go\u003e\nexport GO111MODULE=on\ngo mod download\n```\n\nYour application may either act as a [Central System](#central-system) (server) or as a [Charge Point](#charge-point) (\nclient).\n\n### Central System\n\nIf you want to integrate the library into your custom Central System, you must implement the callbacks defined in the\nprofile interfaces, e.g.:\n\n```go\nimport (\n\"github.com/lorenzodonini/ocpp-go/ocpp1.6/core\"\n\"github.com/lorenzodonini/ocpp-go/ocpp1.6/types\"\n\"time\"\n)\n\nconst defaultHeartbeatInterval = 600\n\ntype CentralSystemHandler struct {\n// ... your own state variables\n}\n\nfunc (handler *CentralSystemHandler) OnAuthorize(chargePointId string, request *core.AuthorizeRequest) (confirmation *core.AuthorizeConfirmation, err error) {\n// ... your own custom logic\nreturn core.NewAuthorizationConfirmation(types.NewIdTagInfo(types.AuthorizationStatusAccepted)), nil\n}\n\nfunc (handler *CentralSystemHandler) OnBootNotification(chargePointId string, request *core.BootNotificationRequest) (confirmation *core.BootNotificationConfirmation, err error) {\n// ... your own custom logic\nreturn core.NewBootNotificationConfirmation(types.NewDateTime(time.Now()), defaultHeartbeatInterval, core.RegistrationStatusAccepted), nil\n}\n\n// further callbacks...\n```\n\nEvery time a request from the charge point comes in, the respective callback function is called.\nFor every callback you must return either a confirmation or an error. The result will be sent back automatically to the\ncharge point.\nThe callback is invoked inside a dedicated goroutine, so you don't have to worry about synchronization.\n\nYou need to implement at least all other callbacks defined in the `core.CentralSystemHandler` interface.\n\nDepending on which OCPP profiles you want to support in your application, you will need to implement additional\ncallbacks as well.\n\nTo start a central system instance, simply run the following:\n\n```go\ncentralSystem := ocpp16.NewCentralSystem(nil, nil)\n\n// Set callback handlers for connect/disconnect\ncentralSystem.SetNewChargePointHandler(func (chargePointId string) {\nlog.Printf(\"new charge point %v connected\", chargePointId)\n})\ncentralSystem.SetChargePointDisconnectedHandler(func (chargePointId string) {\nlog.Printf(\"charge point %v disconnected\", chargePointId)\n})\n\n// Set handler for profile callbacks\nhandler := \u0026CentralSystemHandler{}\ncentralSystem.SetCoreHandler(handler)\n\n// Start central system\nlistenPort := 8887\nlog.Printf(\"starting central system\")\ncentralSystem.Start(listenPort, \"/{ws}\") // This call starts server in daemon mode and is blocking\nlog.Println(\"stopped central system\")\n```\n\n#### Sending requests\n\nTo send requests to the charge point, you may either use the simplified API:\n\n```go\nerr := centralSystem.ChangeAvailability(\"1234\", myCallback, 1, core.AvailabilityTypeInoperative)\nif err != nil {\nlog.Printf(\"error sending message: %v\", err)\n}\n```\n\nor create a message manually:\n\n```go\nrequest := core.NewChangeAvailabilityRequest(1, core.AvailabilityTypeInoperative)\nerr := centralSystem.SendRequestAsync(\"clientId\", request, callbackFunction)\nif err != nil {\nlog.Printf(\"error sending message: %v\", err)\n}\n```\n\nIn both cases, the request is sent asynchronously and the function returns right away.\nYou need to write the callback function to check for errors and handle the confirmation on your own:\n\n```go\nmyCallback := func (confirmation *core.ChangeAvailabilityConfirmation, e error) {\nif e != nil {\nlog.Printf(\"operation failed: %v\", e)\n} else {\nlog.Printf(\"status: %v\", confirmation.Status)\n// ... your own custom logic\n}\n}\n```\n\nSince the initial `centralSystem.Start` call blocks forever, you may want to wrap it in a goroutine (that is, if you\nneed to run other operations on the main thread).\n\n#### Example\n\nYou can take a look at the [full example](./example/1.6/cs/central_system_sim.go).\nTo run it, simply execute:\n\n```bash\ngo run ./example/1.6/cs/*.go\n```\n\n#### Docker\n\nA containerized version of the central system example is available:\n\n```bash\ndocker pull ldonini/ocpp1.6-central-system:latest\ndocker run -it -p 8887:8887 --rm --name central-system ldonini/ocpp1.6-central-system:latest\n```\n\nYou can also run it directly using docker-compose:\n\n```sh\ndocker-compose -f example/1.6/docker-compose.yml up central-system\n```\n\n#### TLS\n\nIf you wish to test the central system using TLS, make sure you put your self-signed certificates inside the\n`example/1.6/certs` folder.\n\nFeel free to use the utility script `cd example/1.6 \u0026\u0026 ./create-test-certificates.sh` for generating test certificates.\n\nThen run the following:\n\n```\ndocker-compose -f example/1.6/docker-compose.tls.yml up central-system\n```\n\n### Charge Point\n\nIf you want to integrate the library into your custom Charge Point, you must implement the callbacks defined in the\nprofile interfaces, e.g.:\n\n```go\nimport (\n\"github.com/lorenzodonini/ocpp-go/ocpp1.6/core\"\n\"github.com/lorenzodonini/ocpp-go/ocpp1.6/types\"\n)\n\ntype ChargePointHandler struct {\n// ... your own state variables\n}\n\nfunc (handler *ChargePointHandler) OnChangeAvailability(request *core.ChangeAvailabilityRequest) (confirmation *core.ChangeAvailabilityConfirmation, err error) {\n// ... your own custom logic\nreturn core.NewChangeAvailabilityConfirmation(core.AvailabilityStatusAccepted), nil\n}\n\nfunc (handler *ChargePointHandler) OnChangeConfiguration(request *core.ChangeConfigurationRequest) (confirmation *core.ChangeConfigurationConfirmation, err error) {\n// ... your own custom logic\nreturn core.NewChangeConfigurationConfirmation(core.ConfigurationStatusAccepted), nil\n}\n\n// further callbacks...\n```\n\nWhen a request from the central system comes in, the respective callback function gets invoked.\nFor every callback you must return either a confirmation or an error. The result will be sent back automatically to the\ncentral system.\n\nYou need to implement at least all other callbacks defined in the `core.ChargePointHandler` interface.\n\nDepending on which OCPP profiles you want to support in your application, you will need to implement additional\ncallbacks as well.\n\nTo start a charge point instance, simply run the following:\n\n```go\nchargePointId := \"cp0001\"\ncsUrl = \"ws://localhost:8887\"\nchargePoint := ocpp16.NewChargePoint(chargePointId, nil, nil)\n\n// Set a handler for all callback functions\nhandler := \u0026ChargePointHandler{}\nchargePoint.SetCoreHandler(handler)\n\n// Connects to central system\nerr := chargePoint.Start(csUrl)\nif err != nil {\nlog.Println(err)\n} else {\nlog.Printf(\"connected to central system at %v\", csUrl)\nmainRoutine() // ... your program logic goes here\n}\n\n// Disconnect\nchargePoint.Stop()\nlog.Printf(\"disconnected from central system\")\n```\n\n#### Sending requests\n\nTo send requests to the central station, you have two options. You may either use the simplified synchronous blocking\nAPI (recommended):\n\n```go\nbootConf, err := chargePoint.BootNotification(\"model1\", \"vendor1\")\nif err != nil {\nlog.Fatal(err)\n} else {\nlog.Printf(\"status: %v, interval: %v, current time: %v\", bootConf.Status, bootConf.Interval, bootConf.CurrentTime.String())\n}\n// ... do something with the confirmation\n```\n\nor create a message manually:\n\n```go\nrequest := core.NewBootNotificationRequest(\"model1\", \"vendor1\")\n```\n\nYou can then decide to send the message using a synchronous blocking call:\n\n```go\n// Synchronous call\nconfirmation, err := chargePoint.SendRequest(request)\nif err != nil {\nlog.Printf(\"error sending message: %v\", err)\n}\nbootConf := confirmation.(*core.BootNotificationConfirmation)\n// ... do something with the confirmation\n```\n\nor an asynchronous call:\n\n```go\n// Asynchronous call\nerr := chargePoint.SendRequestAsync(request, callbackFunction)\nif err != nil {\nlog.Printf(\"error sending message: %v\", err)\n}\n```\n\nIn the latter case, you need to write the callback function and check for errors on your own:\n\n```go\ncallback := func (confirmation ocpp.Response, e error) {\nbootConf := confirmation.(*core.BootNotificationConfirmation)\nif e != nil {\nlog.Printf(\"operation failed: %v\", e)\n} else {\nlog.Printf(\"status: %v\", bootConf.Status)\n// ... your own custom logic\n}\n}\n```\n\nWhen creating a message manually, you always need to perform type assertion yourself, as the `SendRequest` and\n`SendRequestAsync` APIs use generic `Request` and `Confirmation` interfaces.\n\n#### Example\n\nYou can take a look at the [full example](./example/1.6/cp/charge_point_sim.go).\nTo run it, simply execute:\n\n```bash\nCLIENT_ID=chargePointSim CENTRAL_SYSTEM_URL=ws://\u003chost\u003e:8887 go run example/1.6/cp/*.go\n```\n\nYou need to specify the URL of a running central station server via environment variable, so the charge point can reach\nit.\n\n#### Docker\n\nA containerized version of the charge point example is available:\n\n```bash\ndocker pull ldonini/ocpp1.6-charge-point:latest\ndocker run -e CLIENT_ID=chargePointSim -e CENTRAL_SYSTEM_URL=ws://\u003chost\u003e:8887 -it --rm --name charge-point ldonini/ocpp1.6-charge-point:latest\n```\n\nYou need to specify the host, on which the central system is running, in order for the charge point to connect to it.\n\nYou can also run it directly using docker-compose:\n\n```sh\ndocker-compose -f example/1.6/docker-compose.yml up charge-point\n```\n\n#### TLS\n\nIf you wish to test the charge point using TLS, make sure you put your self-signed certificates inside the\n`example/1.6/certs` folder.\n\nFeel free to use the utility script `cd example/1.6 \u0026\u0026 ./create-test-certificates.sh` for generating test certificates.\n\nThen run the following:\n\n```\ndocker-compose -f example/1.6/docker-compose.tls.yml up charge-point\n```\n\n## OCPP 1.6 Security extension\n\nThe library supports the OCPP 1.6 Security extension, which adds support for additional messages that aren't a part of\noriginal OCPP 1.6 specification. The security extension is optional, but recommended to implement.\n\nThere aren't any clear examples how to determine if a charge point supports security extensions via `SupportedProfiles`\nconfiguration key or which profiles are required to be implemented in order to support the security extension.\nAs of now, the security extension is split into multiple profiles/functional blocks:\n\n- `ExtendedTriggerMessage`\n- `Certificates` (certificate management)\n- `Security` (event notifications, certificate signing)\n- `SecureFirmware` (secure firmware update)\n- `Logging`\n\n### HTTP Basic Auth\n\nThe security extension specifies how to secure the communication between charge points and central systems\nusing HTTP Basic Auth and/or certificates. These are already provided in the websocket server/client\nimplementation.\n\nExample charge point:\n\n```go\nwsClient := ws.NewClient()\nwsClient.SetBasicAuth(\"foo\", \"bar\")\ncp := ocpp16.NewChargePoint(chargePointID, nil, wsClient)\n```\n\nExample central system:\n\n```go\nserver := ws.NewServer()\nserver.SetBasicAuthHandler(func (username string, password string) bool {\n// todo Handle basic auth\nreturn true\n})\ncs := ocpp16.NewCentralSystem(nil, server)\n```\n\n### Certificate-based authentication (mTLS)\n\nThe security extension specifies how to secure the communication between charge points and central systems\nusing mTLS (client certificates). The library provides the necessary functionality to configure TLS,\nbut mTLS itself is not in scope and should be handled by the user.\n\n### Additional configuration keys\n\nThe OCPP 1.6 security extension introduces additional configuration keys.\nThese are not a part of the standard library, but they impact how the charge point should behave.\n\nThe charge point websocket client should be restarted when the `AuthorizationKey` configuration changes.\n\n### Central System\n\nTo add support for security extension in the central system, you have the following handlers:\n\n```go\n// Support callbacks for all OCPP 1.6 profiles\nhandler := \u0026CentralSystemHandler{chargePoints: map[string]*ChargePointState{}}\ncentralSystem.SetCoreHandler(handler)\ncentralSystem.SetLocalAuthListHandler(handler)\ncentralSystem.SetFirmwareManagementHandler(handler)\ncentralSystem.SetReservationHandler(handler)\ncentralSystem.SetRemoteTriggerHandler(handler)\ncentralSystem.SetSmartChargingHandler(handler)\n\n// Add callbacks for OCPP 1.6 security profiles\ncentralSystem.SetSecurityHandler(handler)\ncentralSystem.SetSecureFirmwareHandler(handler)\ncentralSystem.SetLogHandler(handler)\n\n```\n\n### Charge Point\n\nTo add support for security extension in the charge point, you have the following handlers:\n\n```go\nhandler := \u0026ChargePointHandler{}\n// Support callbacks for all OCPP 1.6 profiles\nchargePoint.SetCoreHandler(handler)\nchargePoint.SetFirmwareManagementHandler(handler)\nchargePoint.SetLocalAuthListHandler(handler)\nchargePoint.SetReservationHandler(handler)\nchargePoint.SetRemoteTriggerHandler(handler)\nchargePoint.SetSmartChargingHandler(handler)\n// OCPP 1.6j Security extension\nchargePoint.SetCertificateHandler(handler)\nchargePoint.SetLogHandler(handler)\nchargePoint.SetSecureFirmwareHandler(handler)\nchargePoint.SetExtendedTriggerMessageHandler(handler)\nchargePoint.SetSecurityHandler(handler)\n\n```\n\n## Advanced Features\n\nThe library offers several advanced features, especially at websocket and ocpp-j level.\n\n### Automatic message validation\n\nAll incoming and outgoing messages are validated by default, using the [validator](gopkg.in/go-playground/validator)\npackage.\nConstraints are defined on every request/response struct, as per OCPP specs.\n\nValidation may be disabled at a package level if needed:\n\n```go\nocppj.SetMessageValidation(false)\n```\n\nUse at your own risk, as this will disable validation for all messages!\n\n\u003e I will be evaluating the possibility to selectively disable validation for a specific message,\n\u003e e.g. by passing message options.\n\n### Verbose logging\n\nThe `ws` and `ocppj` packages offer the possibility to enable verbose logs, via your logger of choice, e.g.:\n\n```go\n// Setup your own logger\nlog = logrus.New()\nlog.SetFormatter(\u0026logrus.TextFormatter{FullTimestamp: true})\nlog.SetLevel(logrus.DebugLevel) // Debug level needed to see all logs\n// Pass own logger to ws and ocppj packages\nws.SetLogger(log.WithField(\"logger\", \"websocket\"))\nocppj.SetLogger(log.WithField(\"logger\", \"ocppj\"))\n```\n\nThe logger you pass needs to conform to the `logging.Logger` interface.\nCommonly used logging libraries, such as zap or logrus, adhere to this interface out-of-the-box.\n\nIf you are using a logger, that isn't conform, you can simply write an adapter between the `Logger` interface and your\nown logging system.\n\n### Websocket ping-pong\n\nThe websocket package supports configuring ping pong for both endpoints.\n\nBy default, the client sends a ping every 54 seconds and waits for a pong for 60 seconds, before timing out.\nThe values can be configured as follows:\n```go\ncfg := ws.NewClientTimeoutConfig()\ncfg.PingPeriod = 10 * time.Second\ncfg.PongWait = 20 * time.Second\nwebsocketClient.SetTimeoutConfig(cfg)\n```\n\nBy default, the server does not send out any pings and waits for a ping from the client for 60 seconds, before timing out.\nTo configure the server to send out pings, the `PingPeriod` and `PongWait` must be set to a value greater than 0:\n```go\ncfg := ws.NewServerTimeoutConfig()\ncfg.PingPeriod = 10 * time.Second\ncfg.PongWait = 20 * time.Second\nwebsocketServer.SetTimeoutConfig(cfg)\n```\n\nTo disable sending ping messages, set the `PingPeriod` value to `0`.\n\n## OCPP 2.0.1 Usage\n\nExperimental support for version 2.0.1 is now supported!\n\n\u003e Version 2.0 was skipped entirely, since it is considered obsolete.\n\nRequests and responses in OCPP 2.0.1 are handled the same way they were in v1.6.\nThe notable change is that there are now significantly more supported messages and profiles (feature sets),\nwhich also require their own handlers to be implemented.\n\nThe library API to the lower websocket and ocpp-j layers remains unchanged.\n\nBelow are very minimal setup code snippets, to get you started.\nCSMS is now the equivalent of the Central System,\nwhile the Charging Station is the new equivalent of a Charge Point.\n\nRefer to the [examples folder](example/2.0.1) for a full working example.\nMore in-depth documentation for v2.0.1 will follow.\n\n**Bug reports for this version are welcome.**\n\n### CSMS\n\nTo start a CSMS instance, run the following:\n\n```go\nimport \"github.com/lorenzodonini/ocpp-go/ocpp2.0.1\"\n\ncsms := ocpp2.NewCSMS(nil, nil)\n\n// Set callback handlers for connect/disconnect\ncsms.SetNewChargingStationHandler(func (chargingStation ocpp2.ChargingStationConnection) {\nlog.Printf(\"new charging station %v connected\", chargingStation.ID())\n})\ncsms.SetChargingStationDisconnectedHandler(func (chargingStation ocpp2.ChargingStationConnection) {\nlog.Printf(\"charging station %v disconnected\", chargingStation.ID())\n})\n\n// Set handler for profile callbacks\nhandler := \u0026CSMSHandler{}\ncsms.SetAuthorizationHandler(handler)\ncsms.SetAvailabilityHandler(handler)\ncsms.SetDiagnosticsHandler(handler)\ncsms.SetFirmwareHandler(handler)\ncsms.SetLocalAuthListHandler(handler)\ncsms.SetMeterHandler(handler)\ncsms.SetProvisioningHandler(handler)\ncsms.SetRemoteControlHandler(handler)\ncsms.SetReservationHandler(handler)\ncsms.SetTariffCostHandler(handler)\ncsms.SetTransactionsHandler(handler)\n\n// Start central system\nlistenPort := 8887\nlog.Printf(\"starting CSMS\")\ncsms.Start(listenPort, \"/{ws}\") // This call starts server in daemon mode and is blocking\nlog.Println(\"stopped CSMS\")\n```\n\n#### Sending requests\n\nSimilarly to v1.6, you may send requests using the simplified API, e.g.\n\n```go\nerr := csms.GetLocalListVersion(chargingStationID, myCallback)\nif err != nil {\nlog.Printf(\"error sending message: %v\", err)\n}\n```\n\nOr you may build requests manually and send them using the asynchronous API.\n\n#### Docker image\n\nThere is a Dockerfile and a docker image available upstream.\nFeel free\n\n### Charging Station\n\nTo start a charging station instance, simply run the following:\n\n```go\nchargingStationID := \"cs0001\"\ncsmsUrl = \"ws://localhost:8887\"\nchargingStation := ocpp2.NewChargingStation(chargingStationID, nil, nil)\n\n// Set a handler for all callback functions\nhandler := \u0026ChargingStationHandler{}\nchargingStation.SetAvailabilityHandler(handler)\nchargingStation.SetAuthorizationHandler(handler)\nchargingStation.SetDataHandler(handler)\nchargingStation.SetDiagnosticsHandler(handler)\nchargingStation.SetDisplayHandler(handler)\nchargingStation.SetFirmwareHandler(handler)\nchargingStation.SetISO15118Handler(handler)\nchargingStation.SetLocalAuthListHandler(handler)\nchargingStation.SetProvisioningHandler(handler)\nchargingStation.SetRemoteControlHandler(handler)\nchargingStation.SetReservationHandler(handler)\nchargingStation.SetSmartChargingHandler(handler)\nchargingStation.SetTariffCostHandler(handler)\nchargingStation.SetTransactionsHandler(handler)\n\n// Connects to CSMS\nerr := chargingStation.Start(csmsUrl)\nif err != nil {\nlog.Println(err)\n} else {\nlog.Printf(\"connected to CSMS at %v\", csmsUrl)\nmainRoutine() // ... your program logic goes here\n}\n\n// Disconnect\nchargingStation.Stop()\nlog.Println(\"disconnected from CSMS\")\n```\n\n#### Sending requests\n\nSimilarly to v1.6 you may send requests using the simplified API (recommended), e.g.\n\n```go\nbootResp, err := chargingStation.BootNotification(provisioning.BootReasonPowerUp, \"model1\", \"vendor1\")\nif err != nil {\nlog.Printf(\"error sending message: %v\", err)\n} else {\nlog.Printf(\"status: %v, interval: %v, current time: %v\", bootResp.Status, bootResp.Interval, bootResp.CurrentTime.String())\n}\n```\n\nOr you may build requests manually and send them using either the synchronous or asynchronous API.\n\n#### Contributing\n\nIf you're contributing a code change, you'll want to be sure the tests are passing first; here are the steps to check\nthat:\n\n- Install [toxiproxy](https://github.com/Shopify/toxiproxy) for your platform\n- Shell 1 - `toxiproxy-server -port 8474 -host localhost`\n- Shell 2 - `go fmt ./... \u0026\u0026 go vet ./... \u0026\u0026 go test -v -count=1 -failfast ./...`\n\n#### Generating mocks\n\nFor generating mocks, the `mockery` tool is used. For `mockery` installation, follow the instructions on\nthe [official docs](https://vektra.github.io/mockery/latest/).\n\nWhen adding new interfaces and needing to generate mocks, you should:\n\n1. Add the package/interface to the `.mockery.yaml` file. Be mindful of the naming conventions. The mocks should mostly\n   be generated in the same package as the interface, be snake case and suffixed with `_mock.go`. Following the existing\n   examples should give you a good idea of how to proceed.\n\n2. Run the following command:\n   ```sh\n   mockery \n   ```\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Florenzodonini%2Focpp-go","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Florenzodonini%2Focpp-go","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Florenzodonini%2Focpp-go/lists"}