From 858deaa294bcd66ba15945fc11712380e1ec06e2 Mon Sep 17 00:00:00 2001 From: premultiply <4681172+premultiply@users.noreply.github.com> Date: Fri, 19 Sep 2025 23:21:27 +0200 Subject: [PATCH] Ocpp: add optional support for profileKind "relative" (#22139) --- charger/ocpp.go | 35 ++++++++++++++++++++++------------- charger/ocpp_test.go | 8 ++++---- 2 files changed, 26 insertions(+), 17 deletions(-) diff --git a/charger/ocpp.go b/charger/ocpp.go index a8a126170..8130c0e19 100644 --- a/charger/ocpp.go +++ b/charger/ocpp.go @@ -44,8 +44,9 @@ type OCPP struct { enabled bool current float64 - stackLevelZero bool - lp loadpoint.API + stackLevelZero bool + profileKindRelative bool + lp loadpoint.API } const defaultIdTag = "evcc" // RemoteStartTransaction only @@ -71,9 +72,10 @@ func NewOCPPFromConfig(ctx context.Context, other map[string]interface{}) (api.C AutoStart bool // TODO deprecated NoStop bool // TODO deprecated - ForcePowerCtrl bool - StackLevelZero *bool - RemoteStart bool + ForcePowerCtrl bool + StackLevelZero *bool + ProfileKindRelative bool + RemoteStart bool }{ Connector: 1, MeterInterval: 10 * time.Second, @@ -85,11 +87,12 @@ func NewOCPPFromConfig(ctx context.Context, other map[string]interface{}) (api.C } stackLevelZero := cc.StackLevelZero != nil && *cc.StackLevelZero + profileKindRelative := cc.ProfileKindRelative c, err := NewOCPP(ctx, cc.StationId, cc.Connector, cc.IdTag, cc.MeterValues, cc.MeterInterval, - cc.ForcePowerCtrl, stackLevelZero, cc.RemoteStart, + cc.ForcePowerCtrl, stackLevelZero, profileKindRelative, cc.RemoteStart, cc.ConnectTimeout) if err != nil { return c, err @@ -143,7 +146,7 @@ func NewOCPPFromConfig(ctx context.Context, other map[string]interface{}) (api.C func NewOCPP(ctx context.Context, id string, connector int, idTag string, meterValues string, meterInterval time.Duration, - forcePowerCtrl, stackLevelZero, remoteStart bool, + forcePowerCtrl, stackLevelZero, profileKindRelative, remoteStart bool, connectTimeout time.Duration, ) (*OCPP, error) { log := util.NewLogger(fmt.Sprintf("%s-%d", lo.CoalesceOrEmpty(id, "ocpp"), connector)) @@ -184,10 +187,11 @@ func NewOCPP(ctx context.Context, } c := &OCPP{ - log: log, - cp: cp, - conn: conn, - stackLevelZero: stackLevelZero, + log: log, + cp: cp, + conn: conn, + stackLevelZero: stackLevelZero, + profileKindRelative: profileKindRelative, } if cp.HasRemoteTriggerFeature { @@ -328,14 +332,19 @@ func (c *OCPP) createTxDefaultChargingProfile(current float64) *types.ChargingPr res := &types.ChargingProfile{ ChargingProfileId: c.cp.ChargingProfileId, ChargingProfilePurpose: types.ChargingProfilePurposeTxDefaultProfile, - ChargingProfileKind: types.ChargingProfileKindAbsolute, ChargingSchedule: &types.ChargingSchedule{ - StartSchedule: types.NewDateTime(time.Now().Add(-time.Minute)), ChargingRateUnit: c.cp.ChargingRateUnit, ChargingSchedulePeriod: []types.ChargingSchedulePeriod{period}, }, } + if c.profileKindRelative { + res.ChargingProfileKind = types.ChargingProfileKindRelative + } else { + res.ChargingProfileKind = types.ChargingProfileKindAbsolute + res.ChargingSchedule.StartSchedule = types.NewDateTime(time.Now().Add(-time.Minute)) + } + if !c.stackLevelZero { res.StackLevel = c.cp.StackLevel } diff --git a/charger/ocpp_test.go b/charger/ocpp_test.go index 79753515b..9ed429bca 100644 --- a/charger/ocpp_test.go +++ b/charger/ocpp_test.go @@ -113,7 +113,7 @@ func (suite *ocppTestSuite) TestConnect() { suite.Require().True(cp1.IsConnected()) // 1st charge point- local - c1, err := NewOCPP(context.TODO(), "test-1", 1, "", "", 0, false, false, true, ocppTestConnectTimeout) + c1, err := NewOCPP(context.TODO(), "test-1", 1, "", "", 0, false, false, false, true, ocppTestConnectTimeout) suite.Require().NoError(err) // status and meter values @@ -162,7 +162,7 @@ func (suite *ocppTestSuite) TestConnect() { suite.Require().True(cp2.IsConnected()) // 2nd charge point - local - c2, err := NewOCPP(context.TODO(), "test-2", 1, "", "", 0, false, false, true, ocppTestConnectTimeout) + c2, err := NewOCPP(context.TODO(), "test-2", 1, "", "", 0, false, false, false, true, ocppTestConnectTimeout) suite.Require().NoError(err) { @@ -204,7 +204,7 @@ func (suite *ocppTestSuite) TestAutoStart() { suite.Require().True(cp1.IsConnected()) // 1st charge point- local - c1, err := NewOCPP(context.TODO(), "test-3", 1, "", "", 0, false, false, false, ocppTestConnectTimeout) + c1, err := NewOCPP(context.TODO(), "test-3", 1, "", "", 0, false, false, false, false, ocppTestConnectTimeout) suite.Require().NoError(err) // status and meter values @@ -251,7 +251,7 @@ func (suite *ocppTestSuite) TestTimeout() { }) // 1st charge point- local - _, err := NewOCPP(context.TODO(), "test-4", 1, "", "", 0, false, false, false, ocppTestConnectTimeout) + _, err := NewOCPP(context.TODO(), "test-4", 1, "", "", 0, false, false, false, false, ocppTestConnectTimeout) suite.Require().NoError(err) }