@@ -18,9 +18,9 @@ There are currently no plans of supporting OCPP-S.
18
18
19
19
Planned milestones and features:
20
20
21
- - [x] OCPP 1.6
22
- - [x] OCPP 2.0.1 (examples working, but will need more real-world testing)
23
- - [ ] Dedicated package for configuration management
21
+ - [x] OCPP 1.6
22
+ - [x] OCPP 2.0.1 (examples working, but will need more real-world testing)
23
+ - [ ] Dedicated package for configuration management
24
24
25
25
## OCPP 1.6 Usage
26
26
@@ -31,6 +31,7 @@ go get github.com/lorenzodonini/ocpp-go
31
31
```
32
32
33
33
You will also need to fetch some dependencies:
34
+
34
35
``` sh
35
36
cd < path-to-ocpp-go>
36
37
export GO111MODULE=on
@@ -42,6 +43,7 @@ Your application may either act as a [Central System](#central-system) (server)
42
43
### Central System
43
44
44
45
If you want to integrate the library into your custom Central System, you must implement the callbacks defined in the profile interfaces, e.g.:
46
+
45
47
``` go
46
48
import (
47
49
" github.com/lorenzodonini/ocpp-go/ocpp1.6/core"
@@ -65,7 +67,7 @@ func (handler *CentralSystemHandler) OnBootNotification(chargePointId string, re
65
67
return core.NewBootNotificationConfirmation (types.NewDateTime (time.Now ()), defaultHeartbeatInterval, core.RegistrationStatusAccepted ), nil
66
68
}
67
69
68
- // further callbacks...
70
+ // further callbacks...
69
71
```
70
72
71
73
Every time a request from the charge point comes in, the respective callback function is called.
@@ -77,6 +79,7 @@ You need to implement at least all other callbacks defined in the `core.CentralS
77
79
Depending on which OCPP profiles you want to support in your application, you will need to implement additional callbacks as well.
78
80
79
81
To start a central system instance, simply run the following:
82
+
80
83
``` go
81
84
centralSystem := ocpp16.NewCentralSystem (nil , nil )
82
85
@@ -102,6 +105,7 @@ log.Println("stopped central system")
102
105
#### Sending requests
103
106
104
107
To send requests to the charge point, you may either use the simplified API:
108
+
105
109
``` go
106
110
err := centralSystem.ChangeAvailability (" 1234" , myCallback, 1 , core.AvailabilityTypeInoperative )
107
111
if err != nil {
@@ -110,6 +114,7 @@ if err != nil {
110
114
```
111
115
112
116
or create a message manually:
117
+
113
118
``` go
114
119
request := core.NewChangeAvailabilityRequest (1 , core.AvailabilityTypeInoperative )
115
120
err := centralSystem.SendRequestAsync (" clientId" , request, callbackFunction)
@@ -118,8 +123,9 @@ if err != nil {
118
123
}
119
124
```
120
125
121
- In both cases, the request is sent asynchronously and the function returns right away.
126
+ In both cases, the request is sent asynchronously and the function returns right away.
122
127
You need to write the callback function to check for errors and handle the confirmation on your own:
128
+
123
129
``` go
124
130
myCallback := func (confirmation *core.ChangeAvailabilityConfirmation , e error ) {
125
131
if e != nil {
@@ -137,19 +143,22 @@ Since the initial `centralSystem.Start` call blocks forever, you may want to wra
137
143
138
144
You can take a look at the [ full example] ( ./example/1.6/cs/central_system_sim.go ) .
139
145
To run it, simply execute:
146
+
140
147
``` bash
141
148
go run ./example/1.6/cs/* .go
142
149
```
143
150
144
151
#### Docker
145
152
146
153
A containerized version of the central system example is available:
154
+
147
155
``` bash
148
156
docker pull ldonini/ocpp1.6-central-system:latest
149
157
docker run -it -p 8887:8887 --rm --name central-system ldonini/ocpp1.6-central-system:latest
150
158
```
151
159
152
160
You can also run it directly using docker-compose:
161
+
153
162
``` sh
154
163
docker-compose -f example/1.6/docker-compose.yml up central-system
155
164
```
@@ -158,16 +167,18 @@ docker-compose -f example/1.6/docker-compose.yml up central-system
158
167
159
168
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.
160
169
161
- Feel free to use the utility script ` cd example/1.6 && ./create-test-certificates.sh ` for generating test certificates.
170
+ Feel free to use the utility script ` cd example/1.6 && ./create-test-certificates.sh ` for generating test certificates.
162
171
163
172
Then run the following:
173
+
164
174
```
165
175
docker-compose -f example/1.6/docker-compose.tls.yml up central-system
166
176
```
167
177
168
178
### Charge Point
169
179
170
180
If you want to integrate the library into your custom Charge Point, you must implement the callbacks defined in the profile interfaces, e.g.:
181
+
171
182
``` go
172
183
import (
173
184
" github.com/lorenzodonini/ocpp-go/ocpp1.6/core"
@@ -199,6 +210,7 @@ You need to implement at least all other callbacks defined in the `core.ChargePo
199
210
Depending on which OCPP profiles you want to support in your application, you will need to implement additional callbacks as well.
200
211
201
212
To start a charge point instance, simply run the following:
213
+
202
214
``` go
203
215
chargePointId := " cp0001"
204
216
csUrl = " ws://localhost:8887"
@@ -213,7 +225,7 @@ err := chargePoint.Start(csUrl)
213
225
if err != nil {
214
226
log.Println (err)
215
227
} else {
216
- log.Printf (" connected to central system at %v " , csUrl)
228
+ log.Printf (" connected to central system at %v " , csUrl)
217
229
mainRoutine () // ... your program logic goes here
218
230
}
219
231
@@ -225,6 +237,7 @@ log.Printf("disconnected from central system")
225
237
#### Sending requests
226
238
227
239
To send requests to the central station, you have two options. You may either use the simplified synchronous blocking API (recommended):
240
+
228
241
``` go
229
242
bootConf , err := chargePoint.BootNotification (" model1" , " vendor1" )
230
243
if err != nil {
@@ -236,11 +249,13 @@ if err != nil {
236
249
```
237
250
238
251
or create a message manually:
252
+
239
253
``` go
240
254
request := core.NewBootNotificationRequest (" model1" , " vendor1" )
241
255
```
242
256
243
257
You can then decide to send the message using a synchronous blocking call:
258
+
244
259
``` go
245
260
// Synchronous call
246
261
confirmation , err := chargePoint.SendRequest (request)
@@ -250,7 +265,9 @@ if err != nil {
250
265
bootConf := confirmation.(*core.BootNotificationConfirmation )
251
266
// ... do something with the confirmation
252
267
```
268
+
253
269
or an asynchronous call:
270
+
254
271
``` go
255
272
// Asynchronous call
256
273
err := chargePoint.SendRequestAsync (request, callbackFunction)
@@ -260,6 +277,7 @@ if err != nil {
260
277
```
261
278
262
279
In the latter case, you need to write the callback function and check for errors on your own:
280
+
263
281
``` go
264
282
callback := func (confirmation ocpp.Response , e error ) {
265
283
bootConf := confirmation.(*core.BootNotificationConfirmation )
@@ -275,8 +293,10 @@ callback := func(confirmation ocpp.Response, e error) {
275
293
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.
276
294
277
295
#### Example
296
+
278
297
You can take a look at the [ full example] ( ./example/1.6/cp/charge_point_sim.go ) .
279
298
To run it, simply execute:
299
+
280
300
``` bash
281
301
CLIENT_ID=chargePointSim CENTRAL_SYSTEM_URL=ws://< host> :8887 go run example/1.6/cp/* .go
282
302
```
@@ -286,6 +306,7 @@ You need to specify the URL of a running central station server via environment
286
306
#### Docker
287
307
288
308
A containerized version of the charge point example is available:
309
+
289
310
``` bash
290
311
docker pull ldonini/ocpp1.6-charge-point:latest
291
312
docker run -e CLIENT_ID=chargePointSim -e CENTRAL_SYSTEM_URL=ws://< host> :8887 -it --rm --name charge-point ldonini/ocpp1.6-charge-point:latest
@@ -294,6 +315,7 @@ docker run -e CLIENT_ID=chargePointSim -e CENTRAL_SYSTEM_URL=ws://<host>:8887 -i
294
315
You need to specify the host, on which the central system is running, in order for the charge point to connect to it.
295
316
296
317
You can also run it directly using docker-compose:
318
+
297
319
``` sh
298
320
docker-compose -f example/1.6/docker-compose.yml up charge-point
299
321
```
@@ -302,9 +324,10 @@ docker-compose -f example/1.6/docker-compose.yml up charge-point
302
324
303
325
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.
304
326
305
- Feel free to use the utility script ` cd example/1.6 && ./create-test-certificates.sh ` for generating test certificates.
327
+ Feel free to use the utility script ` cd example/1.6 && ./create-test-certificates.sh ` for generating test certificates.
306
328
307
329
Then run the following:
330
+
308
331
```
309
332
docker-compose -f example/1.6/docker-compose.tls.yml up charge-point
310
333
```
@@ -319,18 +342,20 @@ All incoming and outgoing messages are validated by default, using the [validato
319
342
Constraints are defined on every request/response struct, as per OCPP specs.
320
343
321
344
Validation may be disabled at a package level if needed:
345
+
322
346
``` go
323
347
ocppj.SetMessageValidation (false )
324
- ```
348
+ ```
325
349
326
350
Use at your own risk, as this will disable validation for all messages!
327
351
328
- > I will be evaluating the possibility to selectively disable validation for a specific message,
352
+ > I will be evaluating the possibility to selectively disable validation for a specific message,
329
353
> e.g. by passing message options.
330
354
331
355
### Verbose logging
332
356
333
357
The ` ws ` and ` ocppj ` packages offer the possibility to enable verbose logs, via your logger of choice, e.g.:
358
+
334
359
``` go
335
360
// Setup your own logger
336
361
log = logrus.New ()
@@ -340,17 +365,19 @@ log.SetLevel(logrus.DebugLevel) // Debug level needed to see all logs
340
365
ws.SetLogger (log.WithField (" logger" , " websocket" ))
341
366
ocppj.SetLogger (log.WithField (" logger" , " ocppj" ))
342
367
```
368
+
343
369
The logger you pass needs to conform to the ` logging.Logger ` interface.
344
370
Commonly used logging libraries, such as zap or logrus, adhere to this interface out-of-the-box.
345
371
346
372
If you are using a logger, that isn't conform, you can simply write an adapter between the ` Logger ` interface and your own logging system.
347
373
348
374
### Websocket ping-pong
349
375
350
- The websocket package currently supports client-initiated pings only.
376
+ The websocket package currently supports client-initiated pings only.
351
377
352
378
If your setup requires the server to be the initiator of a ping-pong (e.g. for web-based charge points),
353
379
you may disable ping-pong entirely and just rely on the heartbeat mechanism:
380
+
354
381
``` go
355
382
cfg := ws.NewServerTimeoutConfig ()
356
383
cfg.PingWait = 0 // this instructs the server to wait forever
@@ -366,7 +393,7 @@ Experimental support for version 2.0.1 is now supported!
366
393
> Version 2.0 was skipped entirely, since it is considered obsolete.
367
394
368
395
Requests and responses in OCPP 2.0.1 are handled the same way they were in v1.6.
369
- The notable change is that there are now significantly more supported messages and profiles (feature sets),
396
+ The notable change is that there are now significantly more supported messages and profiles (feature sets),
370
397
which also require their own handlers to be implemented.
371
398
372
399
The library API to the lower websocket and ocpp-j layers remains unchanged.
@@ -383,6 +410,7 @@ More in-depth documentation for v2.0.1 will follow.
383
410
### CSMS
384
411
385
412
To start a CSMS instance, run the following:
413
+
386
414
``` go
387
415
import " github.com/lorenzodonini/ocpp-go/ocpp2.0.1"
388
416
@@ -420,6 +448,7 @@ log.Println("stopped CSMS")
420
448
#### Sending requests
421
449
422
450
Similarly to v1.6, you may send requests using the simplified API, e.g.
451
+
423
452
``` go
424
453
err := csms.GetLocalListVersion (chargingStationID, myCallback)
425
454
if err != nil {
@@ -432,11 +461,12 @@ Or you may build requests manually and send them using the asynchronous API.
432
461
#### Docker image
433
462
434
463
There is a Dockerfile and a docker image available upstream.
435
- Feel free
464
+ Feel free
436
465
437
466
### Charging Station
438
467
439
468
To start a charging station instance, simply run the following:
469
+
440
470
``` go
441
471
chargingStationID := " cs0001"
442
472
csmsUrl = " ws://localhost:8887"
@@ -464,7 +494,7 @@ err := chargingStation.Start(csmsUrl)
464
494
if err != nil {
465
495
log.Println (err)
466
496
} else {
467
- log.Printf (" connected to CSMS at %v " , csmsUrl)
497
+ log.Printf (" connected to CSMS at %v " , csmsUrl)
468
498
mainRoutine () // ... your program logic goes here
469
499
}
470
500
@@ -476,6 +506,7 @@ log.Println("disconnected from CSMS")
476
506
#### Sending requests
477
507
478
508
Similarly to v1.6 you may send requests using the simplified API (recommended), e.g.
509
+
479
510
``` go
480
511
bootResp , err := chargingStation.BootNotification (provisioning.BootReasonPowerUp , " model1" , " vendor1" )
481
512
if err != nil {
@@ -485,4 +516,14 @@ if err != nil {
485
516
}
486
517
```
487
518
488
- Or you may build requests manually and send them using either the synchronous or asynchronous API.
519
+ Or you may build requests manually and send them using either the synchronous or asynchronous API.
520
+
521
+ #### Contributing
522
+
523
+ If you're contributing a code change, you'll want to be sure the tests are passing first; here are the steps to check that:
524
+
525
+ - Install [ toxiproxy] ( https://github.com/Shopify/toxiproxy ) for your platform
526
+ - Shell 1 - ` cd example/1.6 && ./create-test-certificates.sh ; cd ../.. `
527
+ - Shell 1 - ` cd example/2.0.1 && ./create-test-certificates.sh ; cd ../.. `
528
+ - Shell 1 - ` toxiproxy-server -port 8474 -host localhost `
529
+ - Shell 2 - ` go fmt ./... && go vet ./... && go test -v -count=1 -failfast ./... `
0 commit comments