22package ocppj
33
44import (
5- "bytes"
65 "encoding/json"
76 "fmt"
8- "math/rand"
9- "reflect"
10-
117 "github.com/lorenzodonini/ocpp-go/logging"
8+ "math/rand"
129
1310 "gopkg.in/go-playground/validator.v9"
1411
@@ -65,9 +62,11 @@ func SetMessageValidation(enabled bool) {
6562type MessageType int
6663
6764const (
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
7170)
7271
7372// An OCPP-J message.
@@ -183,12 +182,41 @@ func (callError *CallError) MarshalJSON() ([]byte, error) {
183182 return ocppMessageToJson (fields )
184183}
185184
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+
186213const (
187214 NotImplemented ocpp.ErrorCode = "NotImplemented" // Requested Action is not known by receiver.
188215 NotSupported ocpp.ErrorCode = "NotSupported" // Requested Action is recognized but not supported by the receiver.
189216 InternalError ocpp.ErrorCode = "InternalError" // An internal error occurred and the receiver was not able to process the requested Action successfully.
190217 MessageTypeNotSupported ocpp.ErrorCode = "MessageTypeNotSupported" // A message with a Message Type Number received that is not supported by this implementation.
191218 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.
192220 SecurityError ocpp.ErrorCode = "SecurityError" // During the processing of Action a security issue occurred preventing receiver from completing the Action successfully.
193221 PropertyConstraintViolation ocpp.ErrorCode = "PropertyConstraintViolation" // Payload is syntactically correct but at least one field contains an invalid value.
194222 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 {
207235 switch d .Dialect () {
208236 case ocpp .V16 :
209237 return FormatViolationV16
210- case ocpp .V2 :
238+ case ocpp .V2 , ocpp . V21 :
211239 return FormatViolationV2
212240 default :
213241 panic (fmt .Sprintf ("invalid dialect: %v" , d ))
@@ -218,7 +246,7 @@ func OccurrenceConstraintErrorType(d dialector) ocpp.ErrorCode {
218246 switch d .Dialect () {
219247 case ocpp .V16 :
220248 return OccurrenceConstraintViolationV16
221- case ocpp .V2 :
249+ case ocpp .V2 , ocpp . V21 :
222250 return OccurrenceConstraintViolationV2
223251 default :
224252 panic (fmt .Sprintf ("invalid dialect: %v" , d ))
@@ -228,32 +256,17 @@ func OccurrenceConstraintErrorType(d dialector) ocpp.ErrorCode {
228256func IsErrorCodeValid (fl validator.FieldLevel ) bool {
229257 code := ocpp .ErrorCode (fl .Field ().String ())
230258 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 :
232263 return true
233264 }
234265 return false
235266}
236267
237268// -------------------- Logic --------------------
238269
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-
257270func ocppMessageToJson (message interface {}) ([]byte , error ) {
258271 jsonData , err := jsonMarshal (message )
259272 if err != nil {
@@ -317,15 +330,6 @@ func errorFromValidation(d dialector, validationErrors validator.ValidationError
317330 return ocpp .NewError (GenericError , fmt .Sprintf ("%v" , validationErrors .Error ()), messageId )
318331}
319332
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-
329333// -------------------- Endpoint --------------------
330334
331335// 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
372376 return nil , false
373377}
374378
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-
409379// Parses an OCPP-J message. The function expects an array of elements, as contained in the JSON message.
410380//
411381// 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
414384 if len (arr ) < 3 {
415385 return nil , ocpp .NewError (FormatErrorType (endpoint ), "Invalid message. Expected array length >= 3" , "" )
416386 }
387+
417388 rawTypeId , ok := arr [0 ].(float64 )
418389 if ! ok {
419390 return nil , ocpp .NewError (FormatErrorType (endpoint ), fmt .Sprintf ("Invalid element %v at 0, expected message type (int)" , arr [0 ]), "" )
420391 }
392+
421393 typeId := MessageType (rawTypeId )
422394 uniqueId , ok := arr [1 ].(string )
423395 if ! ok {
424396 return nil , ocpp .NewError (FormatErrorType (endpoint ), fmt .Sprintf ("Invalid element %v at 1, expected unique ID (string)" , arr [1 ]), uniqueId )
425397 }
398+
426399 if uniqueId == "" {
427400 return nil , ocpp .NewError (FormatErrorType (endpoint ), "Invalid unique ID, cannot be empty" , uniqueId )
428401 }
429- // Parse message
430- if typeId == CALL {
402+
403+ // Parse message base on type
404+ switch typeId {
405+ case CALL :
431406 if len (arr ) != 4 {
432407 return nil , ocpp .NewError (FormatErrorType (endpoint ), "Invalid Call message. Expected array length 4" , uniqueId )
433408 }
@@ -455,7 +430,7 @@ func (endpoint *Endpoint) ParseMessage(arr []interface{}, pendingRequestState Cl
455430 return nil , errorFromValidation (endpoint , err .(validator.ValidationErrors ), uniqueId , action )
456431 }
457432 return & call , nil
458- } else if typeId == CALL_RESULT {
433+ case CALL_RESULT :
459434 request , ok := pendingRequestState .GetPendingRequest (uniqueId )
460435 if ! ok {
461436 log .Infof ("No previous request %v sent. Discarding response message" , uniqueId )
@@ -476,7 +451,7 @@ func (endpoint *Endpoint) ParseMessage(arr []interface{}, pendingRequestState Cl
476451 return nil , errorFromValidation (endpoint , err .(validator.ValidationErrors ), uniqueId , request .GetFeatureName ())
477452 }
478453 return & callResult , nil
479- } else if typeId == CALL_ERROR {
454+ case CALL_ERROR , CALL_RESULT_ERROR :
480455 _ , ok := pendingRequestState .GetPendingRequest (uniqueId )
481456 if ! ok {
482457 log .Infof ("No previous request %v sent. Discarding error message" , uniqueId )
@@ -510,7 +485,16 @@ func (endpoint *Endpoint) ParseMessage(arr []interface{}, pendingRequestState Cl
510485 return nil , errorFromValidation (endpoint , err .(validator.ValidationErrors ), uniqueId , "" )
511486 }
512487 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 :
514498 return nil , ocpp .NewError (MessageTypeNotSupported , fmt .Sprintf ("Invalid message type ID %v" , typeId ), uniqueId )
515499 }
516500}
0 commit comments