2
2
package ocppj
3
3
4
4
import (
5
- "bytes"
6
5
"encoding/json"
7
6
"fmt"
8
- "math/rand"
9
- "reflect"
10
-
11
7
"github.com/lorenzodonini/ocpp-go/logging"
8
+ "math/rand"
12
9
13
10
"gopkg.in/go-playground/validator.v9"
14
11
@@ -65,9 +62,11 @@ func SetMessageValidation(enabled bool) {
65
62
type MessageType int
66
63
67
64
const (
68
- CALL MessageType = 2
69
- CALL_RESULT MessageType = 3
70
- CALL_ERROR MessageType = 4
65
+ CALL MessageType = 2
66
+ CALL_RESULT MessageType = 3
67
+ CALL_ERROR MessageType = 4
68
+ CALL_RESULT_ERROR MessageType = 5
69
+ SEND MessageType = 6
71
70
)
72
71
73
72
// An OCPP-J message.
@@ -183,12 +182,41 @@ func (callError *CallError) MarshalJSON() ([]byte, error) {
183
182
return ocppMessageToJson (fields )
184
183
}
185
184
185
+ // -------------------- Call --------------------
186
+
187
+ // An OCPP-J SEND message, containing an OCPP Request.
188
+ type Send struct {
189
+ Message `validate:"-"`
190
+ MessageTypeId MessageType `json:"messageTypeId" validate:"required,eq=2"`
191
+ UniqueId string `json:"uniqueId" validate:"required,max=36"`
192
+ Action string `json:"action" validate:"required,max=36"`
193
+ Payload ocpp.Request `json:"payload" validate:"required"`
194
+ }
195
+
196
+ func (call * Send ) GetMessageTypeId () MessageType {
197
+ return call .MessageTypeId
198
+ }
199
+
200
+ func (call * Send ) GetUniqueId () string {
201
+ return call .UniqueId
202
+ }
203
+
204
+ func (call * Send ) MarshalJSON () ([]byte , error ) {
205
+ fields := make ([]interface {}, 4 )
206
+ fields [0 ] = int (call .MessageTypeId )
207
+ fields [1 ] = call .UniqueId
208
+ fields [2 ] = call .Action
209
+ fields [3 ] = call .Payload
210
+ return jsonMarshal (fields )
211
+ }
212
+
186
213
const (
187
214
NotImplemented ocpp.ErrorCode = "NotImplemented" // Requested Action is not known by receiver.
188
215
NotSupported ocpp.ErrorCode = "NotSupported" // Requested Action is recognized but not supported by the receiver.
189
216
InternalError ocpp.ErrorCode = "InternalError" // An internal error occurred and the receiver was not able to process the requested Action successfully.
190
217
MessageTypeNotSupported ocpp.ErrorCode = "MessageTypeNotSupported" // A message with a Message Type Number received that is not supported by this implementation.
191
218
ProtocolError ocpp.ErrorCode = "ProtocolError" // Payload for Action is incomplete.
219
+ RpcFrameworkError ocpp.ErrorCode = "RpcFrameworkError" // Content of the call is not a valid RPC Request, for example: MessageId could not be read.
192
220
SecurityError ocpp.ErrorCode = "SecurityError" // During the processing of Action a security issue occurred preventing receiver from completing the Action successfully.
193
221
PropertyConstraintViolation ocpp.ErrorCode = "PropertyConstraintViolation" // Payload is syntactically correct but at least one field contains an invalid value.
194
222
OccurrenceConstraintViolationV2 ocpp.ErrorCode = "OccurrenceConstraintViolation" // Payload for Action is syntactically correct but at least one of the fields violates occurrence constraints.
@@ -207,7 +235,7 @@ func FormatErrorType(d dialector) ocpp.ErrorCode {
207
235
switch d .Dialect () {
208
236
case ocpp .V16 :
209
237
return FormatViolationV16
210
- case ocpp .V2 :
238
+ case ocpp .V2 , ocpp . V21 :
211
239
return FormatViolationV2
212
240
default :
213
241
panic (fmt .Sprintf ("invalid dialect: %v" , d ))
@@ -218,7 +246,7 @@ func OccurrenceConstraintErrorType(d dialector) ocpp.ErrorCode {
218
246
switch d .Dialect () {
219
247
case ocpp .V16 :
220
248
return OccurrenceConstraintViolationV16
221
- case ocpp .V2 :
249
+ case ocpp .V2 , ocpp . V21 :
222
250
return OccurrenceConstraintViolationV2
223
251
default :
224
252
panic (fmt .Sprintf ("invalid dialect: %v" , d ))
@@ -228,32 +256,17 @@ func OccurrenceConstraintErrorType(d dialector) ocpp.ErrorCode {
228
256
func IsErrorCodeValid (fl validator.FieldLevel ) bool {
229
257
code := ocpp .ErrorCode (fl .Field ().String ())
230
258
switch code {
231
- case NotImplemented , NotSupported , InternalError , MessageTypeNotSupported , ProtocolError , SecurityError , FormatViolationV16 , FormatViolationV2 , PropertyConstraintViolation , OccurrenceConstraintViolationV16 , OccurrenceConstraintViolationV2 , TypeConstraintViolation , GenericError :
259
+ case NotImplemented , NotSupported , InternalError , MessageTypeNotSupported ,
260
+ ProtocolError , SecurityError , FormatViolationV16 , FormatViolationV2 ,
261
+ PropertyConstraintViolation , OccurrenceConstraintViolationV16 , OccurrenceConstraintViolationV2 ,
262
+ TypeConstraintViolation , GenericError :
232
263
return true
233
264
}
234
265
return false
235
266
}
236
267
237
268
// -------------------- Logic --------------------
238
269
239
- // Unmarshals an OCPP-J json object from a byte array.
240
- // Returns the array of elements contained in the message.
241
- func ParseRawJsonMessage (dataJson []byte ) ([]interface {}, error ) {
242
- var arr []interface {}
243
- err := json .Unmarshal (dataJson , & arr )
244
- if err != nil {
245
- return nil , err
246
- }
247
- return arr , nil
248
- }
249
-
250
- // Unmarshals an OCPP-J json object from a JSON string.
251
- // Returns the array of elements contained in the message.
252
- func ParseJsonMessage (dataJson string ) ([]interface {}, error ) {
253
- rawJson := []byte (dataJson )
254
- return ParseRawJsonMessage (rawJson )
255
- }
256
-
257
270
func ocppMessageToJson (message interface {}) ([]byte , error ) {
258
271
jsonData , err := jsonMarshal (message )
259
272
if err != nil {
@@ -317,15 +330,6 @@ func errorFromValidation(d dialector, validationErrors validator.ValidationError
317
330
return ocpp .NewError (GenericError , fmt .Sprintf ("%v" , validationErrors .Error ()), messageId )
318
331
}
319
332
320
- // Marshals data by manipulating EscapeHTML property of encoder
321
- func jsonMarshal (t interface {}) ([]byte , error ) {
322
- buffer := & bytes.Buffer {}
323
- encoder := json .NewEncoder (buffer )
324
- encoder .SetEscapeHTML (EscapeHTML )
325
- err := encoder .Encode (t )
326
- return bytes .TrimRight (buffer .Bytes (), "\n " ), err
327
- }
328
-
329
333
// -------------------- Endpoint --------------------
330
334
331
335
// An OCPP-J endpoint is one of the two entities taking part in the communication.
@@ -372,40 +376,6 @@ func (endpoint *Endpoint) GetProfileForFeature(featureName string) (*ocpp.Profil
372
376
return nil , false
373
377
}
374
378
375
- func parseRawJsonRequest (raw interface {}, requestType reflect.Type ) (ocpp.Request , error ) {
376
- if raw == nil {
377
- raw = & struct {}{}
378
- }
379
- bytes , err := json .Marshal (raw )
380
- if err != nil {
381
- return nil , err
382
- }
383
- request := reflect .New (requestType ).Interface ()
384
- err = json .Unmarshal (bytes , & request )
385
- if err != nil {
386
- return nil , err
387
- }
388
- result := request .(ocpp.Request )
389
- return result , nil
390
- }
391
-
392
- func parseRawJsonConfirmation (raw interface {}, confirmationType reflect.Type ) (ocpp.Response , error ) {
393
- if raw == nil {
394
- raw = & struct {}{}
395
- }
396
- bytes , err := json .Marshal (raw )
397
- if err != nil {
398
- return nil , err
399
- }
400
- confirmation := reflect .New (confirmationType ).Interface ()
401
- err = json .Unmarshal (bytes , & confirmation )
402
- if err != nil {
403
- return nil , err
404
- }
405
- result := confirmation .(ocpp.Response )
406
- return result , nil
407
- }
408
-
409
379
// Parses an OCPP-J message. The function expects an array of elements, as contained in the JSON message.
410
380
//
411
381
// Pending requests are automatically cleared, in case the received message is a CallResponse or CallError.
@@ -414,20 +384,25 @@ func (endpoint *Endpoint) ParseMessage(arr []interface{}, pendingRequestState Cl
414
384
if len (arr ) < 3 {
415
385
return nil , ocpp .NewError (FormatErrorType (endpoint ), "Invalid message. Expected array length >= 3" , "" )
416
386
}
387
+
417
388
rawTypeId , ok := arr [0 ].(float64 )
418
389
if ! ok {
419
390
return nil , ocpp .NewError (FormatErrorType (endpoint ), fmt .Sprintf ("Invalid element %v at 0, expected message type (int)" , arr [0 ]), "" )
420
391
}
392
+
421
393
typeId := MessageType (rawTypeId )
422
394
uniqueId , ok := arr [1 ].(string )
423
395
if ! ok {
424
396
return nil , ocpp .NewError (FormatErrorType (endpoint ), fmt .Sprintf ("Invalid element %v at 1, expected unique ID (string)" , arr [1 ]), uniqueId )
425
397
}
398
+
426
399
if uniqueId == "" {
427
400
return nil , ocpp .NewError (FormatErrorType (endpoint ), "Invalid unique ID, cannot be empty" , uniqueId )
428
401
}
429
- // Parse message
430
- if typeId == CALL {
402
+
403
+ // Parse message base on type
404
+ switch typeId {
405
+ case CALL :
431
406
if len (arr ) != 4 {
432
407
return nil , ocpp .NewError (FormatErrorType (endpoint ), "Invalid Call message. Expected array length 4" , uniqueId )
433
408
}
@@ -455,7 +430,7 @@ func (endpoint *Endpoint) ParseMessage(arr []interface{}, pendingRequestState Cl
455
430
return nil , errorFromValidation (endpoint , err .(validator.ValidationErrors ), uniqueId , action )
456
431
}
457
432
return & call , nil
458
- } else if typeId == CALL_RESULT {
433
+ case CALL_RESULT :
459
434
request , ok := pendingRequestState .GetPendingRequest (uniqueId )
460
435
if ! ok {
461
436
log .Infof ("No previous request %v sent. Discarding response message" , uniqueId )
@@ -476,7 +451,7 @@ func (endpoint *Endpoint) ParseMessage(arr []interface{}, pendingRequestState Cl
476
451
return nil , errorFromValidation (endpoint , err .(validator.ValidationErrors ), uniqueId , request .GetFeatureName ())
477
452
}
478
453
return & callResult , nil
479
- } else if typeId == CALL_ERROR {
454
+ case CALL_ERROR , CALL_RESULT_ERROR :
480
455
_ , ok := pendingRequestState .GetPendingRequest (uniqueId )
481
456
if ! ok {
482
457
log .Infof ("No previous request %v sent. Discarding error message" , uniqueId )
@@ -510,7 +485,16 @@ func (endpoint *Endpoint) ParseMessage(arr []interface{}, pendingRequestState Cl
510
485
return nil , errorFromValidation (endpoint , err .(validator.ValidationErrors ), uniqueId , "" )
511
486
}
512
487
return & callError , nil
513
- } else {
488
+
489
+ case SEND :
490
+ // SEND can be only sent in OCPP 2.1
491
+ if endpoint .Dialect () != ocpp .V21 {
492
+ return nil , ocpp .NewError (MessageTypeNotSupported , "SEND message is not supported in this OCPP version" , uniqueId )
493
+ }
494
+
495
+ // Send does not expect a confirmation, so it is not added to the pending requests.
496
+ return nil , nil
497
+ default :
514
498
return nil , ocpp .NewError (MessageTypeNotSupported , fmt .Sprintf ("Invalid message type ID %v" , typeId ), uniqueId )
515
499
}
516
500
}
0 commit comments