Skip to content

Commit

Permalink
Ocpp: add autostart mode (#14733)
Browse files Browse the repository at this point in the history
  • Loading branch information
andig authored Jul 7, 2024
1 parent 93c8b36 commit 4273966
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 23 deletions.
74 changes: 53 additions & 21 deletions charger/ocpp.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ type OCPP struct {
meterValuesSample string
timeout time.Duration
phaseSwitching bool
autoStart bool
chargingRateUnit types.ChargingRateUnitType
lp loadpoint.API
}
Expand All @@ -53,6 +54,7 @@ func NewOCPPFromConfig(other map[string]interface{}) (api.Charger, error) {
BootNotification *bool
GetConfiguration *bool
ChargingRateUnit string
AutoStart bool
}{
Connector: 1,
IdTag: defaultIdTag,
Expand All @@ -70,7 +72,7 @@ func NewOCPPFromConfig(other map[string]interface{}) (api.Charger, error) {

c, err := NewOCPP(cc.StationId, cc.Connector, cc.IdTag,
cc.MeterValues, cc.MeterInterval,
boot, noConfig,
boot, noConfig, cc.AutoStart,
cc.ConnectTimeout, cc.Timeout, cc.ChargingRateUnit)
if err != nil {
return c, err
Expand Down Expand Up @@ -104,7 +106,7 @@ func NewOCPPFromConfig(other map[string]interface{}) (api.Charger, error) {
// NewOCPP creates OCPP charger
func NewOCPP(id string, connector int, idtag string,
meterValues string, meterInterval time.Duration,
boot, noConfig bool,
boot, noConfig, autoStart bool,
connectTimeout, timeout time.Duration,
chargingRateUnit string,
) (*OCPP, error) {
Expand Down Expand Up @@ -132,10 +134,11 @@ func NewOCPP(id string, connector int, idtag string,
}

c := &OCPP{
log: log,
conn: conn,
idtag: idtag,
timeout: timeout,
log: log,
conn: conn,
idtag: idtag,
autoStart: autoStart,
timeout: timeout,
}

c.log.DEBUG.Printf("waiting for chargepoint: %v", connectTimeout)
Expand Down Expand Up @@ -287,6 +290,13 @@ func (c *OCPP) hasMeasurement(val types.Measurand) bool {
return slices.Contains(strings.Split(c.meterValuesSample, ","), string(val))
}

func (c *OCPP) effectiveIdTag() string {
if idtag := c.conn.IdTag(); idtag != "" {
return idtag
}
return c.idtag
}

// configure updates CP configuration
func (c *OCPP) configure(key, val string) error {
rc := make(chan error, 1)
Expand Down Expand Up @@ -325,17 +335,40 @@ func (c *OCPP) Enabled() (bool, error) {
return c.enabled, nil
}

// Enable implements the api.Charger interface
func (c *OCPP) Enable(enable bool) (err error) {
rc := make(chan error, 1)
txn, err := c.conn.TransactionID()
func (c *OCPP) Enable(enable bool) error {
var err error

defer func() {
if err == nil {
c.enabled = enable
}
}()
if c.autoStart {
err = c.enableAutostart(enable)
} else {
err = c.enableRemote(enable)
}

if err == nil {
c.enabled = enable
}

return err
}

// enableAutostart enables auto-started session
func (c *OCPP) enableAutostart(enable bool) error {
var current float64
if enable {
current = c.current
}

return c.updatePeriod(current)
}

// enableRemote enables session by using RemoteStart/Stop
func (c *OCPP) enableRemote(enable bool) error {
txn, err := c.conn.TransactionID()
if err != nil {
return err
}

rc := make(chan error, 1)
if enable {
if txn > 0 {
// we have the transaction id, treat as enabled
Expand All @@ -348,7 +381,7 @@ func (c *OCPP) Enable(enable bool) (err error) {
}

rc <- err
}, c.idtag, func(request *core.RemoteStartTransactionRequest) {
}, c.effectiveIdTag(), func(request *core.RemoteStartTransactionRequest) {
connector := c.conn.ID()
request.ConnectorId = &connector
request.ChargingProfile = c.getTxChargingProfile(c.current, 0)
Expand Down Expand Up @@ -490,11 +523,10 @@ func (c *OCPP) phases1p3p(phases int) error {
return c.updatePeriod(c.current)
}

// // Identify implements the api.Identifier interface
// Unless charger uses vehicle ID as idTag in authorize.req it is not possible to implement this in ocpp1.6
// func (c *OCPP) Identify() (string, error) {
// return "", errors.New("not implemented")
// }
// Identify implements the api.Identifier interface
func (c *OCPP) Identify() (string, error) {
return c.conn.IdTag(), nil
}

var _ loadpoint.Controller = (*OCPP)(nil)

Expand Down
7 changes: 7 additions & 0 deletions charger/ocpp/connector.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ type Connector struct {

txnCount int // change initial value to the last known global transaction. Needs persistence
txnId int
idTag string
}

func NewConnector(log *util.Logger, id int, cp *CP, timeout time.Duration) (*Connector, error) {
Expand Down Expand Up @@ -61,6 +62,12 @@ func (conn *Connector) ID() int {
return conn.id
}

func (conn *Connector) IdTag() string {
conn.mu.Lock()
defer conn.mu.Unlock()
return conn.idTag
}

func (conn *Connector) TriggerMessageRequest(feature remotetrigger.MessageTrigger, f ...func(request *remotetrigger.TriggerMessageRequest)) {
Instance().TriggerMessageRequest(conn.cp.ID(), feature, func(request *remotetrigger.TriggerMessageRequest) {
request.ConnectorId = &conn.id
Expand Down
1 change: 1 addition & 0 deletions charger/ocpp/connector_core.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ func (conn *Connector) StartTransaction(request *core.StartTransactionRequest) (

conn.txnCount++
conn.txnId = conn.txnCount
conn.idTag = request.IdTag

res := &core.StartTransactionConfirmation{
IdTagInfo: &types.IdTagInfo{
Expand Down
4 changes: 2 additions & 2 deletions charger/ocpp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ func (suite *ocppTestSuite) TestConnect() {
suite.Require().True(cp1.IsConnected())

// 1st charge point- local
c1, err := NewOCPP("test-1", 1, "", "", 0, false, false, ocppTestConnectTimeout, ocppTestTimeout, "A")
c1, err := NewOCPP("test-1", 1, "", "", 0, false, false, false, ocppTestConnectTimeout, ocppTestTimeout, "A")
suite.Require().NoError(err)

// status and meter values
Expand Down Expand Up @@ -158,7 +158,7 @@ func (suite *ocppTestSuite) TestConnect() {
suite.Require().True(cp2.IsConnected())

// 2nd charge point - local
c2, err := NewOCPP("test-2", 1, "", "", 0, false, false, ocppTestConnectTimeout, ocppTestTimeout, "A")
c2, err := NewOCPP("test-2", 1, "", "", 0, false, false, false, ocppTestConnectTimeout, ocppTestTimeout, "A")
suite.Require().NoError(err)

{
Expand Down
4 changes: 4 additions & 0 deletions templates/definition/charger/ocpp.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ requirements:
* Local network connection
params:
- preset: ocpp
- name: autostart
advanced: true
type: bool
- name: getconfiguration
advanced: true
type: bool
Expand Down Expand Up @@ -78,6 +81,7 @@ params:
en: Unit for setting ChargingProfile values ("W" or "A")
render: |
{{ include "ocpp" . }}
autostart: {{ .autostart }}
{{- if ne .getconfiguration "true" }}
getconfiguration: {{ .getconfiguration }}
{{- end }}
Expand Down

0 comments on commit 4273966

Please sign in to comment.