Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 55 additions & 0 deletions cmd/ocpp_v16_profiles.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package cmd

import (
"fmt"
"strings"

"github.com/ChargePi/ocpp-manager/ocpp_v16"
"github.com/lorenzodonini/ocpp-go/ocpp1.6/core"
"github.com/lorenzodonini/ocpp-go/ocpp1.6/localauth"
)

var supportedOcppV16ConfigurationProfiles = []string{
core.ProfileName,
localauth.ProfileName,
}

func newDefaultOcppV16Configuration() (*ocpp_v16.Config, error) {
cfg, err := ocpp_v16.DefaultConfigurationFromProfiles(supportedOcppV16ConfigurationProfiles...)
if err != nil {
return nil, err
}

upsertOcppV16ConfigKey(cfg, ocpp_v16.SupportedFeatureProfiles, strings.Join(supportedOcppV16Profiles, ", "), true)
upsertOcppV16ConfigKey(cfg, ocpp_v16.AuthorizationCacheEnabled, "true", false)
upsertOcppV16ConfigKey(cfg, ocpp_v16.ReserveConnectorZeroSupported, "false", true)
upsertOcppV16ConfigKey(cfg, ocpp_v16.LightIntensity, "100", false)

return cfg, nil
}

func upsertOcppV16ConfigKey(cfg *ocpp_v16.Config, key ocpp_v16.Key, value string, readonly bool) {
for i := range cfg.Keys {
if cfg.Keys[i].Key == key.String() {
cfg.Keys[i].Readonly = readonly
cfg.Keys[i].Value = &value
return
}
}

cfg.Keys = append(cfg.Keys, core.ConfigurationKey{
Key: key.String(),
Readonly: readonly,
Value: &value,
})
}

func getOcppV16ConfigValue(cfg *ocpp_v16.Config, key ocpp_v16.Key) (*string, error) {
for _, item := range cfg.Keys {
if item.Key == key.String() {
return item.Value, nil
}
}

return nil, fmt.Errorf("missing OCPP 1.6 configuration key %s", key)
}
46 changes: 46 additions & 0 deletions cmd/ocpp_v16_profiles_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package cmd

import (
"strings"
"testing"

"github.com/ChargePi/ocpp-manager/ocpp_v16"
)

func TestNewDefaultOcppV16Configuration(t *testing.T) {
cfg, err := newDefaultOcppV16Configuration()
if err != nil {
t.Fatalf("newDefaultOcppV16Configuration returned error: %v", err)
}

profiles, err := getOcppV16ConfigValue(cfg, ocpp_v16.SupportedFeatureProfiles)
if err != nil {
t.Fatal(err)
}
if profiles == nil {
t.Fatal("SupportedFeatureProfiles value is nil")
}

expectedProfiles := strings.Join(supportedOcppV16Profiles, ", ")
if *profiles != expectedProfiles {
t.Fatalf("SupportedFeatureProfiles = %q, want %q", *profiles, expectedProfiles)
}

reserveConnectorZeroSupported, err := getOcppV16ConfigValue(cfg, ocpp_v16.ReserveConnectorZeroSupported)
if err != nil {
t.Fatal(err)
}
if reserveConnectorZeroSupported == nil || *reserveConnectorZeroSupported != "false" {
t.Fatalf("ReserveConnectorZeroSupported = %v, want false", reserveConnectorZeroSupported)
}

for _, key := range []ocpp_v16.Key{ocpp_v16.AuthorizationCacheEnabled, ocpp_v16.LightIntensity} {
if _, err := getOcppV16ConfigValue(cfg, key); err != nil {
t.Fatal(err)
}
}

if _, err := ocpp_v16.NewV16ConfigurationManager(*cfg, supportedOcppV16ConfigurationProfiles...); err != nil {
t.Fatalf("NewV16ConfigurationManager returned error: %v", err)
}
}
4 changes: 2 additions & 2 deletions cmd/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,12 +69,12 @@ func runCommand() *cobra.Command {
protocolVersion = connectionSettings.ProtocolVersion
)

cfg, err := ocpp_v16.DefaultConfigurationFromProfiles(supportedOcppV16Profiles...)
cfg, err := newDefaultOcppV16Configuration()
if err != nil {
logger.With(zap.Error(err)).Fatal("Cannot create OCPP configuration")
}

ocppVariableManager, err := ocpp_v16.NewV16ConfigurationManager(*cfg, supportedOcppV16Profiles...)
ocppVariableManager, err := ocpp_v16.NewV16ConfigurationManager(*cfg, supportedOcppV16ConfigurationProfiles...)
if err != nil {
logger.With(zap.Error(err)).Fatal("Cannot create OCPP variable manager")
}
Expand Down
4 changes: 3 additions & 1 deletion internal/chargepoint/v16/charge_point.go
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,8 @@ func (cp *ChargePoint) setProfilesFromConfig() error {

for _, profile := range strings.Split(*profiles, ", ") {
switch profile {
case core.ProfileName:
logger.Debug("Core handler already configured")
case reservation.ProfileName:
cp.chargePoint.SetReservationHandler(cp)
logger.Debug("Setting reservation handler")
Expand All @@ -386,7 +388,7 @@ func (cp *ChargePoint) setProfilesFromConfig() error {
logger.Debug("Setting local auth handler")
cp.chargePoint.SetLocalAuthListHandler(cp)

err = cp.setupCoreConfigurationValidation()
err = cp.setupLocalAuthListConfigurationValidation()
case remotetrigger.ProfileName:
logger.Debug("Setting remote trigger handler")
cp.chargePoint.SetRemoteTriggerHandler(cp)
Expand Down
59 changes: 59 additions & 0 deletions internal/chargepoint/v16/profiles_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package v16

import (
"strings"
"testing"

mock_manager "github.com/ChargePi/ChargePi-go/gen/mocks/pkg/configuration/manager"
"github.com/ChargePi/ocpp-manager/ocpp_v16"
ocpp16 "github.com/lorenzodonini/ocpp-go/ocpp1.6"
"github.com/lorenzodonini/ocpp-go/ocpp1.6/core"
"github.com/lorenzodonini/ocpp-go/ocpp1.6/localauth"
"github.com/lorenzodonini/ocpp-go/ocpp1.6/remotetrigger"
"github.com/lorenzodonini/ocpp-go/ocpp1.6/reservation"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
"go.uber.org/zap/zaptest"
)

func TestSetProfilesFromConfigAcceptsRuntimeOnlyProfiles(t *testing.T) {
profiles := strings.Join([]string{
core.ProfileName,
reservation.ProfileName,
remotetrigger.ProfileName,
localauth.ProfileName,
}, ", ")
settingsManager := mock_manager.NewMockManager(t)

settingsManager.EXPECT().OnUpdateKey(ocpp_v16.AuthorizationCacheEnabled, mock.Anything).Return(nil)
settingsManager.EXPECT().OnUpdateKey(ocpp_v16.HeartbeatInterval, mock.Anything).Return(nil)
settingsManager.EXPECT().OnUpdateKey(ocpp_v16.LightIntensity, mock.Anything).Return(nil)
settingsManager.EXPECT().GetConfigurationValue(ocpp_v16.SupportedFeatureProfiles).Return(&profiles, nil)
settingsManager.EXPECT().OnUpdateKey(ocpp_v16.LocalAuthListMaxLength, mock.Anything).Return(nil)

cp := &ChargePoint{
chargePoint: ocpp16.NewChargePoint("test-charge-point", nil, nil),
settingsManager: settingsManager,
logger: zaptest.NewLogger(t),
}

require.NoError(t, cp.setProfilesFromConfig())
}

func TestSetProfilesFromConfigRejectsUnknownProfile(t *testing.T) {
profiles := strings.Join([]string{core.ProfileName, "UnknownProfile"}, ", ")
settingsManager := mock_manager.NewMockManager(t)

settingsManager.EXPECT().OnUpdateKey(ocpp_v16.AuthorizationCacheEnabled, mock.Anything).Return(nil)
settingsManager.EXPECT().OnUpdateKey(ocpp_v16.HeartbeatInterval, mock.Anything).Return(nil)
settingsManager.EXPECT().OnUpdateKey(ocpp_v16.LightIntensity, mock.Anything).Return(nil)
settingsManager.EXPECT().GetConfigurationValue(ocpp_v16.SupportedFeatureProfiles).Return(&profiles, nil)

cp := &ChargePoint{
chargePoint: ocpp16.NewChargePoint("test-charge-point", nil, nil),
settingsManager: settingsManager,
logger: zaptest.NewLogger(t),
}

require.Error(t, cp.setProfilesFromConfig())
}
7 changes: 0 additions & 7 deletions internal/chargepoint/v16/settings.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,13 +130,6 @@ func (cp *ChargePoint) setupSmartChargingConfigurationValidation() error {

// setupCoreConfigurationValidation sets up the configuration validation for custom variables.
func (cp *ChargePoint) setupCustomConfigurationValidation() error {
err := cp.settingsManager.OnUpdateKey("", func(value *string) error {
return nil
})
if err != nil {
return err
}

return nil
}

Expand Down
Loading