Skip to content

Commit

Permalink
Merge pull request #18 from grid-x/sync-fork
Browse files Browse the repository at this point in the history
Sync fork
  • Loading branch information
hnicolaysen authored Mar 5, 2024
2 parents d4afed5 + c686786 commit 607bfeb
Show file tree
Hide file tree
Showing 66 changed files with 1,520 additions and 349 deletions.
2 changes: 1 addition & 1 deletion example/1.6/cp/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,7 @@ func (handler *ChargePointHandler) OnCancelReservation(request *reservation.Canc
func (handler *ChargePointHandler) OnSetChargingProfile(request *smartcharging.SetChargingProfileRequest) (confirmation *smartcharging.SetChargingProfileConfirmation, err error) {
//TODO: handle logic
logDefault(request.GetFeatureName()).Warn("no set charging profile logic implemented yet")
return smartcharging.NewSetChargingProfileConfirmation(smartcharging.ChargingProfileStatusNotImplemented), nil
return smartcharging.NewSetChargingProfileConfirmation(smartcharging.ChargingProfileStatusNotSupported), nil
}

func (handler *ChargePointHandler) OnClearChargingProfile(request *smartcharging.ClearChargingProfileRequest) (confirmation *smartcharging.ClearChargingProfileConfirmation, err error) {
Expand Down
2 changes: 1 addition & 1 deletion example/2.0.1/csms/csms_sim.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ func exampleRoutine(chargingStationID string, handler *CSMSHandler) {
time.Sleep(2 * time.Second)
// Reserve a connector
reservationID := 42
clientIDTokenType := types.IdTokenTypeKeyCode
clientIDTokenType := types.IdToken{IdToken: "1234", Type: types.IdTokenTypeKeyCode}
clientIdTag := "l33t"
connectorID := 1
expiryDate := types.NewDateTime(time.Now().Add(1 * time.Hour))
Expand Down
32 changes: 25 additions & 7 deletions ocpp1.6/central_system.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package ocpp16

import (
"fmt"
"reflect"

"github.com/lorenzodonini/ocpp-go/internal/callbackqueue"
"github.com/lorenzodonini/ocpp-go/ocpp"
Expand Down Expand Up @@ -360,6 +361,10 @@ func (cs *centralSystem) SetSmartChargingHandler(handler smartcharging.CentralSy
cs.smartChargingHandler = handler
}

func (cs *centralSystem) SetNewChargingStationValidationHandler(handler ws.CheckClientHandler) {
cs.server.SetNewClientValidationHandler(handler)
}

func (cs *centralSystem) SetNewChargePointHandler(handler ChargePointConnectionHandler) {
cs.server.SetNewClientHandler(func(chargePoint ws.Channel) {
handler(chargePoint)
Expand Down Expand Up @@ -399,30 +404,40 @@ func (cs *centralSystem) SendRequestAsync(clientId string, request ocpp.Request,
}

func (cs *centralSystem) Start(listenPort int, listenPath string) {
// Overriding some protocol-specific values in the lower layers globally
ocppj.FormationViolation = ocppj.FormatViolationV16
// Start server
cs.server.Start(listenPort, listenPath)
}

func (cs *centralSystem) sendResponse(chargePointId string, confirmation ocpp.Response, err error, requestId string) {
// send error response
if err != nil {
cs.error(fmt.Errorf("error handling request: %w", err))
err := cs.server.SendError(chargePointId, requestId, ocppj.InternalError, "Error handling request", nil)
// Send error response
err = cs.server.SendError(chargePointId, requestId, ocppj.InternalError, err.Error(), nil)
if err != nil {
// Error while sending an error. Will attempt to send a default error instead
cs.server.HandleFailedResponseError(chargePointId, requestId, err, "")
// Notify client implementation
err = fmt.Errorf("error replying cp %s to request %s with 'internal error': %w", chargePointId, requestId, err)
cs.error(err)
}
return
}

if confirmation == nil {
if confirmation == nil || reflect.ValueOf(confirmation).IsNil() {
err = fmt.Errorf("empty confirmation to %s for request %s", chargePointId, requestId)
// Sending a dummy error to server instead, then notify client implementation
_ = cs.server.SendError(chargePointId, requestId, ocppj.GenericError, err.Error(), nil)
cs.error(err)
return
}

// send confirmation response
err = cs.server.SendResponse(chargePointId, requestId, confirmation)
if err != nil {
// Error while sending an error. Will attempt to send a default error instead
cs.server.HandleFailedResponseError(chargePointId, requestId, err, confirmation.GetFeatureName())
// Notify client implementation
err = fmt.Errorf("error replying cp %s to request %s: %w", chargePointId, requestId, err)
cs.error(err)
}
Expand Down Expand Up @@ -519,7 +534,8 @@ func (cs *centralSystem) handleIncomingRequest(chargePoint ChargePointConnection

func (cs *centralSystem) handleIncomingConfirmation(chargePoint ChargePointConnection, confirmation ocpp.Response, requestId string) {
if callback, ok := cs.callbackQueue.Dequeue(chargePoint.ID()); ok {
callback(confirmation, nil)
// Execute in separate goroutine, so the caller goroutine is available
go callback(confirmation, nil)
} else {
err := fmt.Errorf("no handler available for call of type %v from client %s for request %s", confirmation.GetFeatureName(), chargePoint.ID(), requestId)
cs.error(err)
Expand All @@ -528,7 +544,8 @@ func (cs *centralSystem) handleIncomingConfirmation(chargePoint ChargePointConne

func (cs *centralSystem) handleIncomingError(chargePoint ChargePointConnection, err *ocpp.Error, details interface{}) {
if callback, ok := cs.callbackQueue.Dequeue(chargePoint.ID()); ok {
callback(nil, err)
// Execute in separate goroutine, so the caller goroutine is available
go callback(nil, err)
} else {
err := fmt.Errorf("no handler available for call error %w from client %s", err, chargePoint.ID())
cs.error(err)
Expand All @@ -537,7 +554,8 @@ func (cs *centralSystem) handleIncomingError(chargePoint ChargePointConnection,

func (cs *centralSystem) handleCanceledRequest(chargePointID string, request ocpp.Request, err *ocpp.Error) {
if callback, ok := cs.callbackQueue.Dequeue(chargePointID); ok {
callback(nil, err)
// Execute in separate goroutine, so the caller goroutine is available
go callback(nil, err)
} else {
err := fmt.Errorf("no handler available for canceled request %s for client %s: %w",
request.GetFeatureName(), chargePointID, err)
Expand Down
29 changes: 22 additions & 7 deletions ocpp1.6/charge_point.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package ocpp16

import (
"fmt"
"reflect"

"github.com/lorenzodonini/ocpp-go/internal/callbackqueue"
"github.com/lorenzodonini/ocpp-go/ocpp"
Expand Down Expand Up @@ -295,35 +296,45 @@ func (cp *chargePoint) clearCallbacks(invokeCallback bool) {
}

func (cp *chargePoint) sendResponse(confirmation ocpp.Response, err error, requestId string) {
// send error response
if err != nil {
err = cp.client.SendError(requestId, ocppj.ProtocolError, err.Error(), nil)
// Send error response
err = cp.client.SendError(requestId, ocppj.InternalError, err.Error(), nil)
if err != nil {
err = fmt.Errorf("replying cs to request %s with 'protocol error': %w", requestId, err)
// Error while sending an error. Will attempt to send a default error instead
cp.client.HandleFailedResponseError(requestId, err, "")
// Notify client implementation
err = fmt.Errorf("replying to request %s with 'internal error' failed: %w", requestId, err)
cp.error(err)
}

return
}

if confirmation == nil {
if confirmation == nil || reflect.ValueOf(confirmation).IsNil() {
err = fmt.Errorf("empty confirmation to request %s", requestId)
// Sending a dummy error to server instead, then notify client implementation
_ = cp.client.SendError(requestId, ocppj.GenericError, err.Error(), nil)
cp.error(err)
return
}

// send confirmation response
err = cp.client.SendResponse(requestId, confirmation)
if err != nil {
err = fmt.Errorf("replying cs to request %s: %w", requestId, err)
// Error while sending an error. Will attempt to send a default error instead
cp.client.HandleFailedResponseError(requestId, err, confirmation.GetFeatureName())
// Notify client implementation
err = fmt.Errorf("failed responding to request %s: %w", requestId, err)
cp.error(err)
}
}

func (cp *chargePoint) Start(centralSystemUrl string) error {
// Overriding some protocol-specific values in the lower layers globally
ocppj.FormationViolation = ocppj.FormatViolationV16
// Start client
cp.stopC = make(chan struct{}, 1)
// Async response handler receives incoming responses/errors and triggers callbacks
err := cp.client.Start(centralSystemUrl)
// Async response handler receives incoming responses/errors and triggers callbacks
if err == nil {
go cp.asyncCallbackHandler()
}
Expand All @@ -340,6 +351,10 @@ func (cp *chargePoint) Stop() {
}
}

func (cp *chargePoint) IsConnected() bool {
return cp.client.IsConnected()
}

func (cp *chargePoint) notImplementedError(requestId string, action string) {
err := cp.client.SendError(requestId, ocppj.NotImplemented, fmt.Sprintf("no handler for action %v implemented", action), nil)
if err != nil {
Expand Down
2 changes: 1 addition & 1 deletion ocpp1.6/core/get_configuration.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ const GetConfigurationFeatureName = "GetConfiguration"
type ConfigurationKey struct {
Key string `json:"key" validate:"required,max=50"`
Readonly bool `json:"readonly"`
Value *string `json:"value,omitempty" validate:"max=500"`
Value *string `json:"value,omitempty" validate:"omitempty,max=500"`
}

// The field definition of the GetConfiguration request payload sent by the Central System to the Charge Point.
Expand Down
5 changes: 3 additions & 2 deletions ocpp1.6/core/remote_start_transaction.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
package core

import (
"github.com/lorenzodonini/ocpp-go/ocpp1.6/types"
"reflect"

"github.com/lorenzodonini/ocpp-go/ocpp1.6/types"
)

// -------------------- Remote Start Transaction (CS -> CP) --------------------
Expand All @@ -19,7 +20,7 @@ type RemoteStartTransactionRequest struct {
// This field definition of the RemoteStartTransaction confirmation payload, sent by the Charge Point to the Central System in response to a RemoteStartTransactionRequest.
// In case the request was invalid, or couldn't be processed, an error will be sent instead.
type RemoteStartTransactionConfirmation struct {
Status types.RemoteStartStopStatus `json:"status" validate:"required,remoteStartStopStatus"`
Status types.RemoteStartStopStatus `json:"status" validate:"required,remoteStartStopStatus16"`
}

// Central System can request a Charge Point to start a transaction by sending a RemoteStartTransactionRequest.
Expand Down
5 changes: 3 additions & 2 deletions ocpp1.6/core/remote_stop_transaction.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
package core

import (
"github.com/lorenzodonini/ocpp-go/ocpp1.6/types"
"reflect"

"github.com/lorenzodonini/ocpp-go/ocpp1.6/types"
)

// -------------------- Remote Stop Transaction (CS -> CP) --------------------
Expand All @@ -17,7 +18,7 @@ type RemoteStopTransactionRequest struct {
// This field definition of the RemoteStopTransaction confirmation payload, sent by the Charge Point to the Central System in response to a RemoteStopTransactionRequest.
// In case the request was invalid, or couldn't be processed, an error will be sent instead.
type RemoteStopTransactionConfirmation struct {
Status types.RemoteStartStopStatus `json:"status" validate:"required,remoteStartStopStatus"`
Status types.RemoteStartStopStatus `json:"status" validate:"required,remoteStartStopStatus16"`
}

// Central System can request a Charge Point to stop a transaction by sending a RemoteStopTransactionRequest to Charge Point with the identifier of the transaction.
Expand Down
15 changes: 8 additions & 7 deletions ocpp1.6/core/reset.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
package core

import (
"reflect"

"github.com/lorenzodonini/ocpp-go/ocpp1.6/types"
"gopkg.in/go-playground/validator.v9"
"reflect"
)

// -------------------- Reset (CS -> CP) --------------------
Expand Down Expand Up @@ -45,13 +46,13 @@ func isValidResetStatus(fl validator.FieldLevel) bool {

// The field definition of the Reset request payload sent by the Central System to the Charge Point.
type ResetRequest struct {
Type ResetType `json:"type" validate:"required,resetType"`
Type ResetType `json:"type" validate:"required,resetType16"`
}

// This field definition of the Reset confirmation payload, sent by the Charge Point to the Central System in response to a ResetRequest.
// In case the request was invalid, or couldn't be processed, an error will be sent instead.
type ResetConfirmation struct {
Status ResetStatus `json:"status" validate:"required,resetStatus"`
Status ResetStatus `json:"status" validate:"required,resetStatus16"`
}

// The Central System SHALL send a ResetRequest for requesting a Charge Point to reset itself.
Expand All @@ -62,8 +63,8 @@ type ResetConfirmation struct {
// At receipt of a soft reset, the Charge Point SHALL stop ongoing transactions gracefully and send StopTransactionRequest for every ongoing transaction.
// It should then restart the application software (if possible, otherwise restart the processor/controller).
// At receipt of a hard reset the Charge Point SHALL restart (all) the hardware, it is not required to gracefully stop ongoing transaction.
//If possible the Charge Point sends a StopTransactionRequest for previously ongoing transactions after having restarted and having been accepted by the Central System via a BootNotificationConfirmation.
//This is a last resort solution for a not correctly functioning Charge Points, by sending a "hard" reset, (queued) information might get lost.
// If possible the Charge Point sends a StopTransactionRequest for previously ongoing transactions after having restarted and having been accepted by the Central System via a BootNotificationConfirmation.
// This is a last resort solution for a not correctly functioning Charge Points, by sending a "hard" reset, (queued) information might get lost.
type ResetFeature struct{}

func (f ResetFeature) GetFeatureName() string {
Expand Down Expand Up @@ -97,6 +98,6 @@ func NewResetConfirmation(status ResetStatus) *ResetConfirmation {
}

func init() {
_ = types.Validate.RegisterValidation("resetType", isValidResetType)
_ = types.Validate.RegisterValidation("resetStatus", isValidResetStatus)
_ = types.Validate.RegisterValidation("resetType16", isValidResetType)
_ = types.Validate.RegisterValidation("resetStatus16", isValidResetStatus)
}
7 changes: 4 additions & 3 deletions ocpp1.6/smartcharging/clear_charging_profile.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
package smartcharging

import (
"reflect"

"github.com/lorenzodonini/ocpp-go/ocpp1.6/types"
"gopkg.in/go-playground/validator.v9"
"reflect"
)

// -------------------- Clear Charging Profile (CS -> CP) --------------------
Expand Down Expand Up @@ -32,14 +33,14 @@ func isValidClearChargingProfileStatus(fl validator.FieldLevel) bool {
type ClearChargingProfileRequest struct {
Id *int `json:"id,omitempty" validate:"omitempty"`
ConnectorId *int `json:"connectorId,omitempty" validate:"omitempty,gte=0"`
ChargingProfilePurpose types.ChargingProfilePurposeType `json:"chargingProfilePurpose,omitempty" validate:"omitempty,chargingProfilePurpose"`
ChargingProfilePurpose types.ChargingProfilePurposeType `json:"chargingProfilePurpose,omitempty" validate:"omitempty,chargingProfilePurpose16"`
StackLevel *int `json:"stackLevel,omitempty" validate:"omitempty,gte=0"`
}

// This field definition of the ClearChargingProfile confirmation payload, sent by the Charge Point to the Central System in response to a ClearChargingProfileRequest.
// In case the request was invalid, or couldn't be processed, an error will be sent instead.
type ClearChargingProfileConfirmation struct {
Status ClearChargingProfileStatus `json:"status" validate:"required,chargingProfileStatus"`
Status ClearChargingProfileStatus `json:"status" validate:"required,clearChargingProfileStatus"`
}

// If the Central System wishes to clear some or all of the charging profiles that were previously sent the Charge Point,
Expand Down
5 changes: 3 additions & 2 deletions ocpp1.6/smartcharging/get_composite_schedule.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
package smartcharging

import (
"reflect"

"github.com/lorenzodonini/ocpp-go/ocpp1.6/types"
"gopkg.in/go-playground/validator.v9"
"reflect"
)

// -------------------- Get Composite Schedule (CS -> CP) --------------------
Expand Down Expand Up @@ -32,7 +33,7 @@ func isValidGetCompositeScheduleStatus(fl validator.FieldLevel) bool {
type GetCompositeScheduleRequest struct {
ConnectorId int `json:"connectorId" validate:"gte=0"`
Duration int `json:"duration" validate:"gte=0"`
ChargingRateUnit types.ChargingRateUnitType `json:"chargingRateUnit,omitempty" validate:"omitempty,chargingRateUnit"`
ChargingRateUnit types.ChargingRateUnitType `json:"chargingRateUnit,omitempty" validate:"omitempty,chargingRateUnit16"`
}

// This field definition of the GetCompositeSchedule confirmation payload, sent by the Charge Point to the Central System in response to a GetCompositeScheduleRequest.
Expand Down
8 changes: 4 additions & 4 deletions ocpp1.6/smartcharging/set_charging_profile.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,15 @@ const SetChargingProfileFeatureName = "SetChargingProfile"
type ChargingProfileStatus string

const (
ChargingProfileStatusAccepted ChargingProfileStatus = "Accepted"
ChargingProfileStatusRejected ChargingProfileStatus = "Rejected"
ChargingProfileStatusNotImplemented ChargingProfileStatus = "NotImplemented"
ChargingProfileStatusAccepted ChargingProfileStatus = "Accepted"
ChargingProfileStatusRejected ChargingProfileStatus = "Rejected"
ChargingProfileStatusNotSupported ChargingProfileStatus = "NotSupported"
)

func isValidChargingProfileStatus(fl validator.FieldLevel) bool {
status := ChargingProfileStatus(fl.Field().String())
switch status {
case ChargingProfileStatusAccepted, ChargingProfileStatusRejected, ChargingProfileStatusNotImplemented:
case ChargingProfileStatusAccepted, ChargingProfileStatusRejected, ChargingProfileStatusNotSupported:
return true
default:
return false
Expand Down
Loading

0 comments on commit 607bfeb

Please sign in to comment.