Skip to content

Commit d0bd7df

Browse files
Update OCPP 1.6 examples (#16)
* Rename profile handlers Signed-off-by: Lorenzo Donini <[email protected]> * Update SetCoreHandler function name for charge point Signed-off-by: Lorenzo Donini <[email protected]> * Update ocpp 1.6 examples Signed-off-by: Lorenzo Donini <[email protected]> * Use alpine image for docker execution Signed-off-by: Lorenzo Donini <[email protected]> * Setup code coverage test in ci Signed-off-by: Lorenzo Donini <[email protected]> * Move ocppj tests to ocppj folder Signed-off-by: Lorenzo Donini <[email protected]> * Update test coverage creation Signed-off-by: Lorenzo Donini <[email protected]> * Cover profile packages in tests Signed-off-by: Lorenzo Donini <[email protected]> * Run gofmt Signed-off-by: Lorenzo Donini <[email protected]> * Refactor examples and include TLS support Signed-off-by: Lorenzo Donini <[email protected]> * Move examples to 1.6 folder Signed-off-by: Lorenzo Donini <[email protected]> * Add script for generating test certificates Signed-off-by: Lorenzo Donini <[email protected]> * Update readme usage Signed-off-by: Lorenzo Donini <[email protected]> * Fix dockerfile path in travis.yml Signed-off-by: Lorenzo Donini <[email protected]> * Update 1.6 example with central system sim Signed-off-by: Lorenzo Donini <[email protected]> * Use cp configMap and simulate more messages Signed-off-by: Lorenzo Donini <[email protected]>
1 parent 3f543b5 commit d0bd7df

37 files changed

+876
-298
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,6 @@
1313

1414
# Idea
1515
.idea/*
16+
17+
# Project-specific
18+
certs/

.travis.yml

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,19 +17,26 @@ jobs:
1717
- stage: test
1818
script:
1919
- go build ./...
20-
- go test ./...
20+
- go get golang.org/x/tools/cmd/cover
21+
- go get github.com/mattn/goveralls
22+
- go test ./ws ./ocppj -v -covermode=count -coverprofile=coverage.out
23+
- go test -v -covermode=count -coverprofile=ocpp16.out -coverpkg=github.com/lorenzodonini/ocpp-go/ocpp1.6/... github.com/lorenzodonini/ocpp-go/ocpp1.6_test
24+
- go test -v -covermode=count -coverprofile=ocpp20.out -coverpkg=github.com/lorenzodonini/ocpp-go/ocpp2.0/... github.com/lorenzodonini/ocpp-go/ocpp2.0_test
25+
- sed '1d;$d' ocpp16.out >> coverage.out
26+
- sed '1d;$d' ocpp20.out >> coverage.out
27+
- goveralls -coverprofile=coverage.out -service=travis-ci -repotoken $COVERALLS_TOKEN
2128
- stage: publish_latest
2229
script:
23-
- docker build -t ldonini/ocpp1.6-central-system:latest -f example/cs1.6/Dockerfile .
24-
- docker build -t ldonini/ocpp1.6-charge-point:latest -f example/cp1.6/Dockerfile .
30+
- docker build -t ldonini/ocpp1.6-central-system:latest -f example/1.6/cs/Dockerfile .
31+
- docker build -t ldonini/ocpp1.6-charge-point:latest -f example/1.6/cp/Dockerfile .
2532
- echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin
2633
- docker push ldonini/ocpp1.6-central-system:latest
2734
- docker push ldonini/ocpp1.6-charge-point:latest
2835
if: branch == master
2936
- stage: release
3037
script:
31-
- docker build -t "ldonini/ocpp1.6-central-system:$TRAVIS_TAG" -f example/cs1.6/Dockerfile .
32-
- docker build -t "ldonini/ocpp1.6-charge-point:$TRAVIS_TAG" -f example/cp1.6/Dockerfile .
38+
- docker build -t "ldonini/ocpp1.6-central-system:$TRAVIS_TAG" -f example/1.6/cs/Dockerfile .
39+
- docker build -t "ldonini/ocpp1.6-charge-point:$TRAVIS_TAG" -f example/1.6/cp/Dockerfile .
3340
- echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin
3441
- docker push "ldonini/ocpp1.6-central-system:$TRAVIS_TAG"
3542
- docker push "ldonini/ocpp1.6-charge-point:$TRAVIS_TAG"

README.md

Lines changed: 77 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
# ocpp-go
22

33
[![Build Status](https://travis-ci.org/lorenzodonini/ocpp-go.svg?branch=master)](https://travis-ci.org/lorenzodonini/ocpp-go)
4+
[![GoDoc](https://img.shields.io/badge/godoc-reference-5272B4)](https://godoc.org/github.com/lorenzodonini/ocpp-go)
5+
[![Coverage Status](https://coveralls.io/repos/github/lorenzodonini/ocpp-go/badge.svg?branch=ocpp1.6/examples)](https://coveralls.io/github/lorenzodonini/ocpp-go?branch=ocpp1.6/examples)
6+
[![Go report](https://goreportcard.com/badge/github.com/lorenzodonini/ocpp-go)](https://goreportcard.com/report/github.com/lorenzodonini/ocpp-go)
47

58
Open Charge Point Protocol implementation in Go.
69

@@ -9,14 +12,14 @@ The library targets modern charge points and central systems, running OCPP versi
912
Given that SOAP will no longer be supported in future versions of OCPP, only OCPP-J is supported in this library.
1013
There are currently no plans of supporting OCPP-S.
1114

12-
## Roadmap
15+
## Status & Roadmap
16+
17+
**Note: Releases 0.10.0 introduced breaking changes in some API, due to refactoring. The functionality remains the same, but naming changed.**
1318

1419
Planned milestones and features:
1520

1621
- [x] OCPP 1.6
17-
- [ ] OCPP 2.0
18-
19-
**Note: The library is still a WIP, therefore expect some APIs to change.**
22+
- [ ] OCPP 2.0
2023

2124
## OCPP 1.6 Usage
2225

@@ -33,24 +36,32 @@ export GO111MODULE=on
3336
go mod download
3437
```
3538

36-
Your application may either act as a Central System (server) or as a Charge Point (client).
39+
Your application may either act as a [Central System](#central-system) (server) or as a [Charge Point](#charge-point) (client).
3740

3841
### Central System
3942

4043
If you want to integrate the library into your custom Central System, you must implement the callbacks defined in the profile interfaces, e.g.:
4144
```go
45+
import (
46+
"github.com/lorenzodonini/ocpp-go/ocpp1.6/core"
47+
"github.com/lorenzodonini/ocpp-go/ocpp1.6/types"
48+
"time"
49+
)
50+
51+
const defaultHeartbeatInterval = 600
52+
4253
type CentralSystemHandler struct {
4354
// ... your own state variables
4455
}
4556

46-
func (handler * CentralSystemHandler) OnAuthorize(chargePointId string, request *ocpp16.AuthorizeRequest) (confirmation *ocpp16.AuthorizeConfirmation, err error) {
57+
func (handler *CentralSystemHandler) OnAuthorize(chargePointId string, request *core.AuthorizeRequest) (confirmation *core.AuthorizeConfirmation, err error) {
4758
// ... your own custom logic
48-
return ocpp16.NewAuthorizationConfirmation(ocpp16.NewIdTagInfo(ocpp16.AuthorizationStatusAccepted)), nil
59+
return core.NewAuthorizationConfirmation(types.NewIdTagInfo(types.AuthorizationStatusAccepted)), nil
4960
}
5061

51-
func (handler * CentralSystemHandler) OnBootNotification(chargePointId string, request *ocpp16.BootNotificationRequest) (confirmation *ocpp16.BootNotificationConfirmation, err error) {
62+
func (handler *CentralSystemHandler) OnBootNotification(chargePointId string, request *core.BootNotificationRequest) (confirmation *core.BootNotificationConfirmation, err error) {
5263
// ... your own custom logic
53-
return ocpp16.NewBootNotificationConfirmation(ocpp16.NewDateTime(time.Now()), defaultHeartbeatInterval, ocpp16.RegistrationStatusAccepted), nil
64+
return core.NewBootNotificationConfirmation(types.NewDateTime(time.Now()), defaultHeartbeatInterval, core.RegistrationStatusAccepted), nil
5465
}
5566

5667
// further callbacks...
@@ -60,7 +71,7 @@ Every time a request from the charge point comes in, the respective callback fun
6071
For every callback you must return either a confirmation or an error. The result will be sent back automatically to the charge point.
6172
The callback is invoked inside a dedicated goroutine, so you don't have to worry about synchronization.
6273

63-
You need to implement at least all other callbacks defined in the `ocpp16.CentralSystemCoreListener` interface.
74+
You need to implement at least all other callbacks defined in the `core.CentralSystemHandler` interface.
6475

6576
Depending on which OCPP profiles you want to support in your application, you will need to implement additional callbacks as well.
6677

@@ -78,7 +89,7 @@ centralSystem.SetChargePointDisconnectedHandler(func(chargePointId string) {
7889

7990
// Set handler for profile callbacks
8091
handler := &CentralSystemHandler{}
81-
centralSystem.SetCentralSystemCoreListener(handler)
92+
centralSystem.SetCoreHandler(handler)
8293

8394
// Start central system
8495
listenPort := 8887
@@ -91,15 +102,15 @@ log.Println("stopped central system")
91102

92103
To send requests to the charge point, you may either use the simplified API:
93104
```go
94-
err := centralSystem.ChangeAvailability("1234", myCallback, 1, ocpp16.AvailabilityTypeInoperative)
105+
err := centralSystem.ChangeAvailability("1234", myCallback, 1, core.AvailabilityTypeInoperative)
95106
if err != nil {
96107
log.Printf("error sending message: %v", err)
97108
}
98109
```
99110

100111
or create a message manually:
101112
```go
102-
request := ocpp16.NewChangeAvailabilityRequest(1, ocpp16.AvailabilityTypeInoperative)
113+
request := core.NewChangeAvailabilityRequest(1, core.AvailabilityTypeInoperative)
103114
err := centralSystem.SendRequestAsync("clientId", request, callbackFunction)
104115
if err != nil {
105116
log.Printf("error sending message: %v", err)
@@ -109,7 +120,7 @@ if err != nil {
109120
In both cases, the request is sent asynchronously and the function returns right away.
110121
You need to write the callback function to check for errors and handle the confirmation on your own:
111122
```go
112-
myCallback := func(confirmation *ocpp16.ChangeAvailabilityConfirmation, e error) {
123+
myCallback := func(confirmation *core.ChangeAvailabilityConfirmation, e error) {
113124
if e != nil {
114125
log.Printf("operation failed: %v", e)
115126
} else {
@@ -119,14 +130,14 @@ myCallback := func(confirmation *ocpp16.ChangeAvailabilityConfirmation, e error)
119130
}
120131
```
121132

122-
Since the initial `centralSystem.Start` call blocks forever, you may want to wrap it in a goroutine (that is, if you need to send requests to charge points form the main thread).
133+
Since the initial `centralSystem.Start` call blocks forever, you may want to wrap it in a goroutine (that is, if you need to run other operations on the main thread).
123134

124135
#### Example
125136

126-
You can take a look at the full example inside `central_system_sim.go`.
137+
You can take a look at the [full example](./example/1.6/cs/central_system_sim.go).
127138
To run it, simply execute:
128139
```bash
129-
go run ./example/cs/central_system_sim.go
140+
go run ./example/1.6/cs/*.go
130141
```
131142

132143
#### Docker
@@ -137,36 +148,52 @@ docker pull ldonini/ocpp1.6-central-system:latest
137148
docker run -it -p 8887:8887 --rm --name central-system ldonini/ocpp1.6-central-system:latest
138149
```
139150

140-
You can also build the docker image from source, using:
151+
You can also run it directly using docker-compose:
141152
```sh
142-
docker-compose up central_system
153+
docker-compose -f example/1.6/docker-compose.yml up central_system
154+
```
155+
156+
#### TLS
157+
158+
If you wish to test the central system using TLS, make sure you put your self-signed certificates inside the `example/1.6/certs` folder.
159+
160+
Feel free to use the utility script `cd example/1.6 && ./create-test-certificates.sh` for generating test certificates.
161+
162+
Then run the following:
163+
```
164+
docker-compose -f example/1.6/docker-compose.tls.yml up central-system
143165
```
144166

145167
### Charge Point
146168

147169
If you want to integrate the library into your custom Charge Point, you must implement the callbacks defined in the profile interfaces, e.g.:
148170
```go
171+
import (
172+
"github.com/lorenzodonini/ocpp-go/ocpp1.6/core"
173+
"github.com/lorenzodonini/ocpp-go/ocpp1.6/types"
174+
)
175+
149176
type ChargePointHandler struct {
150177
// ... your own state variables
151178
}
152179

153-
func (handler * ChargePointHandler) OnChangeAvailability(request *ocpp16.ChangeAvailabilityRequest) (confirmation *ocpp16.ChangeAvailabilityConfirmation, err error) {
180+
func (handler *ChargePointHandler) OnChangeAvailability(request *core.ChangeAvailabilityRequest) (confirmation *core.ChangeAvailabilityConfirmation, err error) {
154181
// ... your own custom logic
155-
return ocpp16.NewChangeAvailabilityConfirmation(ocpp16.AvailabilityStatusAccepted), nil
182+
return core.NewChangeAvailabilityConfirmation(core.AvailabilityStatusAccepted), nil
156183
}
157184

158-
func (handler * ChargePointHandler) OnChangeConfiguration(request *ocpp16.ChangeConfigurationRequest) (confirmation *ocpp16.ChangeConfigurationConfirmation, err error) {
185+
func (handler *ChargePointHandler) OnChangeConfiguration(request *core.ChangeConfigurationRequest) (confirmation *core.ChangeConfigurationConfirmation, err error) {
159186
// ... your own custom logic
160-
return ocpp16.NewChangeConfigurationConfirmation(ocpp16.ConfigurationStatusAccepted), nil
187+
return core.NewChangeConfigurationConfirmation(core.ConfigurationStatusAccepted), nil
161188
}
162189

163190
// further callbacks...
164191
```
165192

166-
When a request from the central system comes in, the respective callback function is called.
193+
When a request from the central system comes in, the respective callback function gets invoked.
167194
For every callback you must return either a confirmation or an error. The result will be sent back automatically to the central system.
168195

169-
You need to implement at least all other callbacks defined in the `ocpp16.ChargePointCoreListener` interface.
196+
You need to implement at least all other callbacks defined in the `core.ChargePointHandler` interface.
170197

171198
Depending on which OCPP profiles you want to support in your application, you will need to implement additional callbacks as well.
172199

@@ -178,7 +205,7 @@ chargePoint := ocpp16.NewChargePoint(chargePointId, nil, nil)
178205

179206
// Set a handler for all callback functions
180207
handler := &ChargePointHandler{}
181-
chargePoint.SetChargePointCoreListener(handler)
208+
chargePoint.SetCoreHandler(handler)
182209

183210
// Connects to central system
184211
err := chargePoint.Start(csUrl)
@@ -208,7 +235,7 @@ log.Printf("status: %v, interval: %v, current time: %v", bootConf.Status, bootCo
208235

209236
or create a message manually:
210237
```go
211-
request := ocpp16.NewBootNotificationRequest("model1", "vendor1")
238+
request := core.NewBootNotificationRequest("model1", "vendor1")
212239
```
213240

214241
You can then decide to send the message using a synchronous blocking call:
@@ -218,7 +245,7 @@ confirmation, err := chargePoint.SendRequest(request)
218245
if err != nil {
219246
log.Printf("error sending message: %v", err)
220247
}
221-
bootConf := confirmation.(*ocpp16.BootNotificationConfirmation)
248+
bootConf := confirmation.(*core.BootNotificationConfirmation)
222249
// ... do something with the confirmation
223250
```
224251
or an asynchronous call:
@@ -232,8 +259,8 @@ if err != nil {
232259

233260
In the latter case, you need to write the callback function and check for errors on your own:
234261
```go
235-
callback := func(confirmation ocpp.Confirmation, e error) {
236-
bootConf := confirmation.(*ocpp16.BootNotificationConfirmation)
262+
callback := func(confirmation ocpp.Response, e error) {
263+
bootConf := confirmation.(*core.BootNotificationConfirmation)
237264
if e != nil {
238265
log.Printf("operation failed: %v", e)
239266
} else {
@@ -246,13 +273,13 @@ callback := func(confirmation ocpp.Confirmation, e error) {
246273
When creating a message manually, you always need to perform type assertion yourself, as the `SendRequest` and `SendRequestAsync` APIs use generic `Request` and `Confirmation` interfaces.
247274

248275
#### Example
249-
You can take a look at the full example inside `charge_point_sim.go`.
276+
You can take a look at the [full example](./example/1.6/cp/charge_point_sim.go).
250277
To run it, simply execute:
251278
```bash
252-
CLIENT_ID=chargePointSim CENTRAL_SYSTEM_URL=ws://<host>:8887 go run ./example/cp/charge_point_sim.go
279+
CLIENT_ID=chargePointSim CENTRAL_SYSTEM_URL=ws://<host>:8887 go run example/1.6/cp/*.go
253280
```
254281

255-
You need to specify the hostname/IP of a running central station server, so the charge point can reach it.
282+
You need to specify the URL of a running central station server via environment variable, so the charge point can reach it.
256283

257284
#### Docker
258285

@@ -264,7 +291,22 @@ docker run -e CLIENT_ID=chargePointSim -e CENTRAL_SYSTEM_URL=ws://<host>:8887 -i
264291

265292
You need to specify the host, on which the central system is running, in order for the charge point to connect to it.
266293

267-
You can also build the docker image from source, using:
294+
You can also run it directly using docker-compose:
268295
```sh
269-
docker-compose up charge_point
296+
docker-compose -f example/1.6/docker-compose.yml up charge_point
270297
```
298+
299+
#### TLS
300+
301+
If you wish to test the charge point using TLS, make sure you put your self-signed certificates inside the `example/1.6/certs` folder.
302+
303+
Feel free to use the utility script `cd example/1.6 && ./create-test-certificates.sh` for generating test certificates.
304+
305+
Then run the following:
306+
```
307+
docker-compose -f example/1.6/docker-compose.tls.yml up charge_point
308+
```
309+
310+
## OCPP 2.0 Usage
311+
312+
Documentation will follow, once the protocol is fully implemented.
Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,18 @@ COPY . .
99
# Fetch dependencies.
1010
RUN go mod download
1111
# Build the binary.
12-
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags="-w -s" -o /go/bin/charge_point example/cp1.6/charge_point_sim.go
12+
RUN GOOS=linux GOARCH=amd64 go build -ldflags="-w -s" -o /go/bin/charge_point example/1.6/cp/*.go
1313

1414
############################
1515
# STEP 2 build a small image
1616
############################
17-
FROM scratch
17+
FROM alpine
1818

1919
COPY --from=builder /go/bin/charge_point /bin/charge_point
2020

21+
# Add CA certificates
22+
# It currently throws a warning on alpine: WARNING: ca-certificates.crt does not contain exactly one certificate or CRL: skipping.
23+
# Ignore the warning.
24+
RUN apk update && apk add ca-certificates && rm -rf /var/cache/apk/* && update-ca-certificates
25+
2126
CMD [ "charge_point" ]

0 commit comments

Comments
 (0)